Prepration for PPP and 5.16 support

This commit is contained in:
Gerben Jan Dijkman 2022-01-10 13:52:54 +01:00
parent 52a2547796
commit 6da383de61
194 changed files with 12171 additions and 654487 deletions

View File

@ -1,6 +1,3 @@
DIST all-5.12.17.patch 15073524 BLAKE2B bd085b619a3bc1190cbfdc6bfd74cd6606f67f55106f89e0522619aaf69b672d68a7e93d843d7a4680529532e654d71becf4a7378d453fcc72978ee24d415b57 SHA512 e4bae86407767b685b3ec47f383d2db44281fe6a58914e4a117449c2ff96fe3c6341a7b59d1a92790c1565ecc3c14dacbbdc96fbc1b718ec7402c27c2dc37d0d
DIST all-5.15.6.patch 15465054 BLAKE2B e60ee46d00f0d2a82c491431366e96650b08050e64bc5a751961a7f7d465735250bdc2b26832fc1f0a6a21da1d7c5e87d119359a02c9e175201af5750f8e50f4 SHA512 6499b9f8b5575ca3ab21a28ec5a9c9bd0bcecfec54b90cf7dac1f2c9e818f0a5804a7389f37e6220661210f7ecc80da3cfd3b2c218d29c0d10bb9066c68aa802
DIST linux-5.12.tar.xz 118112412 BLAKE2B 842d921b9a73d2aaade763dbd2ec67bdfe0275baa6d628b775f5c87574ad7dc86f0419afcd48c10c1235f4bffa16084243f2cf4556e6afcd391e975fe8ba530b SHA512 be03b6fee1d1ea8087b09874d27c0a602c0b04fd90ad38b975bd2c8455a07e83c29b56814aaf1389e82305fae0e4c2d1701075a7f0a7295dd28149f967ec5b3d
DIST linux-5.15.tar.xz 121913744 BLAKE2B 3921274b23f7938abdf3ed9334534b4581e13d7484303d3a5280eddb038999aaa8b836666a487472d9c4a219af0f06b9fecccaf348fb5510ab8762f4ef4b7e83 SHA512 d25ad40b5bcd6a4c6042fd0fd84e196e7a58024734c3e9a484fd0d5d54a0c1d87db8a3c784eff55e43b6f021709dc685eb0efa18d2aec327e4f88a79f405705a
DIST patch-5.12.17.xz 889940 BLAKE2B 78c10887c9c28261f5a99c3ed19c9390d8af92ee49dd4dd13092493e71c446fa58b9025eecb3ea8f605f1c3644c5ef85a25c056a4fbe143eb91f49eb9b2b866b SHA512 1c42b4efa3d26fb4bdc96c422a32646b2d9018cb84d231ccae4c64e1cdd342ed43828c6da3eb40cbe80550734254b8e824cec98cb1635d47baef75bae37bfd31
DIST patch-5.15.6.xz 430232 BLAKE2B ed3eb640ae8617ae726b9d98f3b17ab1602f733e228970826e4a34cb7e466b61ead5371f51e6bc1fc75bb9e468cfeca66c6bca21731f25b53decc52eb59ecb3e SHA512 926403406c82f4589bb872cb74ff21dc4729184a3dd5293ba0cc201c13a5c3917b231721be551a6f19fb1d93e443b8ebac557df2a9cc265967a693b4031cedb3

View File

@ -1,40 +0,0 @@
From 7045054c96224ead00aae09246f475dfe6202def Mon Sep 17 00:00:00 2001
From: Danct12 <danct12@disroot.org>
Date: Tue, 19 Jan 2021 10:09:01 +0700
Subject: [PATCH] arm64: dts: allwinner: pinephone: stop LEDs on suspend
Signed-off-by: Danct12 <danct12@disroot.org>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
index 02d82980c..00ed866ae 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
@@ -218,14 +218,12 @@
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_BLUE>;
gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
- retain-state-suspended;
};
green {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_GREEN>;
gpios = <&pio 3 18 GPIO_ACTIVE_HIGH>; /* PD18 */
- retain-state-suspended;
};
red {
@@ -233,7 +231,6 @@
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_RED>;
gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
- retain-state-suspended;
};
};
--
2.30.0

View File

@ -0,0 +1,35 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 15 Nov 2021 04:09:50 +0100
Subject: [PATCH 01/36] base: property: Swap order of search for connection to
"devcon, graph"
This avoids confusing error in kernel log, when using devcon matching
in DT. Example:
"OF: graph: no port node found in /i2c@ff3d0000/typec-portc@22"
This suggest there's some error because graph based search failed,
but there is no error, because devcon based matching succeeds.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/base/property.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/property.c b/drivers/base/property.c
index f1f35b4..68cb945 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1261,10 +1261,10 @@ void *fwnode_connection_find_match(struct fwnode_handle *fwnode,
if (!fwnode || !match)
return NULL;
- ret = fwnode_graph_devcon_match(fwnode, con_id, data, match);
+ ret = fwnode_devcon_match(fwnode, con_id, data, match);
if (ret)
return ret;
- return fwnode_devcon_match(fwnode, con_id, data, match);
+ return fwnode_graph_devcon_match(fwnode, con_id, data, match);
}
EXPORT_SYMBOL_GPL(fwnode_connection_find_match);

View File

@ -1,24 +0,0 @@
From 22008251d617054271a65f29178e2df74dd3e33c Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bshah@kde.org>
Date: Fri, 9 Apr 2021 16:22:49 +0530
Subject: [PATCH 1/5] drivers/usb: add reset_resume callback
---
drivers/usb/serial/option.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c6969ca728390..21aeb7dc8f6ee 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -2105,6 +2105,7 @@ static struct usb_serial_driver option_1port_device = {
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
+ .reset_resume = usb_wwan_resume,
#endif
};
--
2.31.1

View File

@ -1,67 +0,0 @@
From 27061f0b322a585c30db111719f89c23c15a88b4 Mon Sep 17 00:00:00 2001
From: Sathish Narasimman <nsathish41@gmail.com>
Date: Thu, 29 Oct 2020 13:18:21 +0530
Subject: Bluetooth: Fix: LL PRivacy BLE device fails to connect
When adding device to white list the device is added to resolving list
also. It has to be added only when HCI_ENABLE_LL_PRIVACY flag is set.
HCI_ENABLE_LL_PRIVACY flag has to be tested before adding/deleting devices
to resolving list. use_ll_privacy macro is used only to check if controller
supports LL_Privacy.
https://bugzilla.kernel.org/show_bug.cgi?id=209745
Fixes: 0eee35bdfa3b ("Bluetooth: Update resolving list when updating whitelist")
Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_request.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index e0269192f2e5..a565c91b8599 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -698,7 +698,8 @@ static void del_from_white_list(struct hci_request *req, bdaddr_t *bdaddr,
cp.bdaddr_type);
hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, sizeof(cp), &cp);
- if (use_ll_privacy(req->hdev)) {
+ if (use_ll_privacy(req->hdev) &&
+ hci_dev_test_flag(req->hdev, HCI_ENABLE_LL_PRIVACY)) {
struct smp_irk *irk;
irk = hci_find_irk_by_addr(req->hdev, bdaddr, bdaddr_type);
@@ -732,7 +733,8 @@ static int add_to_white_list(struct hci_request *req,
return -1;
/* White list can not be used with RPAs */
- if (!allow_rpa && !use_ll_privacy(hdev) &&
+ if (!allow_rpa &&
+ !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
hci_find_irk_by_addr(hdev, &params->addr, params->addr_type)) {
return -1;
}
@@ -750,7 +752,8 @@ static int add_to_white_list(struct hci_request *req,
cp.bdaddr_type);
hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp);
- if (use_ll_privacy(hdev)) {
+ if (use_ll_privacy(hdev) &&
+ hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY)) {
struct smp_irk *irk;
irk = hci_find_irk_by_addr(hdev, &params->addr,
@@ -812,7 +815,8 @@ static u8 update_white_list(struct hci_request *req)
}
/* White list can not be used with RPAs */
- if (!allow_rpa && !use_ll_privacy(hdev) &&
+ if (!allow_rpa &&
+ !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
hci_find_irk_by_addr(hdev, &b->bdaddr, b->bdaddr_type)) {
return 0x00;
}
--
cgit v1.2.3-1-gf6bb5

View File

@ -1,28 +0,0 @@
From 9d662fb865ae496a7eb51d2bdddefd2427d9a30e Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bshah@kde.org>
Date: Fri, 9 Apr 2021 16:25:25 +0530
Subject: [PATCH 2/5] Revert "usb: quirks: Add USB_QUIRK_RESET for Quectel
EG25G Modem"
Reverts 8cc2a406ecc711f5
---
drivers/usb/core/quirks.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index cb556617aa34f..6ade3daf78584 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -501,9 +501,6 @@ static const struct usb_device_id usb_quirk_list[] = {
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
- /* Quectel EG25G Modem */
- { USB_DEVICE(0x2c7c, 0x0125), .driver_info = USB_QUIRK_RESET },
-
{ } /* terminating entry must be last */
};
--
2.31.1

View File

@ -1,61 +0,0 @@
From 33212e529708fd480eaf9cc76579f8e7044c0505 Mon Sep 17 00:00:00 2001
From: Martijn Braam <martijn@brixit.nl>
Date: Tue, 20 Oct 2020 14:42:01 +0200
Subject: [PATCH] dts: add pinetab-dev (old display panel)
---
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../dts/allwinner/sun50i-a64-pinetab-dev.dts | 29 +++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts
diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index a21cfdd8924d..2936092002b5 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -15,6 +15,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.0.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.1.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinephone-1.2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinetab.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinetab-dev.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts
new file mode 100644
index 000000000000..1e287f2fb9f3
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab-dev.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64-pinetab.dts"
+
+/ {
+ model = "PineTab";
+ compatible = "pine64,pinetab", "allwinner,sun50i-a64";
+};
+
+&dsi {
+ vcc-dsi-supply = <&reg_dldo1>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "feixin,k101-im2ba02";
+ reg = <0>;
+ avdd-supply = <&reg_dc1sw>;
+ dvdd-supply = <&reg_dc1sw>;
+ cvdd-supply = <&reg_ldo_io1>;
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
+ backlight = <&backlight>;
+ };
+};
--
2.25.4

View File

@ -1,497 +0,0 @@
--- b/drivers/video/fbdev/core/fbcon.c
+++ a/drivers/video/fbdev/core/fbcon.c
@@ -122,6 +122,12 @@
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
enums. */
static int logo_shown = FBCON_LOGO_CANSHOW;
+/* Software scrollback */
+static int fbcon_softback_size = 32768;
+static unsigned long softback_buf, softback_curr;
+static unsigned long softback_in;
+static unsigned long softback_top, softback_end;
+static int softback_lines;
/* console mappings */
static int first_fb_vc;
static int last_fb_vc = MAX_NR_CONSOLES - 1;
@@ -161,6 +167,8 @@
static const struct consw fb_con;
+#define CM_SOFTBACK (8)
+
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
static int fbcon_set_origin(struct vc_data *);
@@ -365,6 +373,18 @@
return color;
}
+static void fbcon_update_softback(struct vc_data *vc)
+{
+ int l = fbcon_softback_size / vc->vc_size_row;
+
+ if (l > 5)
+ softback_end = softback_buf + l * vc->vc_size_row;
+ else
+ /* Smaller scrollback makes no sense, and 0 would screw
+ the operation totally */
+ softback_top = 0;
+}
+
static void fb_flashcursor(struct work_struct *work)
{
struct fb_info *info = container_of(work, struct fb_info, queue);
@@ -394,7 +414,7 @@
c = scr_readw((u16 *) vc->vc_pos);
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
CM_ERASE : CM_DRAW;
+ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
console_unlock();
}
@@ -451,7 +471,13 @@
}
if (!strncmp(options, "scrollback:", 11)) {
+ options += 11;
+ if (*options) {
+ fbcon_softback_size = simple_strtoul(options, &options, 0);
+ if (*options == 'k' || *options == 'K') {
+ fbcon_softback_size *= 1024;
+ }
+ }
- pr_warn("Ignoring scrollback size option\n");
continue;
}
@@ -996,6 +1022,31 @@
set_blitting_type(vc, info);
+ if (info->fix.type != FB_TYPE_TEXT) {
+ if (fbcon_softback_size) {
+ if (!softback_buf) {
+ softback_buf =
+ (unsigned long)
+ kvmalloc(fbcon_softback_size,
+ GFP_KERNEL);
+ if (!softback_buf) {
+ fbcon_softback_size = 0;
+ softback_top = 0;
+ }
+ }
+ } else {
+ if (softback_buf) {
+ kvfree((void *) softback_buf);
+ softback_buf = 0;
+ softback_top = 0;
+ }
+ }
+ if (softback_buf)
+ softback_in = softback_top = softback_curr =
+ softback_buf;
+ softback_lines = 0;
+ }
+
/* Setup default font */
if (!p->fontdata && !vc->vc_font.data) {
if (!fontname[0] || !(font = find_font(fontname)))
@@ -1169,6 +1220,9 @@
if (logo)
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
+ if (vc == svc && softback_buf)
+ fbcon_update_softback(vc);
+
if (ops->rotate_font && ops->rotate_font(info, vc)) {
ops->rotate = FB_ROTATE_UR;
set_blitting_type(vc, info);
@@ -1331,6 +1385,7 @@
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
+ int y;
int c = scr_readw((u16 *) vc->vc_pos);
ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
@@ -1344,8 +1399,16 @@
fbcon_add_cursor_timer(info);
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
+ if (mode & CM_SOFTBACK) {
+ mode &= ~CM_SOFTBACK;
+ y = softback_lines;
+ } else {
+ if (softback_lines)
+ fbcon_set_origin(vc);
+ y = 0;
+ }
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
}
@@ -1416,6 +1479,8 @@
if (con_is_visible(vc)) {
update_screen(vc);
+ if (softback_buf)
+ fbcon_update_softback(vc);
}
}
@@ -1553,6 +1618,99 @@
scrollback_current = 0;
}
+static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
+ long delta)
+{
+ int count = vc->vc_rows;
+ unsigned short *d, *s;
+ unsigned long n;
+ int line = 0;
+
+ d = (u16 *) softback_curr;
+ if (d == (u16 *) softback_in)
+ d = (u16 *) vc->vc_origin;
+ n = softback_curr + delta * vc->vc_size_row;
+ softback_lines -= delta;
+ if (delta < 0) {
+ if (softback_curr < softback_top && n < softback_buf) {
+ n += softback_end - softback_buf;
+ if (n < softback_top) {
+ softback_lines -=
+ (softback_top - n) / vc->vc_size_row;
+ n = softback_top;
+ }
+ } else if (softback_curr >= softback_top
+ && n < softback_top) {
+ softback_lines -=
+ (softback_top - n) / vc->vc_size_row;
+ n = softback_top;
+ }
+ } else {
+ if (softback_curr > softback_in && n >= softback_end) {
+ n += softback_buf - softback_end;
+ if (n > softback_in) {
+ n = softback_in;
+ softback_lines = 0;
+ }
+ } else if (softback_curr <= softback_in && n > softback_in) {
+ n = softback_in;
+ softback_lines = 0;
+ }
+ }
+ if (n == softback_curr)
+ return;
+ softback_curr = n;
+ s = (u16 *) softback_curr;
+ if (s == (u16 *) softback_in)
+ s = (u16 *) vc->vc_origin;
+ while (count--) {
+ unsigned short *start;
+ unsigned short *le;
+ unsigned short c;
+ int x = 0;
+ unsigned short attr = 1;
+
+ start = s;
+ le = advance_row(s, 1);
+ do {
+ c = scr_readw(s);
+ if (attr != (c & 0xff00)) {
+ attr = c & 0xff00;
+ if (s > start) {
+ fbcon_putcs(vc, start, s - start,
+ line, x);
+ x += s - start;
+ start = s;
+ }
+ }
+ if (c == scr_readw(d)) {
+ if (s > start) {
+ fbcon_putcs(vc, start, s - start,
+ line, x);
+ x += s - start + 1;
+ start = s + 1;
+ } else {
+ x++;
+ start++;
+ }
+ }
+ s++;
+ d++;
+ } while (s < le);
+ if (s > start)
+ fbcon_putcs(vc, start, s - start, line, x);
+ line++;
+ if (d == (u16 *) softback_end)
+ d = (u16 *) softback_buf;
+ if (d == (u16 *) softback_in)
+ d = (u16 *) vc->vc_origin;
+ if (s == (u16 *) softback_end)
+ s = (u16 *) softback_buf;
+ if (s == (u16 *) softback_in)
+ s = (u16 *) vc->vc_origin;
+ }
+}
+
static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
int line, int count, int dy)
{
@@ -1692,6 +1850,31 @@
}
}
+static inline void fbcon_softback_note(struct vc_data *vc, int t,
+ int count)
+{
+ unsigned short *p;
+
+ if (vc->vc_num != fg_console)
+ return;
+ p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
+
+ while (count) {
+ scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
+ count--;
+ p = advance_row(p, 1);
+ softback_in += vc->vc_size_row;
+ if (softback_in == softback_end)
+ softback_in = softback_buf;
+ if (softback_in == softback_top) {
+ softback_top += vc->vc_size_row;
+ if (softback_top == softback_end)
+ softback_top = softback_buf;
+ }
+ }
+ softback_curr = softback_in;
+}
+
static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
enum con_scroll dir, unsigned int count)
{
@@ -1714,6 +1897,8 @@
case SM_UP:
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
+ if (softback_top)
+ fbcon_softback_note(vc, t, count);
if (logo_shown >= 0)
goto redraw_up;
switch (p->scrollmode) {
@@ -2084,6 +2269,14 @@
info = registered_fb[con2fb_map[vc->vc_num]];
ops = info->fbcon_par;
+ if (softback_top) {
+ if (softback_lines)
+ fbcon_set_origin(vc);
+ softback_top = softback_curr = softback_in = softback_buf;
+ softback_lines = 0;
+ fbcon_update_softback(vc);
+ }
+
if (logo_shown >= 0) {
struct vc_data *conp2 = vc_cons[logo_shown].d;
@@ -2407,6 +2600,9 @@
int cnt;
char *old_data = NULL;
+ if (con_is_visible(vc) && softback_lines)
+ fbcon_set_origin(vc);
+
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
if (p->userfont)
old_data = vc->vc_font.data;
@@ -2432,6 +2628,8 @@
cols /= w;
rows /= h;
vc_resize(vc, cols, rows);
+ if (con_is_visible(vc) && softback_buf)
+ fbcon_update_softback(vc);
} else if (con_is_visible(vc)
&& vc->vc_mode == KD_TEXT) {
fbcon_clear_margins(vc, 0);
@@ -2590,7 +2788,19 @@
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
{
+ unsigned long p;
+ int line;
+
+ if (vc->vc_num != fg_console || !softback_lines)
+ return (u16 *) (vc->vc_origin + offset);
+ line = offset / vc->vc_size_row;
+ if (line >= softback_lines)
+ return (u16 *) (vc->vc_origin + offset -
+ softback_lines * vc->vc_size_row);
+ p = softback_curr + offset;
+ if (p >= softback_end)
+ p += softback_buf - softback_end;
+ return (u16 *) p;
- return (u16 *) (vc->vc_origin + offset);
}
static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
@@ -2604,7 +2814,22 @@
x = offset % vc->vc_cols;
y = offset / vc->vc_cols;
+ if (vc->vc_num == fg_console)
+ y += softback_lines;
ret = pos + (vc->vc_cols - x) * 2;
+ } else if (vc->vc_num == fg_console && softback_lines) {
+ unsigned long offset = pos - softback_curr;
+
+ if (pos < softback_curr)
+ offset += softback_end - softback_buf;
+ offset /= 2;
+ x = offset % vc->vc_cols;
+ y = offset / vc->vc_cols;
+ ret = pos + (vc->vc_cols - x) * 2;
+ if (ret == softback_end)
+ ret = softback_buf;
+ if (ret == softback_in)
+ ret = vc->vc_origin;
} else {
/* Should not happen */
x = y = 0;
@@ -2632,11 +2857,106 @@
a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
(((a) & 0x0700) << 4);
scr_writew(a, p++);
+ if (p == (u16 *) softback_end)
+ p = (u16 *) softback_buf;
+ if (p == (u16 *) softback_in)
+ p = (u16 *) vc->vc_origin;
+ }
+}
+
+static void fbcon_scrolldelta(struct vc_data *vc, int lines)
+{
+ struct fb_info *info = registered_fb[con2fb_map[fg_console]];
+ struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_display *disp = &fb_display[fg_console];
+ int offset, limit, scrollback_old;
+
+ if (softback_top) {
+ if (vc->vc_num != fg_console)
+ return;
+ if (vc->vc_mode != KD_TEXT || !lines)
+ return;
+ if (logo_shown >= 0) {
+ struct vc_data *conp2 = vc_cons[logo_shown].d;
+
+ if (conp2->vc_top == logo_lines
+ && conp2->vc_bottom == conp2->vc_rows)
+ conp2->vc_top = 0;
+ if (logo_shown == vc->vc_num) {
+ unsigned long p, q;
+ int i;
+
+ p = softback_in;
+ q = vc->vc_origin +
+ logo_lines * vc->vc_size_row;
+ for (i = 0; i < logo_lines; i++) {
+ if (p == softback_top)
+ break;
+ if (p == softback_buf)
+ p = softback_end;
+ p -= vc->vc_size_row;
+ q -= vc->vc_size_row;
+ scr_memcpyw((u16 *) q, (u16 *) p,
+ vc->vc_size_row);
+ }
+ softback_in = softback_curr = p;
+ update_region(vc, vc->vc_origin,
+ logo_lines * vc->vc_cols);
+ }
+ logo_shown = FBCON_LOGO_CANSHOW;
+ }
+ fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
+ fbcon_redraw_softback(vc, disp, lines);
+ fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
+ return;
}
+
+ if (!scrollback_phys_max)
+ return;
+
+ scrollback_old = scrollback_current;
+ scrollback_current -= lines;
+ if (scrollback_current < 0)
+ scrollback_current = 0;
+ else if (scrollback_current > scrollback_max)
+ scrollback_current = scrollback_max;
+ if (scrollback_current == scrollback_old)
+ return;
+
+ if (fbcon_is_inactive(vc, info))
+ return;
+
+ fbcon_cursor(vc, CM_ERASE);
+
+ offset = disp->yscroll - scrollback_current;
+ limit = disp->vrows;
+ switch (disp->scrollmode) {
+ case SCROLL_WRAP_MOVE:
+ info->var.vmode |= FB_VMODE_YWRAP;
+ break;
+ case SCROLL_PAN_MOVE:
+ case SCROLL_PAN_REDRAW:
+ limit -= vc->vc_rows;
+ info->var.vmode &= ~FB_VMODE_YWRAP;
+ break;
+ }
+ if (offset < 0)
+ offset += limit;
+ else if (offset >= limit)
+ offset -= limit;
+
+ ops->var.xoffset = 0;
+ ops->var.yoffset = offset * vc->vc_font.height;
+ ops->update_start(info);
+
+ if (!scrollback_current)
+ fbcon_cursor(vc, CM_DRAW);
}
static int fbcon_set_origin(struct vc_data *vc)
{
+ if (softback_lines)
+ fbcon_scrolldelta(vc, softback_lines);
return 0;
}
@@ -2700,6 +3020,8 @@
fbcon_set_palette(vc, color_table);
update_screen(vc);
+ if (softback_buf)
+ fbcon_update_softback(vc);
}
}
@@ -3110,6 +3432,7 @@
.con_font_default = fbcon_set_def_font,
.con_font_copy = fbcon_copy_font,
.con_set_palette = fbcon_set_palette,
+ .con_scrolldelta = fbcon_scrolldelta,
.con_set_origin = fbcon_set_origin,
.con_invert_region = fbcon_invert_region,
.con_screen_pos = fbcon_screen_pos,
@@ -3344,6 +3667,9 @@
}
#endif
+ kvfree((void *)softback_buf);
+ softback_buf = 0UL;
+
for_each_registered_fb(i) {
int pending = 0;

View File

@ -0,0 +1,152 @@
From: Manish Narani <manish.narani@xilinx.com>
Date: Tue, 18 Sep 2018 20:34:06 +0530
Subject: [PATCH 16/36] sdhci: arasan: Add runtime PM support
Add runtime PM support in Arasan SDHCI driver.
Signed-off-by: Manish Narani <manish.narani@xilinx.com>
---
drivers/mmc/host/sdhci-of-arasan.c | 88 +++++++++++++++++++++++++++++++++++++-
1 file changed, 86 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c
index 6a2e5a4..e08d6ef 100644
--- a/drivers/mmc/host/sdhci-of-arasan.c
+++ b/drivers/mmc/host/sdhci-of-arasan.c
@@ -19,6 +19,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/of.h>
@@ -27,6 +28,7 @@
#include "cqhci.h"
#include "sdhci-pltfm.h"
+#define SDHCI_ARASAN_AUTOSUSPEND_DELAY 2000 /* ms */
#define SDHCI_ARASAN_VENDOR_REGISTER 0x78
#define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8
@@ -472,6 +474,70 @@ static const struct sdhci_pltfm_data sdhci_arasan_thunderbay_pdata = {
SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400,
};
+#ifdef CONFIG_PM
+static int sdhci_arasan_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+
+ if (sdhci_arasan->has_cqe) {
+ ret = cqhci_suspend(host->mmc);
+ if (ret)
+ return ret;
+ }
+
+ ret = sdhci_runtime_suspend_host(host);
+ if (ret)
+ return ret;
+
+ if (host->tuning_mode != SDHCI_TUNING_MODE_3)
+ mmc_retune_needed(host->mmc);
+
+ clk_disable(pltfm_host->clk);
+ clk_disable(sdhci_arasan->clk_ahb);
+
+ return 0;
+}
+
+static int sdhci_arasan_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+ int ret;
+
+ ret = clk_enable(sdhci_arasan->clk_ahb);
+ if (ret) {
+ dev_err(dev, "Cannot enable AHB clock.\n");
+ return ret;
+ }
+
+ ret = clk_enable(pltfm_host->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable SD clock.\n");
+ return ret;
+ }
+
+ ret = sdhci_runtime_resume_host(host, 0);
+ if (ret)
+ goto out;
+
+ if (sdhci_arasan->has_cqe)
+ return cqhci_resume(host->mmc);
+
+ return 0;
+out:
+ clk_disable(pltfm_host->clk);
+ clk_disable(sdhci_arasan->clk_ahb);
+
+ return ret;
+}
+#endif /* ! CONFIG_PM */
+
#ifdef CONFIG_PM_SLEEP
/**
* sdhci_arasan_suspend - Suspend method for the driver
@@ -568,8 +634,10 @@ static int sdhci_arasan_resume(struct device *dev)
}
#endif /* ! CONFIG_PM_SLEEP */
-static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
- sdhci_arasan_resume);
+static const struct dev_pm_ops sdhci_arasan_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(sdhci_arasan_suspend, sdhci_arasan_resume)
+ SET_RUNTIME_PM_OPS(sdhci_arasan_runtime_suspend,
+ sdhci_arasan_runtime_resume, NULL) };
/**
* sdhci_arasan_sdcardclk_recalc_rate - Return the card clock rate
@@ -1708,13 +1776,25 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
}
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ SDHCI_ARASAN_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
+
ret = sdhci_arasan_add_host(sdhci_arasan);
if (ret)
goto err_add_host;
+ pm_runtime_put_autosuspend(&pdev->dev);
+
return 0;
err_add_host:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
if (!IS_ERR(sdhci_arasan->phy))
phy_exit(sdhci_arasan->phy);
unreg_clk:
@@ -1742,6 +1822,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev)
phy_exit(sdhci_arasan->phy);
}
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
sdhci_arasan_unregister_sdclk(&pdev->dev);
ret = sdhci_pltfm_unregister(pdev);

View File

@ -1,48 +0,0 @@
From 4264c74c96e7907b60ee6ed82670317d19ed7ebe Mon Sep 17 00:00:00 2001
From: Edward Vear <edwardvear@gmail.com>
Date: Tue, 27 Oct 2020 00:02:03 -0700
Subject: Bluetooth: Fix attempting to set RPA timeout when unsupported
During controller initialization, an LE Set RPA Timeout command is sent
to the controller if supported. However, the value checked to determine
if the command is supported is incorrect. Page 1921 of the Bluetooth
Core Spec v5.2 shows that bit 2 of octet 35 of the Supported_Commands
field corresponds to the LE Set RPA Timeout command, but currently
bit 6 of octet 35 is checked. This patch checks the correct value
instead.
This issue led to the error seen in the following btmon output during
initialization of an adapter (rtl8761b) and prevented initialization
from completing.
< HCI Command: LE Set Resolvable Private Address Timeout (0x08|0x002e) plen 2
Timeout: 900 seconds
> HCI Event: Command Complete (0x0e) plen 4
LE Set Resolvable Private Address Timeout (0x08|0x002e) ncmd 2
Status: Unsupported Remote Feature / Unsupported LMP Feature (0x1a)
= Close Index: 00:E0:4C:6B:E5:03
The error did not appear when running with this patch.
Signed-off-by: Edward Vear <edwardvear@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index be9cdf5dabe5..30a5267af490 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -763,7 +763,7 @@ static int hci_init3_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_LE_CLEAR_RESOLV_LIST, 0, NULL);
}
- if (hdev->commands[35] & 0x40) {
+ if (hdev->commands[35] & 0x04) {
__le16 rpa_timeout = cpu_to_le16(hdev->rpa_timeout);
/* Set RPA timeout */
--
cgit v1.2.3-1-gf6bb5

View File

@ -1,40 +0,0 @@
Bluetooth: btusb: Some Qualcomm Bluetooth adapters stop working
This issue starts from linux-5.10-rc1, I reproduced this issue on my
Dell Inspiron 7447 with BT adapter 0cf3:e005, the kernel will print
out: "Bluetooth: hci0: don't support firmware rome 0x31010000", and
someone else also reported the similar issue to bugzilla #211571.
I found this is a regression introduced by 'commit b40f58b97386
("Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support"), the
patch assumed that if high ROM version is not zero, it is an adapter
on WCN6855, but many old adapters don't need to load rampatch or nvm,
and they have non-zero high ROM version.
To fix it, let the driver match the rom_version in the
qca_devices_table first, if there is no entry matched, check the
high ROM version, if it is not zero, we assume this adapter is ready
to work and no need to load rampatch and nvm like previously.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=211571
Fixes: b40f58b97386 ("Bluetooth: btusb: Add Qualcomm Bluetooth SoC WCN6855 support")
Signed-off-by: Hui Wang <hui.wang@canonical.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 03b83aa91277..32161dd40ed6 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -4069,6 +4069,13 @@ static int btusb_setup_qca(struct hci_dev *hdev)
info = &qca_devices_table[i];
}
if (!info) {
+ /* If the rom_version is not matched in the qca_devices_table
+ * and the high ROM version is not zero, we assume this chip no
+ * need to load the rampatch and nvm.
+ */
+ if (ver_rom & ~0xffffU)
+ return 0;
+
bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
return -ENODEV;
}

View File

@ -0,0 +1,37 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 22 Oct 2021 18:09:09 +0200
Subject: [PATCH 19/36] clk: rk3399: Export SCLK_CIF_OUT_SRC to device tree
So that it can be used in assigned-clock-parents.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/clk/rockchip/clk-rk3399.c | 2 +-
include/dt-bindings/clock/rk3399-cru.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
index 306910a..897581e 100644
--- a/drivers/clk/rockchip/clk-rk3399.c
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -1259,7 +1259,7 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
RK3399_CLKGATE_CON(27), 6, GFLAGS),
/* cif */
- COMPOSITE_NODIV(0, "clk_cifout_src", mux_pll_src_cpll_gpll_npll_p, 0,
+ COMPOSITE_NODIV(SCLK_CIF_OUT_SRC, "clk_cifout_src", mux_pll_src_cpll_gpll_npll_p, 0,
RK3399_CLKSEL_CON(56), 6, 2, MFLAGS,
RK3399_CLKGATE_CON(10), 7, GFLAGS),
diff --git a/include/dt-bindings/clock/rk3399-cru.h b/include/dt-bindings/clock/rk3399-cru.h
index 44e0a31..e83b3fb 100644
--- a/include/dt-bindings/clock/rk3399-cru.h
+++ b/include/dt-bindings/clock/rk3399-cru.h
@@ -125,6 +125,7 @@
#define SCLK_DDRC 168
#define SCLK_TESTCLKOUT1 169
#define SCLK_TESTCLKOUT2 170
+#define SCLK_CIF_OUT_SRC 171
#define DCLK_VOP0 180
#define DCLK_VOP1 181

View File

@ -1,51 +0,0 @@
From 562a6c114ce736db51e41b8c06c408104b79b126 Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bshah@kde.org>
Date: Wed, 14 Apr 2021 10:29:39 +0530
Subject: [PATCH 3/5] qmi_wwan: provide wrapper for reset_resume
---
drivers/net/usb/qmi_wwan.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index e18ded349d840..cd6ae9696b56a 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -840,6 +840,25 @@ static int qmi_wwan_resume(struct usb_interface *intf)
return ret;
}
+static int qmi_wwan_reset_resume(struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+ struct qmi_wwan_state *info = (void *)&dev->data;
+ int ret = 0;
+ bool callsub = (intf == info->control && info->subdriver &&
+ info->subdriver->reset_resume);
+
+ if (callsub)
+ ret = info->subdriver->reset_resume(intf);
+ if (ret < 0)
+ goto err;
+ ret = usbnet_resume(intf);
+ if (ret < 0 && callsub)
+ info->subdriver->suspend(intf, PMSG_SUSPEND);
+err:
+ return ret;
+}
+
static const struct driver_info qmi_wwan_info = {
.description = "WWAN/QMI device",
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
@@ -1478,7 +1497,7 @@ static struct usb_driver qmi_wwan_driver = {
.disconnect = qmi_wwan_disconnect,
.suspend = qmi_wwan_suspend,
.resume = qmi_wwan_resume,
- .reset_resume = qmi_wwan_resume,
+ .reset_resume = qmi_wwan_reset_resume,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};
--
2.31.1

View File

@ -1,65 +0,0 @@
From 3af7a8b44f265a482c8297b420085cfb53725136 Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bshah@kde.org>
Date: Wed, 14 Apr 2021 10:29:57 +0530
Subject: [PATCH 4/5] cdc-wdm: provide wrapper for reset_resume
---
drivers/usb/class/cdc-wdm.c | 35 ++++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 508b1c3f8b731..2b9355ed4a2ad 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -1119,6 +1119,39 @@ static int wdm_resume(struct usb_interface *intf)
return rv;
}
+
+static int wdm_reset_resume(struct usb_interface *intf)
+{
+ struct wdm_device *desc = wdm_find_device(intf);
+ int rv;
+
+ dev_dbg(&desc->intf->dev, "wdm%d_reset_resume\n", intf->minor);
+
+ spin_lock_irq(&desc->iuspin);
+ set_bit(WDM_RESETTING, &desc->flags);
+ set_bit(WDM_READ, &desc->flags);
+ clear_bit(WDM_IN_USE, &desc->flags);
+
+ desc->rerr = -EINTR;
+
+ spin_unlock_irq(&desc->iuspin);
+ wake_up_all(&desc->wait);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
+ poison_urbs(desc);
+ cancel_work_sync(&desc->rxwork);
+ cancel_work_sync(&desc->service_outs_intr);
+
+ clear_bit(WDM_SUSPENDING, &desc->flags);
+ clear_bit(WDM_OVERFLOW, &desc->flags);
+ clear_bit(WDM_RESETTING, &desc->flags);
+
+ rv = recover_from_urb_loss(desc);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
+
+ return rv;
+}
#endif
static int wdm_pre_reset(struct usb_interface *intf)
@@ -1166,7 +1199,7 @@ static struct usb_driver wdm_driver = {
#ifdef CONFIG_PM
.suspend = wdm_suspend,
.resume = wdm_resume,
- .reset_resume = wdm_resume,
+ .reset_resume = wdm_reset_resume,
#endif
.pre_reset = wdm_pre_reset,
.post_reset = wdm_post_reset,
--
2.31.1

View File

@ -1,58 +0,0 @@
From a163474e9b86c2c25f20733385d8b1d6de492a7f Mon Sep 17 00:00:00 2001
From: Ard Biesheuvel <ardb@kernel.org>
Date: Wed, 25 Nov 2020 08:45:55 +0100
Subject: efivarfs: revert "fix memory leak in efivarfs_create()"
The memory leak addressed by commit fe5186cf12e3 is a false positive:
all allocations are recorded in a linked list, and freed when the
filesystem is unmounted. This leads to double frees, and as reported
by David, leads to crashes if SLUB is configured to self destruct when
double frees occur.
So drop the redundant kfree() again, and instead, mark the offending
pointer variable so the allocation is ignored by kmemleak.
Cc: Vamshi K Sthambamkadi <vamshi.k.sthambamkadi@gmail.com>
Fixes: fe5186cf12e3 ("efivarfs: fix memory leak in efivarfs_create()")
Reported-by: David Laight <David.Laight@aculab.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
fs/efivarfs/inode.c | 2 ++
fs/efivarfs/super.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
index 96c0c86f3fff..0297ad95eb5c 100644
--- a/fs/efivarfs/inode.c
+++ b/fs/efivarfs/inode.c
@@ -7,6 +7,7 @@
#include <linux/efi.h>
#include <linux/fs.h>
#include <linux/ctype.h>
+#include <linux/kmemleak.h>
#include <linux/slab.h>
#include <linux/uuid.h>
@@ -103,6 +104,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
var->var.VariableName[i] = '\0';
inode->i_private = var;
+ kmemleak_ignore(var);
err = efivar_entry_add(var, &efivarfs_list);
if (err)
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index f943fd0b0699..15880a68faad 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -21,7 +21,6 @@ LIST_HEAD(efivarfs_list);
static void efivarfs_evict_inode(struct inode *inode)
{
clear_inode(inode);
- kfree(inode->i_private);
}
static const struct super_operations efivarfs_ops = {
--
cgit v1.2.3-1-gf6bb5

View File

@ -0,0 +1,39 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 21 Nov 2021 17:00:09 +0100
Subject: [PATCH 24/36] media: rockchip: rga: Fix probe bugs
The check for dst_mmu_pages allocation failure was inverted.
rga_parse_dt is missing a error return, so if some of the resources
return DEFER_PROBE, probe will succeed without these resources.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/platform/rockchip/rga/rga.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
index 4de5e8d..82cc0c0 100644
--- a/drivers/media/platform/rockchip/rga/rga.c
+++ b/drivers/media/platform/rockchip/rga/rga.c
@@ -815,8 +815,10 @@ static int rga_probe(struct platform_device *pdev)
mutex_init(&rga->mutex);
ret = rga_parse_dt(rga);
- if (ret)
+ if (ret) {
dev_err(&pdev->dev, "Unable to parse OF data\n");
+ return ret;
+ }
pm_runtime_enable(rga->dev);
@@ -892,7 +894,7 @@ static int rga_probe(struct platform_device *pdev)
}
rga->dst_mmu_pages =
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
- if (rga->dst_mmu_pages) {
+ if (!rga->dst_mmu_pages) {
ret = -ENOMEM;
goto free_src_pages;
}

View File

@ -0,0 +1,34 @@
From: =?utf-8?q?Kamil_Trzci=C5=84ski?= <ayufan@ayufan.eu>
Date: Fri, 8 Jan 2021 00:19:23 +0100
Subject: [PATCH 02/36] drm: dw-mipi-dsi-rockchip: Ensure that lane is
properly configured
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
???
Signed-of-by: Kamil Trzciński <ayufan@ayufan.eu>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index a9acbcc..53c8b40 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -406,6 +406,14 @@ static int dw_mipi_dsi_phy_init(void *priv_data)
*/
vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200;
+ if (dsi->cdata->lanecfg1_grf_reg) {
+ regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg1_grf_reg,
+ dsi->cdata->lanecfg1);
+
+ dev_info(dsi->dev, "dw_mipi_dsi_phy_init / dw_mipi_dsi_rockchip_config: %08x => set=%08x\n",
+ dsi->cdata->lanecfg1_grf_reg, dsi->cdata->lanecfg1);
+ }
+
i = max_mbps_to_parameter(dsi->lane_mbps);
if (i < 0) {
DRM_DEV_ERROR(dsi->dev,

View File

@ -1,34 +0,0 @@
From ed73c96e313c549f710df58c8fbe47200ee13df1 Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bshah@kde.org>
Date: Sat, 10 Apr 2021 08:52:05 +0530
Subject: [PATCH 5/5] net: usb: qmi_wwan: set the DTR when resuming
If usb device does reset_resume instead of unbind/bind, we need to
re-enable the DTR quirk, that way after resuming connection QMI
communication between host and modem is possible again.
Signed-off-by: Bhushan Shah <bshah@kde.org>
Tested-by: Dalton Durst <d@ltondur.st>
---
drivers/net/usb/qmi_wwan.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index cd6ae9696b56a..ada94a3242146 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -855,6 +855,11 @@ static int qmi_wwan_reset_resume(struct usb_interface *intf)
ret = usbnet_resume(intf);
if (ret < 0 && callsub)
info->subdriver->suspend(intf, PMSG_SUSPEND);
+
+ if (dev->driver_info->data & QMI_WWAN_QUIRK_DTR ||
+ le16_to_cpu(dev->udev->descriptor.bcdUSB) >= 0x0201) {
+ qmi_wwan_change_dtr(dev, true);
+ }
err:
return ret;
}
--
2.31.1

View File

@ -1,27 +0,0 @@
From 1671ef2de0f3f698622bed7ba0e9a605fdd260fc Mon Sep 17 00:00:00 2001
From: Bhushan Shah <bshah@kde.org>
Date: Wed, 14 Apr 2021 18:58:41 +0530
Subject: [PATCH 6/6] cdc-wdm: send HUP if we are resetting
If userspace is polling the cdc-wdm socket, and device resets then we
should notify userspace/client about reset.
---
drivers/usb/class/cdc-wdm.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 2b9355ed4a2ad..93d9bacc18384 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -666,6 +666,8 @@ static __poll_t wdm_poll(struct file *file, struct poll_table_struct *wait)
spin_unlock_irqrestore(&desc->iuspin, flags);
goto desc_out;
}
+ if (test_bit(WDM_RESETTING, &desc->flags))
+ mask = EPOLLHUP;
if (test_bit(WDM_READ, &desc->flags))
mask = EPOLLIN | EPOLLRDNORM;
if (desc->rerr || desc->werr)
--
2.31.1

View File

@ -0,0 +1,48 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 17 Oct 2021 18:04:21 +0200
Subject: [PATCH 03/36] drm: rockchip: dw-mipi-dsi: Fix missing
clk_disable_unprepare for pllref_clk
In some error paths, clk_disable_unprepare function was not called.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index 53c8b40..095d0f1 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -960,7 +960,7 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev,
ret = clk_prepare_enable(dsi->grf_clk);
if (ret) {
DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
- return ret;
+ goto err_pllref_disable;
}
dw_mipi_dsi_rockchip_config(dsi);
@@ -972,16 +972,20 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev,
ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to create drm encoder\n");
- return ret;
+ goto err_pllref_disable;
}
ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder);
if (ret) {
DRM_DEV_ERROR(dev, "Failed to bind: %d\n", ret);
- return ret;
+ goto err_pllref_disable;
}
return 0;
+
+err_pllref_disable:
+ clk_disable_unprepare(dsi->pllref_clk);
+ return ret;
}
static void dw_mipi_dsi_rockchip_unbind(struct device *dev,

View File

@ -0,0 +1,145 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 17 Oct 2021 20:14:25 +0200
Subject: [PATCH 04/36] drm: bridge: dw-mipi-dsi: Fix enable/disable of dsi
controller
The driver had it all wrong. mode_set is not for enabling the
DSI controller, that should be done in pre_enable so that
panel driver can initialize the panel (working dsi controller
is needed for that). Having dsi powerup in mode_set led to
all kind of fun, because disable would be called more often
than mode_set.
The whole panel/dsi enable/disable dance is such (for future
reference):
- dsi: mode set
- panel: prepare (we turn on panel power)
- dsi: pre enable (we enable and setup DSI)
- dsi: enable (we enable video data)
- panel: enable (we configure and turn on the display)
For disable:
- panel: disable (we turn off the display nicely)
- dsi: disable (we disable DSI)
- dsi: post disable
- panel: unprepare (we power off display power, panel should
be safely sleeping now)
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 45 +++++++++++++++++++--------
1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index e44e18a..9cce2ab 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -266,6 +266,7 @@ struct dw_mipi_dsi {
struct dw_mipi_dsi *master; /* dual-dsi master ptr */
struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */
+ struct drm_display_mode mode;
const struct dw_mipi_dsi_plat_data *plat_data;
};
@@ -597,6 +598,8 @@ static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
{
u32 val;
+ dev_info(dsi->dev, "mode %d\n", (int)mode_flags);
+
dsi_write(dsi, DSI_PWR_UP, RESET);
if (mode_flags & MIPI_DSI_MODE_VIDEO) {
@@ -871,11 +874,20 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
dsi_write(dsi, DSI_INT_MSK1, 0);
}
+static void dw_mipi_dsi_bridge_disable(struct drm_bridge *bridge)
+{
+ struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+
+ dev_info(dsi->dev, "disable\n");
+}
+
static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
{
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
+ dev_info(dsi->dev, "post disable\n");
+
/*
* Switch to command mode before panel-bridge post_disable &
* panel unprepare.
@@ -884,15 +896,6 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
*/
dw_mipi_dsi_set_mode(dsi, 0);
- /*
- * TODO Only way found to call panel-bridge post_disable &
- * panel unprepare before the dsi "final" disable...
- * This needs to be fixed in the drm_bridge framework and the API
- * needs to be updated to manage our own call chains...
- */
- if (dsi->panel_bridge->funcs->post_disable)
- dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge);
-
if (phy_ops->power_off)
phy_ops->power_off(dsi->plat_data->priv_data);
@@ -921,7 +924,7 @@ static unsigned int dw_mipi_dsi_get_lanes(struct dw_mipi_dsi *dsi)
return dsi->lanes;
}
-static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
+static void dw_mipi_dsi_enable(struct dw_mipi_dsi *dsi,
const struct drm_display_mode *adjusted_mode)
{
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
@@ -973,16 +976,30 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
{
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
- dw_mipi_dsi_mode_set(dsi, adjusted_mode);
+ dev_info(dsi->dev, "mode set\n");
+
+ /* Store the display mode for plugin/DKMS poweron events */
+ memcpy(&dsi->mode, mode, sizeof(dsi->mode));
+}
+
+static void dw_mipi_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+{
+ struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+
+ dev_info(dsi->dev, "pre enable\n");
+
+ /* power up the dsi ctl into a command mode */
+ dw_mipi_dsi_enable(dsi, &dsi->mode);
if (dsi->slave)
- dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
+ dw_mipi_dsi_enable(dsi->slave, &dsi->mode);
}
static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
{
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
- /* Switch to video mode for panel-bridge enable & panel enable */
+ dev_info(dsi->dev, "enable\n");
+
dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO);
if (dsi->slave)
dw_mipi_dsi_set_mode(dsi->slave, MIPI_DSI_MODE_VIDEO);
@@ -1033,7 +1050,9 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
.mode_set = dw_mipi_dsi_bridge_mode_set,
+ .pre_enable = dw_mipi_dsi_bridge_pre_enable,
.enable = dw_mipi_dsi_bridge_enable,
+ .disable = dw_mipi_dsi_bridge_disable,
.post_disable = dw_mipi_dsi_bridge_post_disable,
.mode_valid = dw_mipi_dsi_bridge_mode_valid,
.attach = dw_mipi_dsi_bridge_attach,

View File

@ -0,0 +1,28 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 16 Nov 2021 21:16:26 +0100
Subject: [PATCH 07/36] drm: dw-mipi-dsi-rockchip: Never allow lane bandwidth
to be less than requested
Bandwidth can be less than requested in some cases, because the search
for best values only checked for absolute difference from ideal value.
This is likely not intentional.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index 095d0f1..bd488a8 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -612,7 +612,7 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
continue;
delta = abs(fout - tmp);
- if (delta < min_delta) {
+ if (delta < min_delta && fout < tmp) {
best_prediv = _prediv;
best_fbdiv = _fbdiv;
min_delta = delta;

View File

@ -0,0 +1,23 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 20 Nov 2021 14:35:52 +0100
Subject: [PATCH 09/36] drm: rockchip: cdn-dp: Disable CDN DP on disconnect
Why not?
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/rockchip/cdn-dp-core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 16497c3..f4dcd9e 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -934,6 +934,7 @@ static void cdn_dp_pd_event_work(struct work_struct *work)
DRM_DEV_INFO(dp->dev, "Not connected. Disabling cdn\n");
dp->connected = false;
+ cdn_dp_disable(dp);
/* Connected but not enabled, enable the block */
} else if (!dp->active) {
DRM_DEV_INFO(dp->dev, "Connected, not enabled. Enabling cdn\n");

View File

@ -1,56 +0,0 @@
From 05044b9e4e4ae03f66e1c504d6fef57a1d135897 Mon Sep 17 00:00:00 2001
From: Dylan Van Assche <me@dylanvanassche.be>
Date: Thu, 24 Dec 2020 19:57:12 +0100
Subject: [PATCH] dts: pinephone: Add 'pine64,pinephone' to compat list
Indicates that all PinePhone models share most of the hardware with each other.
Used for feedbackd configuration when retrieving a device specific config for
haptic feedbackd.
---
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts | 2 +-
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts | 2 +-
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
index 0f6faa44c..2e0892b32 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
@@ -7,7 +7,7 @@
/ {
model = "Pine64 PinePhone Developer Batch (1.0)";
- compatible = "pine64,pinephone-1.0", "allwinner,sun50i-a64";
+ compatible = "pine64,pinephone-1.0", "pine64,pinephone", "allwinner,sun50i-a64";
reg_vbus: usb0-vbus {
compatible = "regulator-fixed";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
index 95a880fdc..d6bad0838 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
@@ -7,7 +7,7 @@
/ {
model = "Pine64 PinePhone Braveheart (1.1)";
- compatible = "pine64,pinephone-1.1", "allwinner,sun50i-a64";
+ compatible = "pine64,pinephone-1.1", "pine64,pinephone", "allwinner,sun50i-a64";
reg_vbus: usb0-vbus {
compatible = "regulator-fixed";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
index 23ba72508..710493186 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
@@ -7,7 +7,7 @@
/ {
model = "Pine64 PinePhone (1.2)";
- compatible = "pine64,pinephone-1.2", "allwinner,sun50i-a64";
+ compatible = "pine64,pinephone-1.2", "pine64,pinephone", "allwinner,sun50i-a64";
wifi_pwrseq: wifi-pwrseq {
compatible = "mmc-pwrseq-simple";
--
2.26.2

View File

@ -0,0 +1,69 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 17 Oct 2021 12:46:01 +0200
Subject: [PATCH 10/36] video: fbdev: Add events for early fb event support
This patch adds FB_EARLY_EVENT_BLANK and FB_R_EARLY_EVENT_BLANK
event mode supports. first, fb_notifier_call_chain() is called with
FB_EARLY_EVENT_BLANK and fb_blank() of specific fb driver is called
and then fb_notifier_call_chain() is called with FB_EVENT_BLANK again
at fb_blank(). and if fb_blank() was failed then fb_nitifier_call_chain()
would be called with FB_R_EARLY_EVENT_BLANK to revert the previous effects.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/video/fbdev/core/fbmem.c | 12 +++++++++++-
include/linux/fb.h | 5 +++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 826175a..fb1651a 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1067,7 +1067,7 @@ int
fb_blank(struct fb_info *info, int blank)
{
struct fb_event event;
- int ret = -EINVAL;
+ int ret = -EINVAL, early_ret;
if (blank > FB_BLANK_POWERDOWN)
blank = FB_BLANK_POWERDOWN;
@@ -1075,11 +1075,21 @@ fb_blank(struct fb_info *info, int blank)
event.info = info;
event.data = &blank;
+ early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
+
if (info->fbops->fb_blank)
ret = info->fbops->fb_blank(blank, info);
if (!ret)
fb_notifier_call_chain(FB_EVENT_BLANK, &event);
+ else {
+ /*
+ * if fb_blank is failed then revert effects of
+ * the early blank event.
+ */
+ if (!early_ret)
+ fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
+ }
return ret;
}
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 6f3db99..ffef502a 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -137,6 +137,11 @@ struct fb_cursor_user {
/* A display blank is requested */
#define FB_EVENT_BLANK 0x09
+/* A hardware display blank early change occured */
+#define FB_EARLY_EVENT_BLANK 0x10
+/* A hardware display blank revert early change occured */
+#define FB_R_EARLY_EVENT_BLANK 0x11
+
struct fb_event {
struct fb_info *info;
void *data;

View File

@ -1,29 +0,0 @@
From c965cb8a004c6cc370b4bf297c61fe5ac8ab0583 Mon Sep 17 00:00:00 2001
From: Martijn Braam <martijn@brixit.nl>
Date: Wed, 6 Jan 2021 03:11:17 +0100
Subject: [PATCH] arm64: dts: sunxi: Add mmc aliases for the PineTab
The order for the mmc devices changed in the kernel without this change.
Signed-off-by: Martijn Braam <martijn@brixit.nl>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
index a87790df94b3..1cf3c3a9ad7f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinetab.dts
@@ -18,6 +18,9 @@ / {
compatible = "pine64,pinetab", "allwinner,sun50i-a64";
aliases {
+ mmc0 = &mmc0;
+ mmc1 = &mmc1;
+ mmc2 = &mmc2;
serial0 = &uart0;
ethernet0 = &rtl8723cs;
};
--
2.29.2

View File

@ -0,0 +1,40 @@
From: =?utf-8?q?Kamil_Trzci=C5=84ski?= <ayufan@ayufan.eu>
Date: Mon, 4 Jan 2021 17:57:49 +0100
Subject: [PATCH 11/36] power: rk818: Configure `rk808-clkout2` function
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
???
Signed-of-by: Kamil Trzciński <ayufan@ayufan.eu>
---
drivers/mfd/rk808.c | 1 +
include/linux/mfd/rk808.h | 2 ++
2 files changed, 3 insertions(+)
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index b181fe4..1a6857e 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -303,6 +303,7 @@ static const struct rk808_reg_data rk818_pre_init_reg[] = {
{ RK818_H5V_EN_REG, BIT(0), RK818_H5V_EN },
{ RK808_VB_MON_REG, MASK_ALL, VB_LO_ACT |
VB_LO_SEL_3500MV },
+ { RK808_CLK32OUT_REG, CLK32KOUT2_FUNC_MASK, CLK32KOUT2_FUNC },
};
static const struct regmap_irq rk805_irqs[] = {
diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h
index a96e6d4..2ec0520 100644
--- a/include/linux/mfd/rk808.h
+++ b/include/linux/mfd/rk808.h
@@ -381,6 +381,8 @@ enum rk805_reg {
#define VOUT_LO_INT BIT(0)
#define CLK32KOUT2_EN BIT(0)
+#define CLK32KOUT2_FUNC (0 << 1)
+#define CLK32KOUT2_FUNC_MASK BIT(1)
#define TEMP115C 0x0c
#define TEMP_HOTDIE_MSK 0x0c

View File

@ -1,29 +0,0 @@
From d753557c64f6e85f63cffab53496d6271d724074 Mon Sep 17 00:00:00 2001
From: Martijn Braam <martijn@brixit.nl>
Date: Mon, 15 Feb 2021 13:10:37 -0800
Subject: [PATCH] pinephone: fix pogopin i2c
---
arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
index 39fdf96fe95d..7d0dd52e2f9d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
@@ -635,11 +635,7 @@ &pio {
vcc-pb-supply = <&reg_dcdc1>;
vcc-pc-supply = <&reg_dcdc1>;
vcc-pd-supply = <&reg_dcdc1>;
- /* pinctrl would enable this even if no camera is powered,
- * which is wrong/not necessary
- *
- * vcc-pe-supply = <&reg_aldo1>; (also used by pogo pins i2c)
- */
+ vcc-pe-supply = <&reg_aldo1>; /* (also used by pogo pins i2c) */
vcc-pf-supply = <&reg_dcdc1>;
vcc-pg-supply = <&reg_dldo4>;
vcc-ph-supply = <&reg_dcdc1>;
--
2.30.1

View File

@ -0,0 +1,46 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 19:30:07 +0100
Subject: [PATCH 13/36] power: supply: rk818-battery: Use a more propper
compatible string
Prefix with vendor name.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/mfd/rk808.c | 2 +-
drivers/power/supply/rk818_battery.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index 7d1f000..a99fec0 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -205,7 +205,7 @@ static const struct mfd_cell rk817s[] = {
static const struct mfd_cell rk818s[] = {
{ .name = "rk808-clkout", },
{ .name = "rk808-regulator", },
- { .name = "rk818-battery", .of_compatible = "rk818-battery", },
+ { .name = "rk818-battery", .of_compatible = "rockchip,rk818-battery", },
{
.name = "rk808-rtc",
.num_resources = ARRAY_SIZE(rtc_resources),
diff --git a/drivers/power/supply/rk818_battery.c b/drivers/power/supply/rk818_battery.c
index f09f456..665f043 100644
--- a/drivers/power/supply/rk818_battery.c
+++ b/drivers/power/supply/rk818_battery.c
@@ -3339,7 +3339,7 @@ static int rk818_bat_parse_dt(struct rk818_battery *di)
#endif
static const struct of_device_id rk818_battery_of_match[] = {
- {.compatible = "rk818-battery",},
+ { .compatible = "rockchip,rk818-battery", },
{ },
};
@@ -3565,4 +3565,4 @@ module_exit(battery_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rk818-battery");
-MODULE_AUTHOR("chenjh<chenjh@rock-chips.com>");
\ No newline at end of file
+MODULE_AUTHOR("chenjh<chenjh@rock-chips.com>");

View File

@ -0,0 +1,85 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 14 Nov 2021 21:24:05 +0100
Subject: [PATCH 14/36] power: supply: core: Don't ignore max_current of 0
when setting current limit
If we ignore current limit of 0, the dependent power source will not
set input current limit to that value when the supplier changes max
current to 0. This may happen when USB power is disconnected from the
device.
On next connection, the dependent power supply will start consuming
power at the previously set limit even before the PD/BC1.2 power
negotiation has a chance to complete.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/power/supply/power_supply_core.c | 47 ++++++++++++++------------------
1 file changed, 20 insertions(+), 27 deletions(-)
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index fc12a4f..f681372 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -375,41 +375,34 @@ int power_supply_is_system_supplied(void)
}
EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
-static int __power_supply_get_supplier_max_current(struct device *dev,
- void *data)
-{
- union power_supply_propval ret = {0,};
- struct power_supply *epsy = dev_get_drvdata(dev);
- struct power_supply *psy = data;
-
- if (__power_supply_is_supplied_by(epsy, psy))
- if (!epsy->desc->get_property(epsy,
- POWER_SUPPLY_PROP_CURRENT_MAX,
- &ret))
- return ret.intval;
-
- return 0;
-}
-
int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy)
{
union power_supply_propval val = {0,};
- int curr;
+ struct class_dev_iter iter;
+ struct power_supply *epsy;
+ struct device *dev;
+ int ret;
if (!psy->desc->set_property)
return -EINVAL;
- /*
- * This function is not intended for use with a supply with multiple
- * suppliers, we simply pick the first supply to report a non 0
- * max-current.
- */
- curr = class_for_each_device(power_supply_class, NULL, psy,
- __power_supply_get_supplier_max_current);
- if (curr <= 0)
- return (curr == 0) ? -ENODEV : curr;
+ class_dev_iter_init(&iter, power_supply_class, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
+ epsy = dev_get_drvdata(dev);
+
+ if (!__power_supply_is_supplied_by(epsy, psy))
+ continue;
- val.intval = curr;
+ ret = epsy->desc->get_property(epsy,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ &val);
+ if (!ret)
+ break;
+ }
+ class_dev_iter_exit(&iter);
+
+ if (ret)
+ return ret;
return psy->desc->set_property(psy,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);

View File

@ -0,0 +1,699 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 20:09:02 +0100
Subject: [PATCH 15/36] power: supply: rk818-charger: Implement charger driver
for RK818 PMIC
For now this driver is just meant to watch Type-C power supply
and apply current limits to RK818, to not overload the Type-C
partner.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/mfd/rk808.c | 1 +
drivers/power/supply/Kconfig | 8 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/rk818_charger.c | 637 +++++++++++++++++++++++++++++++++++
4 files changed, 647 insertions(+)
create mode 100644 drivers/power/supply/rk818_charger.c
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index a99fec0..75d18de 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -206,6 +206,7 @@ static const struct mfd_cell rk818s[] = {
{ .name = "rk808-clkout", },
{ .name = "rk808-regulator", },
{ .name = "rk818-battery", .of_compatible = "rockchip,rk818-battery", },
+ { .name = "rk818-charger", .of_compatible = "rockchip,rk818-charger", },
{
.name = "rk808-rtc",
.num_resources = ARRAY_SIZE(rtc_resources),
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index f5d4434..6bf0834 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -862,4 +862,12 @@ config BATTERY_RK818
If you say yes here you will get support for the battery of RK818 PMIC.
This driver can give support for Rk818 Battery Charge Interface.
+config CHARGER_RK818
+ bool "RK818 Charger driver"
+ depends on MFD_RK808
+ default n
+ help
+ If you say yes here you will get support for the charger of RK818 PMIC.
+ This driver can give support for Rk818 Charger Interface.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 1c725ee..3a1526f 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -105,3 +105,4 @@ obj-$(CONFIG_BATTERY_ACER_A500) += acer_a500_battery.o
obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
obj-$(CONFIG_BATTERY_RK818) += rk818_battery.o
+obj-$(CONFIG_CHARGER_RK818) += rk818_charger.o
diff --git a/drivers/power/supply/rk818_charger.c b/drivers/power/supply/rk818_charger.c
new file mode 100644
index 00000000..7b67a0b
--- /dev/null
+++ b/drivers/power/supply/rk818_charger.c
@@ -0,0 +1,637 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * rk818 usb power driver
+ *
+ * Copyright (c) 2021 Ondřej Jirman <megi@xff.cz>
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/mfd/rk808.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+
+#define RK818_CHG_STS_MASK (7u << 4) /* charger status */
+#define RK818_CHG_STS_NONE (0u << 4)
+#define RK818_CHG_STS_WAKEUP_CUR (1u << 4)
+#define RK818_CHG_STS_TRICKLE_CUR (2u << 4)
+#define RK818_CHG_STS_CC_OR_CV (3u << 4)
+#define RK818_CHG_STS_TERMINATED (4u << 4)
+#define RK818_CHG_STS_USB_OV (5u << 4)
+#define RK818_CHG_STS_BAT_TEMP_FAULT (6u << 4)
+#define RK818_CHG_STS_TIMEOUT (7u << 4)
+
+/* RK818_SUP_STS_REG */
+#define RK818_SUP_STS_USB_VLIM_EN BIT(3) /* input voltage limit enable */
+#define RK818_SUP_STS_USB_ILIM_EN BIT(2) /* input current limit enable */
+#define RK818_SUP_STS_USB_EXS BIT(1) /* USB power connected */
+#define RK818_SUP_STS_USB_EFF BIT(0) /* USB fault */
+
+/* RK818_USB_CTRL_REG */
+#define RK818_USB_CTRL_USB_ILIM_MASK (0xfu)
+#define RK818_USB_CTRL_USB_CHG_SD_VSEL_OFFSET 4
+#define RK818_USB_CTRL_USB_CHG_SD_VSEL_MASK (0x7u << 4)
+
+/* RK818_CHRG_CTRL_REG1 */
+#define RK818_CHRG_CTRL_REG1_CHRG_EN BIT(7)
+#define RK818_CHRG_CTRL_REG1_CHRG_VOL_SEL_OFFSET 4
+#define RK818_CHRG_CTRL_REG1_CHRG_VOL_SEL_MASK (0x7u << 4)
+#define RK818_CHRG_CTRL_REG1_CHRG_CUR_SEL_OFFSET 0
+#define RK818_CHRG_CTRL_REG1_CHRG_CUR_SEL_MASK (0xfu << 0)
+
+/* RK818_CHRG_CTRL_REG3 */
+#define RK818_CHRG_CTRL_REG3_CHRG_TERM_DIGITAL BIT(5)
+
+struct rk818_charger {
+ struct device *dev;
+ struct rk808 *rk818;
+ struct regmap *regmap;
+
+ struct power_supply *usb_psy;
+ struct power_supply *charger_psy;
+};
+
+// {{{ USB supply
+
+static int rk818_usb_set_input_current_max(struct rk818_charger *cg,
+ int val)
+{
+ int ret;
+ unsigned reg;
+
+ if (val < 450000)
+ reg = 1;
+ else if (val < 850000)
+ reg = 0;
+ else if (val < 1000000)
+ reg = 2;
+ else if (val < 3000000)
+ reg = 3 + (val - 1000000) / 250000;
+ else
+ reg = 11;
+
+ ret = regmap_update_bits(cg->regmap, RK818_USB_CTRL_REG,
+ RK818_USB_CTRL_USB_ILIM_MASK, reg);
+ if (ret)
+ dev_err(cg->dev,
+ "USB input current limit setting failed (%d)\n", ret);
+
+ return ret;
+}
+
+static int rk818_usb_get_input_current_max(struct rk818_charger *cg,
+ int *val)
+{
+ unsigned reg;
+ int ret;
+
+ ret = regmap_read(cg->regmap, RK818_USB_CTRL_REG, &reg);
+ if (ret) {
+ dev_err(cg->dev,
+ "USB input current limit getting failed (%d)\n", ret);
+ return ret;
+ }
+
+ reg &= RK818_USB_CTRL_USB_ILIM_MASK;
+ if (reg == 0)
+ *val = 450000;
+ else if (reg == 1)
+ *val = 80000;
+ else if (reg == 2)
+ *val = 850000;
+ else if (reg < 11)
+ *val = 1000000 + (reg - 3) * 250000;
+ else
+ *val = 3000000;
+
+ return 0;
+}
+
+static int rk818_usb_set_input_voltage_min(struct rk818_charger *cg,
+ int val)
+{
+ unsigned reg;
+ int ret;
+
+ if (val < 2780000)
+ reg = 0;
+ else if (val < 3270000)
+ reg = (val - 2780000) / 70000;
+ else
+ reg = 7;
+
+ ret = regmap_update_bits(cg->regmap, RK818_USB_CTRL_REG,
+ RK818_USB_CTRL_USB_CHG_SD_VSEL_MASK,
+ reg << RK818_USB_CTRL_USB_CHG_SD_VSEL_OFFSET);
+ if (ret)
+ dev_err(cg->dev,
+ "USB input voltage limit setting failed (%d)\n", ret);
+
+ return ret;
+}
+
+static int rk818_usb_get_input_voltage_min(struct rk818_charger *cg,
+ int *val)
+{
+ unsigned reg;
+ int ret;
+
+ ret = regmap_read(cg->regmap, RK818_USB_CTRL_REG, &reg);
+ if (ret) {
+ dev_err(cg->dev,
+ "USB input voltage limit getting failed (%d)\n", ret);
+ return ret;
+ }
+
+ reg &= RK818_USB_CTRL_USB_CHG_SD_VSEL_MASK;
+ reg >>= RK818_USB_CTRL_USB_CHG_SD_VSEL_OFFSET;
+
+ *val = 2780000 + (reg * 70000);
+
+ return 0;
+}
+
+static int rk818_usb_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct rk818_charger *cg = power_supply_get_drvdata(psy);
+ unsigned reg;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = regmap_read(cg->regmap, RK818_SUP_STS_REG, &reg);
+ if (ret)
+ return ret;
+
+ val->intval = !!(reg & RK818_SUP_STS_USB_EXS);
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = regmap_read(cg->regmap, RK818_SUP_STS_REG, &reg);
+ if (ret)
+ return ret;
+
+ if (!(reg & RK818_SUP_STS_USB_EXS)) {
+ val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+ } else if (reg & RK818_SUP_STS_USB_EFF) {
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ } else {
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ }
+
+ break;
+
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ return rk818_usb_get_input_voltage_min(cg, &val->intval);
+
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return rk818_usb_get_input_current_max(cg, &val->intval);
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk818_usb_power_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct rk818_charger *cg = power_supply_get_drvdata(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ return rk818_usb_set_input_voltage_min(cg, val->intval);
+
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ return rk818_usb_set_input_current_max(cg, val->intval);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int rk818_usb_power_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+ case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Sync the input-current-limit with our parent supply (if we have one) */
+static void rk818_usb_power_external_power_changed(struct power_supply *psy)
+{
+ struct rk818_charger *cg = power_supply_get_drvdata(psy);
+
+ power_supply_set_input_current_limit_from_supplier(cg->usb_psy);
+}
+
+static enum power_supply_property rk818_usb_power_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+ POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
+};
+
+static const struct power_supply_desc rk818_usb_desc = {
+ .name = "rk818-usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .properties = rk818_usb_power_props,
+ .num_properties = ARRAY_SIZE(rk818_usb_power_props),
+ .property_is_writeable = rk818_usb_power_prop_writeable,
+ .get_property = rk818_usb_power_get_property,
+ .set_property = rk818_usb_power_set_property,
+ .external_power_changed = rk818_usb_power_external_power_changed,
+};
+
+// }}}
+// {{{ Charger supply
+
+static int rk818_charger_set_current_max(struct rk818_charger *cg, int val)
+{
+ unsigned reg;
+ int ret;
+
+ if (val < 1000000)
+ reg = 0;
+ else if (val < 3000000)
+ reg = (val - 1000000) / 200000;
+ else
+ reg = 10;
+
+ ret = regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG1,
+ RK818_CHRG_CTRL_REG1_CHRG_CUR_SEL_MASK,
+ reg << RK818_CHRG_CTRL_REG1_CHRG_CUR_SEL_OFFSET);
+ if (ret)
+ dev_err(cg->dev,
+ "Charging max current setting failed (%d)\n", ret);
+
+ return ret;
+}
+
+static int rk818_charger_get_current_max(struct rk818_charger *cg, int *val)
+{
+ unsigned reg;
+ int ret;
+
+ ret = regmap_read(cg->regmap, RK818_CHRG_CTRL_REG1, &reg);
+ if (ret) {
+ dev_err(cg->dev,
+ "Charging max current getting failed (%d)\n", ret);
+ return ret;
+ }
+
+ reg &= RK818_CHRG_CTRL_REG1_CHRG_CUR_SEL_MASK;
+ reg >>= RK818_CHRG_CTRL_REG1_CHRG_CUR_SEL_OFFSET;
+
+ *val = 1000000 + reg * 200000;
+
+ return 0;
+}
+
+static int rk818_charger_set_voltage_max(struct rk818_charger *cg, int val)
+{
+ unsigned reg;
+ int ret;
+
+ if (val < 4050000)
+ reg = 0;
+ else if (val < 4350000)
+ reg = (val - 4050000) / 50000;
+ else
+ reg = 6;
+
+ ret = regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG1,
+ RK818_CHRG_CTRL_REG1_CHRG_VOL_SEL_MASK,
+ reg << RK818_CHRG_CTRL_REG1_CHRG_VOL_SEL_OFFSET);
+ if (ret)
+ dev_err(cg->dev,
+ "Charging end voltage setting failed (%d)\n", ret);
+
+ return ret;
+}
+
+static int rk818_charger_get_voltage_max(struct rk818_charger *cg, int *val)
+{
+ unsigned reg;
+ int ret;
+
+ ret = regmap_read(cg->regmap, RK818_CHRG_CTRL_REG1, &reg);
+ if (ret) {
+ dev_err(cg->dev,
+ "Charging end voltage getting failed (%d)\n", ret);
+ return ret;
+ }
+
+ reg &= RK818_CHRG_CTRL_REG1_CHRG_VOL_SEL_MASK;
+ reg >>= RK818_CHRG_CTRL_REG1_CHRG_VOL_SEL_OFFSET;
+
+ *val = 4050000 + reg * 50000;
+
+ return 0;
+}
+
+static int rk818_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct rk818_charger *cg = power_supply_get_drvdata(psy);
+ unsigned reg;
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = regmap_read(cg->regmap, RK818_CHRG_CTRL_REG1, &reg);
+ if (ret) {
+ dev_err(cg->dev, "failed to read the charger state (%d)\n", ret);
+ return ret;
+ }
+
+ val->intval = !!(reg & RK818_CHRG_CTRL_REG1_CHRG_EN);
+ break;
+
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = regmap_read(cg->regmap, RK818_SUP_STS_REG, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg & RK818_CHG_STS_MASK) {
+ case RK818_CHG_STS_WAKEUP_CUR:
+ case RK818_CHG_STS_TRICKLE_CUR:
+ case RK818_CHG_STS_CC_OR_CV:
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ case RK818_CHG_STS_TERMINATED:
+ default:
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ }
+
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ ret = regmap_read(cg->regmap, RK818_SUP_STS_REG, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg & RK818_CHG_STS_MASK) {
+ case RK818_CHG_STS_WAKEUP_CUR:
+ case RK818_CHG_STS_TRICKLE_CUR:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case RK818_CHG_STS_CC_OR_CV:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ break;
+ case RK818_CHG_STS_TERMINATED:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
+ break;
+ }
+
+ break;
+
+ case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+ ret = regmap_read(cg->regmap, RK818_CHRG_CTRL_REG2, &reg);
+ if (ret)
+ return ret;
+
+ val->intval = 100000 + ((reg >> 6) & 3) * 50000;
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = regmap_read(cg->regmap, RK818_SUP_STS_REG, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg & RK818_CHG_STS_MASK) {
+ case RK818_CHG_STS_USB_OV:
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+ case RK818_CHG_STS_BAT_TEMP_FAULT:
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ break;
+ case RK818_CHG_STS_TIMEOUT:
+ val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ }
+
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ return rk818_charger_get_voltage_max(cg, &val->intval);
+
+ case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+ ret = rk818_charger_get_current_max(cg, &val->intval);
+ val->intval /= 10;
+ return ret;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ return rk818_charger_get_current_max(cg, &val->intval);
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+ val->intval = 4350000;
+ break;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ val->intval = 3000000;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rk818_charger_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct rk818_charger *cg = power_supply_get_drvdata(psy);
+ int ret;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG1,
+ RK818_CHRG_CTRL_REG1_CHRG_EN,
+ val->intval ? RK818_CHRG_CTRL_REG1_CHRG_EN : 0);
+ if (ret)
+ dev_err(cg->dev, "failed to setup the charger (%d)\n", ret);
+
+ return ret;
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ return rk818_charger_set_voltage_max(cg, val->intval);
+
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ return rk818_charger_set_current_max(cg, val->intval);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int rk818_charger_prop_writeable(struct power_supply *psy,
+ enum power_supply_property psp)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+ case POWER_SUPPLY_PROP_ONLINE:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+static enum power_supply_property rk818_charger_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+};
+
+/*
+ * TODO: This functionality should be in a battery driver/supply, but that one
+ * is such a mess, I don't want to touch it now. Let's have a separate supply
+ * for controlling the charger for now, and a prayer for the poor soul that
+ * will have to understand and clean up the battery driver.
+ */
+static const struct power_supply_desc rk818_charger_desc = {
+ .name = "rk818-charger",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = rk818_charger_props,
+ .num_properties = ARRAY_SIZE(rk818_charger_props),
+ .property_is_writeable = rk818_charger_prop_writeable,
+ .get_property = rk818_charger_get_property,
+ .set_property = rk818_charger_set_property,
+};
+
+// }}}
+
+static int rk818_charger_probe(struct platform_device *pdev)
+{
+ struct rk808 *rk818 = dev_get_drvdata(pdev->dev.parent);
+ struct power_supply_config psy_cfg = { };
+ struct device *dev = &pdev->dev;
+ struct rk818_charger *cg;
+ int ret;
+
+ cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
+ if (!cg)
+ return -ENOMEM;
+
+ cg->rk818 = rk818;
+ cg->dev = dev;
+ cg->regmap = rk818->regmap;
+ platform_set_drvdata(pdev, cg);
+
+ psy_cfg.drv_data = cg;
+ psy_cfg.of_node = dev->of_node;
+
+ cg->usb_psy = devm_power_supply_register(dev, &rk818_usb_desc,
+ &psy_cfg);
+ if (IS_ERR(cg->usb_psy))
+ return dev_err_probe(dev, PTR_ERR(cg->usb_psy),
+ "register usb power supply fail\n");
+
+ cg->charger_psy = devm_power_supply_register(dev, &rk818_charger_desc,
+ &psy_cfg);
+ if (IS_ERR(cg->charger_psy))
+ return dev_err_probe(dev, PTR_ERR(cg->charger_psy),
+ "register charger power supply fail\n");
+
+ /* disable voltage limit and enable input current limit */
+ ret = regmap_update_bits(cg->regmap, RK818_SUP_STS_REG,
+ RK818_SUP_STS_USB_ILIM_EN | RK818_SUP_STS_USB_VLIM_EN,
+ RK818_SUP_STS_USB_ILIM_EN);
+ if (ret)
+ dev_warn(cg->dev, "failed to enable input current limit (%d)\n", ret);
+
+ /* make sure analog control loop is enabled */
+ ret = regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG3,
+ RK818_CHRG_CTRL_REG3_CHRG_TERM_DIGITAL,
+ 0);
+ if (ret)
+ dev_warn(cg->dev, "failed to enable analog control loop (%d)\n", ret);
+
+ /* enable charger and set some reasonable limits on each boot */
+ ret = regmap_write(cg->regmap, RK818_CHRG_CTRL_REG1,
+ RK818_CHRG_CTRL_REG1_CHRG_EN
+ | (1) /* 1.2A */
+ | (5 << 4) /* 4.3V */);
+ if (ret)
+ dev_warn(cg->dev, "failed to enable charger (%d)\n", ret);
+
+ power_supply_set_input_current_limit_from_supplier(cg->usb_psy);
+
+ return 0;
+}
+
+static int rk818_charger_remove(struct platform_device *pdev)
+{
+ //struct rk818_charger *cg = platform_get_drvdata(pdev);
+
+ return 0;
+}
+
+static void rk818_charger_shutdown(struct platform_device *pdev)
+{
+}
+
+static int rk818_charger_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ return 0;
+}
+
+static int rk818_charger_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id rk818_charger_of_match[] = {
+ { .compatible = "rockchip,rk818-charger", },
+ { },
+};
+
+static struct platform_driver rk818_charger_driver = {
+ .probe = rk818_charger_probe,
+ .remove = rk818_charger_remove,
+ .suspend = rk818_charger_suspend,
+ .resume = rk818_charger_resume,
+ .shutdown = rk818_charger_shutdown,
+ .driver = {
+ .name = "rk818-charger",
+ .of_match_table = rk818_charger_of_match,
+ },
+};
+
+module_platform_driver(rk818_charger_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rk818-charger");
+MODULE_AUTHOR("Ondřej Jirman <megi@xff.cz>");

View File

@ -0,0 +1,47 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 19:28:27 +0100
Subject: [PATCH 26/36] usb: typec: fusb302: Set the current before enabling
pullups
This seems more reasonable and should avoid short period of incorrect
current setting being applied to CC pin.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 72f9001..776a949 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -635,6 +635,14 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
goto done;
}
+ /* adjust current for SRC */
+ ret = fusb302_set_src_current(chip, cc_src_current[cc]);
+ if (ret < 0) {
+ fusb302_log(chip, "cannot set src current %s, ret=%d",
+ typec_cc_status_name[cc], ret);
+ goto done;
+ }
+
ret = fusb302_i2c_mask_write(chip, FUSB_REG_SWITCHES0,
switches0_mask, switches0_data);
if (ret < 0) {
@@ -645,14 +653,6 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc)
chip->cc1 = TYPEC_CC_OPEN;
chip->cc2 = TYPEC_CC_OPEN;
- /* adjust current for SRC */
- ret = fusb302_set_src_current(chip, cc_src_current[cc]);
- if (ret < 0) {
- fusb302_log(chip, "cannot set src current %s, ret=%d",
- typec_cc_status_name[cc], ret);
- goto done;
- }
-
/* enable/disable interrupts, BC_LVL for SNK and COMP_CHNG for SRC */
switch (cc) {
case TYPEC_CC_RP_DEF:

View File

@ -0,0 +1,108 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 19:29:06 +0100
Subject: [PATCH 27/36] usb: typec: fusb302: Extend debugging interface with
driver state dumps
This is useful for debugging.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 78 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 776a949..1a758e3 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -207,6 +207,81 @@ static int fusb302_debug_show(struct seq_file *s, void *v)
}
DEFINE_SHOW_ATTRIBUTE(fusb302_debug);
+static const char * const typec_cc_status_name[];
+static const char * const cc_polarity_name[];
+static const char * const toggling_mode_name[] = {
+ [TOGGLING_MODE_OFF] = "Off",
+ [TOGGLING_MODE_DRP] = "DRP",
+ [TOGGLING_MODE_SNK] = "SNK",
+ [TOGGLING_MODE_SRC] = "SRC",
+};
+static const char * const src_current_status_name[] = {
+ [SRC_CURRENT_DEFAULT] = "Default",
+ [SRC_CURRENT_MEDIUM] = "Medium",
+ [SRC_CURRENT_HIGH] = "High",
+};
+
+#define FUSB_REG(n) { n, #n },
+struct fusb_reg {
+ u8 addr;
+ const char* name;
+} fusb_regs[] = {
+ FUSB_REG(FUSB_REG_DEVICE_ID)
+ FUSB_REG(FUSB_REG_SWITCHES0)
+ FUSB_REG(FUSB_REG_SWITCHES1)
+ FUSB_REG(FUSB_REG_MEASURE)
+ FUSB_REG(FUSB_REG_CONTROL0)
+ FUSB_REG(FUSB_REG_CONTROL1)
+ FUSB_REG(FUSB_REG_CONTROL2)
+ FUSB_REG(FUSB_REG_CONTROL3)
+ FUSB_REG(FUSB_REG_MASK)
+ FUSB_REG(FUSB_REG_POWER)
+ FUSB_REG(FUSB_REG_RESET)
+ FUSB_REG(FUSB_REG_MASKA)
+ FUSB_REG(FUSB_REG_MASKB)
+ FUSB_REG(FUSB_REG_STATUS0A)
+ FUSB_REG(FUSB_REG_STATUS1A)
+ FUSB_REG(FUSB_REG_INTERRUPTA)
+ FUSB_REG(FUSB_REG_INTERRUPTB)
+ FUSB_REG(FUSB_REG_STATUS0)
+ FUSB_REG(FUSB_REG_STATUS1)
+ FUSB_REG(FUSB_REG_INTERRUPT)
+};
+
+static int fusb302_i2c_read(struct fusb302_chip *chip,
+ u8 address, u8 *data);
+
+static int fusb302_debug_regs_show(struct seq_file *s, void *v)
+{
+ struct fusb302_chip *chip = (struct fusb302_chip *)s->private;
+ int i, ret;
+
+ seq_printf(s, "chip->intr_togdone = %d\n", chip->intr_togdone);
+ seq_printf(s, "chip->intr_bc_lvl = %d\n", chip->intr_bc_lvl);
+ seq_printf(s, "chip->intr_comp_chng = %d\n", chip->intr_comp_chng);
+ seq_printf(s, "chip->vconn_on = %d\n", chip->vconn_on);
+ seq_printf(s, "chip->vbus_on = %d\n", chip->vbus_on);
+ seq_printf(s, "chip->charge_on = %d\n", chip->charge_on);
+ seq_printf(s, "chip->vbus_present = %d\n", chip->vbus_present);
+ seq_printf(s, "chip->cc_polarity = %s\n", cc_polarity_name[chip->cc_polarity]);
+ seq_printf(s, "chip->cc1 = %s\n", typec_cc_status_name[chip->cc1]);
+ seq_printf(s, "chip->cc2 = %s\n", typec_cc_status_name[chip->cc2]);
+ seq_printf(s, "chip->toggling_mode = %s\n", toggling_mode_name[chip->toggling_mode]);
+ seq_printf(s, "chip->src_current_status = %s\n", src_current_status_name[chip->src_current_status]);
+
+ seq_printf(s, "\nRegisters:\n");
+ for (i = 0; i < ARRAY_SIZE(fusb_regs); i++) {
+ u8 val = 0;
+
+ ret = fusb302_i2c_read(chip, fusb_regs[i].addr, &val);
+ if (ret >= 0)
+ seq_printf(s, "%s = %02hhx\n", fusb_regs[i].name, val);
+ }
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(fusb302_debug_regs);
+
static void fusb302_debugfs_init(struct fusb302_chip *chip)
{
char name[NAME_MAX];
@@ -216,6 +291,9 @@ static void fusb302_debugfs_init(struct fusb302_chip *chip)
chip->dentry = debugfs_create_dir(name, usb_debug_root);
debugfs_create_file("log", S_IFREG | 0444, chip->dentry, chip,
&fusb302_debug_fops);
+
+ debugfs_create_file("regs", S_IFREG | 0444, chip->dentry, chip,
+ &fusb302_debug_regs_fops);
}
static void fusb302_debugfs_exit(struct fusb302_chip *chip)

View File

@ -0,0 +1,72 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 23 Nov 2021 17:53:27 +0100
Subject: [PATCH 28/36] usb: typec: fusb302: Retry reading of CC pins status
if activity is detected
This is just for testing, to see if this ever happens. It should
also help when this happens.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 1a758e3..7386805 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -1317,6 +1317,36 @@ static int fusb302_handle_togdone_snk(struct fusb302_chip *chip,
return ret;
}
+static int fusb302_get_status0_stable(struct fusb302_chip *chip, u8 *status0)
+{
+ int ret, tries = 0;
+ u8 reg;
+
+try_again:
+ ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &reg);
+ if (ret < 0)
+ return ret;
+
+ if (reg & FUSB_REG_STATUS0_ACTIVITY) {
+ fusb302_log(chip, "activity reading CC status");
+ if (++tries == 5) {
+ fusb302_log(chip, "failed to read stable status0 value");
+
+ /*
+ * The best we can do is to return at least something.
+ */
+ *status0 = reg;
+ return 0;
+ }
+
+ usleep_range(50, 100);
+ goto try_again;
+ }
+
+ *status0 = reg;
+ return 0;
+}
+
/* On error returns < 0, otherwise a typec_cc_status value */
static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
enum typec_cc_polarity cc_polarity,
@@ -1344,7 +1374,7 @@ static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
return ret;
usleep_range(50, 100);
- ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
+ ret = fusb302_get_status0_stable(chip, &status0);
if (ret < 0)
return ret;
@@ -1360,7 +1390,7 @@ static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
return ret;
usleep_range(50, 100);
- ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
+ ret = fusb302_get_status0_stable(chip, &status0);
if (ret < 0)
return ret;

View File

@ -0,0 +1,186 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 23 Nov 2021 17:55:34 +0100
Subject: [PATCH 29/36] usb: typec: fusb302: More useful of logging status on
interrupt
This is just for debugging. It prints more info that's useful to
see how hardware state changes in time.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 121 +++++++++++++++++++++++++++++++++------
1 file changed, 104 insertions(+), 17 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 7386805..70b0e15 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -68,7 +68,7 @@ static const u8 rd_mda_value[] = {
};
#define LOG_BUFFER_ENTRIES 1024
-#define LOG_BUFFER_ENTRY_SIZE 128
+#define LOG_BUFFER_ENTRY_SIZE 256
struct fusb302_chip {
struct device *dev;
@@ -1598,6 +1598,84 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void fusb302_print_state(struct fusb302_chip *chip)
+{
+ u8 ctl0, ctl2, measure, status0, status1a, sw0, mask;
+ int ret;
+
+ ret = fusb302_i2c_read(chip, FUSB_REG_CONTROL0, &ctl0);
+ if (ret < 0)
+ return;
+ ret = fusb302_i2c_read(chip, FUSB_REG_CONTROL2, &ctl2);
+ if (ret < 0)
+ return;
+ ret = fusb302_i2c_read(chip, FUSB_REG_MEASURE, &measure);
+ if (ret < 0)
+ return;
+ ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
+ if (ret < 0)
+ return;
+ ret = fusb302_i2c_read(chip, FUSB_REG_STATUS1A, &status1a);
+ if (ret < 0)
+ return;
+ ret = fusb302_i2c_read(chip, FUSB_REG_SWITCHES0, &sw0);
+ if (ret < 0)
+ return;
+ ret = fusb302_i2c_read(chip, FUSB_REG_MASK, &mask);
+ if (ret < 0)
+ return;
+
+ //FUSB_REG(FUSB_REG_POWER) // power control
+
+ const char* host_cur = "?";
+ switch ((ctl0 >> 2) & 3) {
+ case 0: host_cur = "none"; break;
+ case 1: host_cur = "80uA"; break;
+ case 2: host_cur = "160uA"; break;
+ case 3: host_cur = "330uA"; break;
+ }
+
+ const char* bc_lvl = "?";
+ switch (status0 & 3) {
+ case 0: bc_lvl = "0-200mV"; break;
+ case 1: bc_lvl = "200-660mV"; break;
+ case 2: bc_lvl = "660-1230mV"; break;
+ case 3: bc_lvl = ">1230mV"; break;
+ }
+
+ // status0
+ unsigned vbusok = !!(status0 & BIT(7));
+ unsigned activity = !!(status0 & BIT(6));
+ unsigned comp = !!(status0 & BIT(5));
+ unsigned wake = !!(status0 & BIT(2));
+
+ // measure
+ unsigned mdac = ((measure & 0x3f) + 1) * 42 * (measure & BIT(6) ? 10 : 1);
+
+ // status1a
+ unsigned togss = (status1a >> 3) & 7;
+ const char* togss_s = "?";
+ switch (togss) {
+ case 0: togss_s = "running"; break;
+ case 1: togss_s = "src1"; break;
+ case 2: togss_s = "src2"; break;
+ case 5: togss_s = "snk1"; break;
+ case 6: togss_s = "snk2"; break;
+ case 7: togss_s = "audio"; break;
+ }
+
+ // ctl2 print as is
+
+#define SW(n) (!!(sw0 & BIT(n)))
+
+ fusb302_log(chip, "state: cc(puen=%u%u vconn=%u%u meas=%u%u pdwn=%u%u) "
+ "host_cur=%s mdac=%umV comp=%u bc_lvl=%s vbusok=%u act=%u "
+ "wake=%u togss=%s ctl2=0x%02x mask=0x%02x",
+ SW(6), SW(7), SW(4), SW(5), SW(2), SW(3), SW(0), SW(1),
+ host_cur, mdac, comp, bc_lvl, vbusok, activity,
+ wake, togss_s, ctl2, mask);
+}
+
static void fusb302_irq_work(struct work_struct *work)
{
struct fusb302_chip *chip = container_of(work, struct fusb302_chip,
@@ -1607,6 +1685,7 @@ static void fusb302_irq_work(struct work_struct *work)
u8 interrupta;
u8 interruptb;
u8 status0;
+ u8 mda;
bool vbus_present;
bool comp_result;
bool intr_togdone;
@@ -1632,9 +1711,10 @@ static void fusb302_irq_work(struct work_struct *work)
ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &status0);
if (ret < 0)
goto done;
- fusb302_log(chip,
- "IRQ: 0x%02x, a: 0x%02x, b: 0x%02x, status0: 0x%02x",
- interrupt, interrupta, interruptb, status0);
+ fusb302_log(chip, "IRQ: 0x%02x, a: 0x%02x, b: 0x%02x",
+ interrupt, interrupta, interruptb);
+
+ fusb302_print_state(chip);
if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) {
vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK);
@@ -1646,32 +1726,39 @@ static void fusb302_irq_work(struct work_struct *work)
}
}
- if ((interrupta & FUSB_REG_INTERRUPTA_TOGDONE) && intr_togdone) {
+ if (interrupta & FUSB_REG_INTERRUPTA_TOGDONE) {
fusb302_log(chip, "IRQ: TOGDONE");
- ret = fusb302_handle_togdone(chip);
- if (ret < 0) {
- fusb302_log(chip,
- "handle togdone error, ret=%d", ret);
- goto done;
+ if (intr_togdone) {
+ ret = fusb302_handle_togdone(chip);
+ if (ret < 0) {
+ fusb302_log(chip,
+ "handle togdone error, ret=%d", ret);
+ goto done;
+ }
}
}
- if ((interrupt & FUSB_REG_INTERRUPT_BC_LVL) && intr_bc_lvl) {
+ if (interrupt & FUSB_REG_INTERRUPT_BC_LVL) {
fusb302_log(chip, "IRQ: BC_LVL, handler pending");
/*
* as BC_LVL interrupt can be affected by PD activity,
* apply delay to for the handler to wait for the PD
* signaling to finish.
*/
- mod_delayed_work(chip->wq, &chip->bc_lvl_handler,
- msecs_to_jiffies(T_BC_LVL_DEBOUNCE_DELAY_MS));
+ if (intr_bc_lvl)
+ mod_delayed_work(chip->wq, &chip->bc_lvl_handler,
+ msecs_to_jiffies(T_BC_LVL_DEBOUNCE_DELAY_MS));
}
- if ((interrupt & FUSB_REG_INTERRUPT_COMP_CHNG) && intr_comp_chng) {
+ if (interrupt & FUSB_REG_INTERRUPT_COMP_CHNG) {
+ ret = fusb302_i2c_read(chip, FUSB_REG_MEASURE, &mda);
+ if (ret < 0)
+ goto done;
+
comp_result = !!(status0 & FUSB_REG_STATUS0_COMP);
- fusb302_log(chip, "IRQ: COMP_CHNG, comp=%s",
- comp_result ? "true" : "false");
- if (comp_result) {
+ fusb302_log(chip, "IRQ: COMP_CHNG, cc* %s mdac (%u mV)",
+ comp_result ? ">" : "<", ((mda & 0x3f) + 1) * 42 * (mda & BIT(6) ? 10 : 1));
+ if (comp_result && intr_comp_chng) {
/* cc level > Rd_threshold, detach */
chip->cc1 = TYPEC_CC_OPEN;
chip->cc2 = TYPEC_CC_OPEN;

View File

@ -0,0 +1,39 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 23 Nov 2021 17:57:06 +0100
Subject: [PATCH 30/36] usb: typec: fusb302: Update VBUS state even if VBUS
interrupt is not triggered
This seems to improve robustness.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 70b0e15..1d5affa 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -1716,14 +1716,16 @@ static void fusb302_irq_work(struct work_struct *work)
fusb302_print_state(chip);
- if (interrupt & FUSB_REG_INTERRUPT_VBUSOK) {
- vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK);
+ vbus_present = !!(status0 & FUSB_REG_STATUS0_VBUSOK);
+ if (interrupt & FUSB_REG_INTERRUPT_VBUSOK)
fusb302_log(chip, "IRQ: VBUS_OK, vbus=%s",
vbus_present ? "On" : "Off");
- if (vbus_present != chip->vbus_present) {
- chip->vbus_present = vbus_present;
- tcpm_vbus_change(chip->tcpm_port);
- }
+ if (vbus_present != chip->vbus_present) {
+ chip->vbus_present = vbus_present;
+ if (!(interrupt & FUSB_REG_INTERRUPT_VBUSOK))
+ fusb302_log(chip, "IRQ: VBUS changed without interrupt, vbus=%s",
+ vbus_present ? "On" : "Off");
+ tcpm_vbus_change(chip->tcpm_port);
}
if (interrupta & FUSB_REG_INTERRUPTA_TOGDONE) {

View File

@ -0,0 +1,160 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 23 Nov 2021 17:58:05 +0100
Subject: [PATCH 31/36] usb: typec: fusb302: Make tcpm/fusb302 logs less
polluted by PD comm stuff
This adds clarity to debugging.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 18 ++++++++++--------
drivers/usb/typec/tcpm/tcpm.c | 18 ++++++++++--------
2 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 1d5affa..ae3b930 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -787,7 +787,7 @@ static int tcpm_get_cc(struct tcpc_dev *dev, enum typec_cc_status *cc1,
mutex_lock(&chip->lock);
*cc1 = chip->cc1;
*cc2 = chip->cc2;
- fusb302_log(chip, "cc1=%s, cc2=%s", typec_cc_status_name[*cc1],
+ fusb302_log(chip, "tcpm_get_cc => cc1=%s, cc2=%s (cached)", typec_cc_status_name[*cc1],
typec_cc_status_name[*cc2]);
mutex_unlock(&chip->lock);
@@ -1073,8 +1073,8 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip,
ret = fusb302_i2c_block_write(chip, FUSB_REG_FIFOS, pos, buf);
if (ret < 0)
return ret;
- fusb302_log(chip, "sending PD message header: %x", msg->header);
- fusb302_log(chip, "sending PD message len: %d", len);
+ //fusb302_log(chip, "sending PD message header: %x", msg->header);
+ //fusb302_log(chip, "sending PD message len: %d", len);
return ret;
}
@@ -1365,8 +1365,10 @@ static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
if (ret < 0)
return ret;
+ //XXX resolve activity conflicts while measuring
+
fusb302_i2c_read(chip, FUSB_REG_SWITCHES0, &status0);
- fusb302_log(chip, "get_src_cc_status switches: 0x%0x", status0);
+ //fusb302_log(chip, "get_src_cc_status switches: 0x%0x", status0);
/* Step 2: Set compararator volt to differentiate between Open and Rd */
ret = fusb302_i2c_write(chip, FUSB_REG_MEASURE, rd_mda);
@@ -1378,7 +1380,7 @@ static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
if (ret < 0)
return ret;
- fusb302_log(chip, "get_src_cc_status rd_mda status0: 0x%0x", status0);
+ //fusb302_log(chip, "get_src_cc_status rd_mda status0: 0x%0x", status0);
if (status0 & FUSB_REG_STATUS0_COMP) {
*cc = TYPEC_CC_OPEN;
return 0;
@@ -1394,7 +1396,7 @@ static int fusb302_get_src_cc_status(struct fusb302_chip *chip,
if (ret < 0)
return ret;
- fusb302_log(chip, "get_src_cc_status ra_mda status0: 0x%0x", status0);
+ //fusb302_log(chip, "get_src_cc_status ra_mda status0: 0x%0x", status0);
if (status0 & FUSB_REG_STATUS0_COMP)
*cc = TYPEC_CC_RD;
else
@@ -1559,8 +1561,8 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
ret = fusb302_i2c_block_read(chip, FUSB_REG_FIFOS, 4, crc);
if (ret < 0)
return ret;
- fusb302_log(chip, "PD message header: %x", msg->header);
- fusb302_log(chip, "PD message len: %d", len);
+ //fusb302_log(chip, "PD message header: %x", msg->header);
+ //fusb302_log(chip, "PD message len: %d", len);
/*
* Check if we've read off a GoodCRC message. If so then indicate to
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 59d4fa2..0451441 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -776,7 +776,7 @@ static void tcpm_debugfs_exit(const struct tcpm_port *port) { }
static void tcpm_set_cc(struct tcpm_port *port, enum typec_cc_status cc)
{
- tcpm_log(port, "cc:=%d", cc);
+ //tcpm_log(port, "cc:=%d", cc);
port->cc_req = cc;
port->tcpc->set_cc(port->tcpc, cc);
}
@@ -869,10 +869,12 @@ static int tcpm_pd_transmit(struct tcpm_port *port,
unsigned long timeout;
int ret;
+ /*
if (msg)
tcpm_log(port, "PD TX, header: %#x", le16_to_cpu(msg->header));
else
tcpm_log(port, "PD TX, type: %#x", type);
+ */
reinit_completion(&port->tx_complete);
ret = port->tcpc->pd_transmit(port->tcpc, type, msg, port->negotiated_rev);
@@ -918,7 +920,7 @@ static int tcpm_pd_transmit(struct tcpm_port *port,
void tcpm_pd_transmit_complete(struct tcpm_port *port,
enum tcpm_transmit_status status)
{
- tcpm_log(port, "PD TX complete, status: %u", status);
+ //tcpm_log(port, "PD TX complete, status: %u", status);
port->tx_status = status;
complete(&port->tx_complete);
}
@@ -951,7 +953,7 @@ static int tcpm_set_polarity(struct tcpm_port *port,
{
int ret;
- tcpm_log(port, "polarity %d", polarity);
+ //tcpm_log(port, "polarity %d", polarity);
ret = port->tcpc->set_polarity(port->tcpc, polarity);
if (ret < 0)
@@ -966,7 +968,7 @@ static int tcpm_set_vconn(struct tcpm_port *port, bool enable)
{
int ret;
- tcpm_log(port, "vconn:=%d", enable);
+ //tcpm_log(port, "vconn:=%d", enable);
ret = port->tcpc->set_vconn(port->tcpc, enable);
if (!ret) {
@@ -2871,8 +2873,8 @@ static void tcpm_pd_rx_handler(struct kthread_work *work)
mutex_lock(&port->lock);
- tcpm_log(port, "PD RX, header: %#x [%d]", le16_to_cpu(msg->header),
- port->attached);
+ //tcpm_log(port, "PD RX, header: %#x [%d]", le16_to_cpu(msg->header),
+ //port->attached);
if (port->attached) {
enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
@@ -5041,7 +5043,7 @@ static void _tcpm_cc_change(struct tcpm_port *port, enum typec_cc_status cc1,
static void _tcpm_pd_vbus_on(struct tcpm_port *port)
{
- tcpm_log_force(port, "VBUS on");
+ tcpm_log_force(port, "VBUS event received: on");
port->vbus_present = true;
/*
* When vbus_present is true i.e. Voltage at VBUS is greater than VSAFE5V implicitly
@@ -5131,7 +5133,7 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
static void _tcpm_pd_vbus_off(struct tcpm_port *port)
{
- tcpm_log_force(port, "VBUS off");
+ tcpm_log_force(port, "VBUS event received: off");
port->vbus_present = false;
port->vbus_never_low = false;
switch (port->state) {

View File

@ -0,0 +1,34 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 14 Nov 2021 01:14:25 +0100
Subject: [PATCH 32/36] usb: typec: fusb302: Add OF extcon support
It's possible to create a dependency cycle between fusb302 and
other drivers via extcon device, so we retrieve the device on
demand after probe and not during probe.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index ae3b930..0c5dd00 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -518,6 +518,16 @@ static int tcpm_get_current_limit(struct tcpc_dev *dev)
int current_limit = 0;
unsigned long timeout;
+ /*
+ * To avoid cycles in OF dependencies, we get extcon when necessary
+ * outside of probe function.
+ */
+ if (of_property_read_bool(chip->dev->of_node, "extcon") && !chip->extcon) {
+ chip->extcon = extcon_get_edev_by_phandle(chip->dev, 0);
+ if (IS_ERR(chip->extcon))
+ chip->extcon = NULL;
+ }
+
if (!chip->extcon)
return 0;

View File

@ -0,0 +1,45 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 20 Nov 2021 14:33:58 +0100
Subject: [PATCH 33/36] usb: typec: fusb302: Fix register definitions
MEASURE_VBUS bit is at position 6. MDAC bits are also wrong.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302_reg.h | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/typec/tcpm/fusb302_reg.h b/drivers/usb/typec/tcpm/fusb302_reg.h
index edc0e4b..f37d226 100644
--- a/drivers/usb/typec/tcpm/fusb302_reg.h
+++ b/drivers/usb/typec/tcpm/fusb302_reg.h
@@ -27,14 +27,13 @@
#define FUSB_REG_SWITCHES1_TXCC2_EN BIT(1)
#define FUSB_REG_SWITCHES1_TXCC1_EN BIT(0)
#define FUSB_REG_MEASURE 0x04
-#define FUSB_REG_MEASURE_MDAC5 BIT(7)
-#define FUSB_REG_MEASURE_MDAC4 BIT(6)
-#define FUSB_REG_MEASURE_MDAC3 BIT(5)
-#define FUSB_REG_MEASURE_MDAC2 BIT(4)
-#define FUSB_REG_MEASURE_MDAC1 BIT(3)
-#define FUSB_REG_MEASURE_MDAC0 BIT(2)
-#define FUSB_REG_MEASURE_VBUS BIT(1)
-#define FUSB_REG_MEASURE_XXXX5 BIT(0)
+#define FUSB_REG_MEASURE_VBUS BIT(6)
+#define FUSB_REG_MEASURE_MDAC5 BIT(5)
+#define FUSB_REG_MEASURE_MDAC4 BIT(4)
+#define FUSB_REG_MEASURE_MDAC3 BIT(3)
+#define FUSB_REG_MEASURE_MDAC2 BIT(2)
+#define FUSB_REG_MEASURE_MDAC1 BIT(1)
+#define FUSB_REG_MEASURE_MDAC0 BIT(0)
#define FUSB_REG_CONTROL0 0x06
#define FUSB_REG_CONTROL0_TX_FLUSH BIT(6)
#define FUSB_REG_CONTROL0_INT_MASK BIT(5)
@@ -105,7 +104,6 @@
#define FUSB_REG_STATUS0A_RX_SOFT_RESET BIT(1)
#define FUSB_REG_STATUS0A_RX_HARD_RESET BIT(0)
#define FUSB_REG_STATUS1A 0x3D
-#define FUSB_REG_STATUS1A_TOGSS BIT(3)
#define FUSB_REG_STATUS1A_TOGSS_RUNNING 0x0
#define FUSB_REG_STATUS1A_TOGSS_SRC1 0x1
#define FUSB_REG_STATUS1A_TOGSS_SRC2 0x2

View File

@ -0,0 +1,37 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 20 Nov 2021 14:35:10 +0100
Subject: [PATCH 34/36] usb: typec: fusb302: Clear interrupts before we start
toggling
This is recommended by the datasheet.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/tcpm/fusb302.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c
index 0c5dd00..011dce5 100644
--- a/drivers/usb/typec/tcpm/fusb302.c
+++ b/drivers/usb/typec/tcpm/fusb302.c
@@ -586,6 +586,7 @@ static int fusb302_set_toggling(struct fusb302_chip *chip,
enum toggling_mode mode)
{
int ret = 0;
+ u8 reg;
/* first disable toggling */
ret = fusb302_i2c_clear_bits(chip, FUSB_REG_CONTROL2,
@@ -644,6 +645,12 @@ static int fusb302_set_toggling(struct fusb302_chip *chip,
} else {
/* Datasheet says vconn MUST be off when toggling */
WARN(chip->vconn_on, "Vconn is on during toggle start");
+
+ /* clear interrupts */
+ ret = fusb302_i2c_read(chip, FUSB_REG_INTERRUPT, &reg);
+ if (ret < 0)
+ return ret;
+
/* unmask TOGDONE interrupt */
ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA,
FUSB_REG_MASKA_TOGDONE);

View File

@ -0,0 +1,388 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 19:24:40 +0100
Subject: [PATCH 35/36] usb: typec: typec-extcon: Add typec -> extcon bridge
driver
This bridge connects standard Type C port interfaces for controling
muxes, switches and usb roles to muxes, switches and usb role
drivers controlled via extcon interface.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/usb/typec/Kconfig | 7 +
drivers/usb/typec/Makefile | 1 +
drivers/usb/typec/typec-extcon.c | 337 +++++++++++++++++++++++++++++++++++++++
3 files changed, 345 insertions(+)
create mode 100644 drivers/usb/typec/typec-extcon.c
diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index ab480f3..01ecc5e 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -88,6 +88,13 @@ config TYPEC_QCOM_PMIC
It will also enable the VBUS output to connected devices when a
DFP connection is made.
+config TYPEC_EXTCON
+ tristate "Type-C switch/mux -> extcon interface bridge driver"
+ depends on USB_ROLE_SWITCH
+ help
+ Say Y or M here if your system needs bridging between typec class
+ and extcon interfaces.
+
source "drivers/usb/typec/mux/Kconfig"
source "drivers/usb/typec/altmodes/Kconfig"
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index a0adb89..d9d8293 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_TYPEC_TPS6598X) += tipd/
obj-$(CONFIG_TYPEC_HD3SS3220) += hd3ss3220.o
obj-$(CONFIG_TYPEC_QCOM_PMIC) += qcom-pmic-typec.o
obj-$(CONFIG_TYPEC_STUSB160X) += stusb160x.o
+obj-$(CONFIG_TYPEC_EXTCON) += typec-extcon.o
obj-$(CONFIG_TYPEC) += mux/
diff --git a/drivers/usb/typec/typec-extcon.c b/drivers/usb/typec/typec-extcon.c
new file mode 100644
index 00000000..143ff24
--- /dev/null
+++ b/drivers/usb/typec/typec-extcon.c
@@ -0,0 +1,337 @@
+/*
+ * typec -> extcon bridge
+ * Copyright (c) 2021 Ondřej Jirman <megi@xff.cz>
+ *
+ * This driver bridges standard type-c interfaces to drivers that
+ * expect extcon interface.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/platform_device.h>
+#include <linux/usb/pd.h>
+#include <linux/usb/role.h>
+#include <linux/usb/typec.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/extcon-provider.h>
+
+struct typec_extcon {
+ struct device *dev;
+
+ /* consumers */
+ struct usb_role_switch *role_sw;
+ struct typec_switch *sw;
+ struct typec_mux *mux;
+
+ /* providers */
+ struct extcon_dev *extcon;
+ struct notifier_block extcon_nb;
+
+ /* cached state from typec controller */
+ enum usb_role role;
+ enum typec_orientation orientation;
+ struct typec_altmode alt;
+ unsigned long mode;
+ bool has_alt;
+ struct mutex lock;
+};
+
+static const unsigned int typec_extcon_cable[] = {
+ EXTCON_DISP_DP,
+
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+
+ EXTCON_CHG_USB_SDP,
+ EXTCON_CHG_USB_CDP,
+ EXTCON_CHG_USB_DCP,
+ EXTCON_CHG_USB_ACA,
+
+ EXTCON_NONE,
+};
+
+static void typec_extcon_set_cable(struct typec_extcon *tce, int id, bool on,
+ union extcon_property_value prop_ss,
+ union extcon_property_value prop_or)
+{
+ union extcon_property_value cur_ss, cur_or;
+ bool prop_diff = false;
+ int ret;
+
+ ret = extcon_get_property(tce->extcon, id,
+ EXTCON_PROP_USB_SS, &cur_ss);
+ if (ret || cur_ss.intval != prop_ss.intval)
+ prop_diff = true;
+
+ ret = extcon_get_property(tce->extcon, id,
+ EXTCON_PROP_USB_TYPEC_POLARITY, &cur_or);
+ if (ret || cur_or.intval != prop_or.intval)
+ prop_diff = true;
+
+ if (!on && extcon_get_state(tce->extcon, id)) {
+ extcon_set_state_sync(tce->extcon, id, false);
+ } else if (on && (!extcon_get_state(tce->extcon, id) || prop_diff)) {
+ extcon_set_state(tce->extcon, id, true);
+ extcon_set_property(tce->extcon, id,
+ EXTCON_PROP_USB_SS, prop_ss);
+ extcon_set_property(tce->extcon, id,
+ EXTCON_PROP_USB_TYPEC_POLARITY, prop_or);
+ extcon_sync(tce->extcon, id);
+ }
+}
+
+static int typec_extcon_sync_extcon(struct typec_extcon *tce)
+{
+ union extcon_property_value prop_ss, prop_or;
+ bool has_dp = false;
+
+ mutex_lock(&tce->lock);
+
+ /* connector is disconnected */
+ if (tce->orientation == TYPEC_ORIENTATION_NONE) {
+ typec_extcon_set_cable(tce, EXTCON_USB, false, prop_ss, prop_or);
+ typec_extcon_set_cable(tce, EXTCON_USB_HOST, false, prop_ss, prop_or);
+ typec_extcon_set_cable(tce, EXTCON_DISP_DP, false, prop_ss, prop_or);
+
+ extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_SDP, false);
+ extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_DCP, false);
+ extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_CDP, false);
+ extcon_set_state_sync(tce->extcon, EXTCON_CHG_USB_ACA, false);
+
+ goto out_unlock;
+ }
+
+ prop_or.intval = tce->orientation == TYPEC_ORIENTATION_NORMAL ? 0 : 1;
+ prop_ss.intval = 0;
+
+ if (tce->has_alt && tce->alt.svid == USB_TYPEC_DP_SID) {
+ switch (tce->mode) {
+ case TYPEC_STATE_SAFE:
+ break;
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ has_dp = true;
+ break;
+ case TYPEC_DP_STATE_D:
+ has_dp = true;
+ fallthrough;
+ case TYPEC_STATE_USB:
+ prop_ss.intval = 1;
+ break;
+ default:
+ dev_err(tce->dev, "unhandled mux mode=%lu\n", tce->mode);
+ break;
+ }
+ }
+
+ typec_extcon_set_cable(tce, EXTCON_USB,
+ tce->role == USB_ROLE_DEVICE, prop_ss, prop_or);
+ typec_extcon_set_cable(tce, EXTCON_USB_HOST,
+ tce->role == USB_ROLE_HOST, prop_ss, prop_or);
+
+ typec_extcon_set_cable(tce, EXTCON_DISP_DP, has_dp, prop_ss, prop_or);
+
+out_unlock:
+ mutex_unlock(&tce->lock);
+ return 0;
+}
+
+static int typec_extcon_sw_set(struct typec_switch *sw,
+ enum typec_orientation orientation)
+{
+ struct typec_extcon *tce = typec_switch_get_drvdata(sw);
+
+ dev_dbg(tce->dev, "SW SET: orientation=%d\n", orientation);
+
+ mutex_lock(&tce->lock);
+ tce->orientation = orientation;
+ mutex_unlock(&tce->lock);
+
+ typec_extcon_sync_extcon(tce);
+
+ return 0;
+}
+
+static int typec_extcon_mux_set(struct typec_mux *mux,
+ struct typec_mux_state *state)
+{
+ struct typec_extcon *tce = typec_mux_get_drvdata(mux);
+ struct typec_altmode *alt = state->alt;
+
+ dev_dbg(tce->dev, "MUX SET: state->mode=%lu\n", state->mode);
+ if (alt)
+ dev_dbg(tce->dev, " ...alt: svid=%04hx mode=%d vdo=%08x active=%u\n",
+ alt->svid, alt->mode, alt->vdo, alt->active);
+
+ mutex_lock(&tce->lock);
+ tce->mode = state->mode;
+ tce->has_alt = alt != NULL;
+ if (alt)
+ tce->alt = *alt;
+ mutex_unlock(&tce->lock);
+
+ typec_extcon_sync_extcon(tce);
+
+ return 0;
+}
+
+static int typec_extcon_usb_set_role(struct usb_role_switch *sw,
+ enum usb_role role)
+{
+ struct typec_extcon *tce = usb_role_switch_get_drvdata(sw);
+
+ dev_dbg(tce->dev, "ROLE SET: role=%d\n", role);
+
+ mutex_lock(&tce->lock);
+ tce->role = role;
+ mutex_unlock(&tce->lock);
+
+ typec_extcon_sync_extcon(tce);
+
+ return 0;
+}
+
+static int typec_extcon_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct typec_extcon *tce = container_of(nb, struct typec_extcon, extcon_nb);
+
+ bool sdp = extcon_get_state(tce->extcon, EXTCON_CHG_USB_SDP);
+ bool cdp = extcon_get_state(tce->extcon, EXTCON_CHG_USB_CDP);
+ bool dcp = extcon_get_state(tce->extcon, EXTCON_CHG_USB_DCP);
+ bool usb = extcon_get_state(tce->extcon, EXTCON_USB);
+ bool usb_host = extcon_get_state(tce->extcon, EXTCON_USB_HOST);
+ bool dp = extcon_get_state(tce->extcon, EXTCON_DISP_DP);
+
+ dev_info(tce->dev, "extcon changed sdp=%d cdp=%d dcp=%d usb=%d usb_host=%d dp=%d\n",
+ sdp, cdp, dcp, usb, usb_host, dp);
+
+ return NOTIFY_OK;
+}
+
+static int typec_extcon_probe(struct platform_device *pdev)
+{
+ struct typec_switch_desc sw_desc = { };
+ struct typec_mux_desc mux_desc = { };
+ struct usb_role_switch_desc role_desc = { };
+ struct device *dev = &pdev->dev;
+ struct typec_extcon *tce;
+ int ret = 0;
+
+ tce = devm_kzalloc(dev, sizeof(*tce), GFP_KERNEL);
+ if (!tce)
+ return -ENOMEM;
+
+ tce->dev = &pdev->dev;
+ mutex_init(&tce->lock);
+ tce->mode = TYPEC_STATE_SAFE;
+
+ sw_desc.drvdata = tce;
+ sw_desc.fwnode = dev->fwnode;
+ sw_desc.set = typec_extcon_sw_set;
+
+ tce->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(tce->sw))
+ return dev_err_probe(dev, PTR_ERR(tce->sw),
+ "Error registering typec switch\n");
+
+ mux_desc.drvdata = tce;
+ mux_desc.fwnode = dev->fwnode;
+ mux_desc.set = typec_extcon_mux_set;
+
+ tce->mux = typec_mux_register(dev, &mux_desc);
+ if (IS_ERR(tce->mux)) {
+ ret = dev_err_probe(dev, PTR_ERR(tce->mux),
+ "Error registering typec mux\n");
+ goto err_sw;
+ }
+
+ role_desc.driver_data = tce;
+ role_desc.fwnode = dev->fwnode;
+ role_desc.name = fwnode_get_name(dev->fwnode);
+ role_desc.set = typec_extcon_usb_set_role;
+
+ tce->role_sw = usb_role_switch_register(dev, &role_desc);
+ if (IS_ERR(tce->role_sw)) {
+ ret = dev_err_probe(dev, PTR_ERR(tce->role_sw),
+ "Error registering USB role switch\n");
+ goto err_mux;
+ }
+
+ tce->extcon = devm_extcon_dev_allocate(dev, typec_extcon_cable);
+ if (IS_ERR(tce->extcon)) {
+ ret = PTR_ERR(tce->extcon);
+ goto err_role;
+ }
+
+ ret = devm_extcon_dev_register(dev, tce->extcon);
+ if (ret) {
+ ret = dev_err_probe(dev, ret, "failed to register extcon device\n");
+ goto err_role;
+ }
+
+ extcon_set_property_capability(tce->extcon, EXTCON_USB,
+ EXTCON_PROP_USB_SS);
+ extcon_set_property_capability(tce->extcon, EXTCON_USB,
+ EXTCON_PROP_USB_TYPEC_POLARITY);
+ extcon_set_property_capability(tce->extcon, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_SS);
+ extcon_set_property_capability(tce->extcon, EXTCON_USB_HOST,
+ EXTCON_PROP_USB_TYPEC_POLARITY);
+ extcon_set_property_capability(tce->extcon, EXTCON_DISP_DP,
+ EXTCON_PROP_USB_SS);
+ extcon_set_property_capability(tce->extcon, EXTCON_DISP_DP,
+ EXTCON_PROP_USB_TYPEC_POLARITY);
+
+ tce->extcon_nb.notifier_call = typec_extcon_notifier;
+ ret = devm_extcon_register_notifier_all(dev, tce->extcon, &tce->extcon_nb);
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register extcon notifier\n");
+ goto err_role;
+ }
+
+ return 0;
+
+err_role:
+ usb_role_switch_unregister(tce->role_sw);
+err_mux:
+ typec_mux_unregister(tce->mux);
+err_sw:
+ typec_switch_unregister(tce->sw);
+ return ret;
+}
+
+static int typec_extcon_remove(struct platform_device *pdev)
+{
+ struct typec_extcon *tce = platform_get_drvdata(pdev);
+
+ usb_role_switch_unregister(tce->role_sw);
+ typec_mux_unregister(tce->mux);
+ typec_switch_unregister(tce->sw);
+
+ return 0;
+}
+
+static struct of_device_id typec_extcon_of_match_table[] = {
+ { .compatible = "linux,typec-extcon-bridge" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, typec_extcon_of_match_table);
+
+static struct platform_driver typec_extcon_driver = {
+ .driver = {
+ .name = "typec-extcon",
+ .of_match_table = typec_extcon_of_match_table,
+ },
+ .probe = typec_extcon_probe,
+ .remove = typec_extcon_remove,
+};
+
+module_platform_driver(typec_extcon_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ondrej Jirman <megous@megous.com>");
+MODULE_DESCRIPTION("typec -> extcon bridge driver");

View File

@ -0,0 +1,64 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 23 Nov 2021 17:32:18 +0100
Subject: [PATCH 36/36] phy: rockchip-typec: Make sure the plug orientation is
respected
RK3399 TRM says about bit 8:
typec_conn_dir_sel: TypeC connect direction select
- 0: select typec_conn_dir (bit0 of this register) to TypeC PHY
- 1: select TCPC ouput typec_con_dir to TypeC PHY (default value)
This means that by default, typec_conn_dir bit is not respected.
Fix setting of typec_conn_dir by setting typec_conn_dir to 0 first.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/phy/rockchip/phy-rockchip-typec.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c
index d2bbdc9..fa10ee9 100644
--- a/drivers/phy/rockchip/phy-rockchip-typec.c
+++ b/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -350,6 +350,7 @@ struct usb3phy_reg {
* struct rockchip_usb3phy_port_cfg - usb3-phy port configuration.
* @reg: the base address for usb3-phy config.
* @typec_conn_dir: the register of type-c connector direction.
+ * @typec_conn_dir_sel: the register of type-c connector direction source.
* @usb3tousb2_en: the register of type-c force usb2 to usb2 enable.
* @external_psm: the register of type-c phy external psm clock.
* @pipe_status: the register of type-c phy pipe status.
@@ -360,6 +361,7 @@ struct usb3phy_reg {
struct rockchip_usb3phy_port_cfg {
unsigned int reg;
struct usb3phy_reg typec_conn_dir;
+ struct usb3phy_reg typec_conn_dir_sel;
struct usb3phy_reg usb3tousb2_en;
struct usb3phy_reg external_psm;
struct usb3phy_reg pipe_status;
@@ -434,6 +436,7 @@ static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
{
.reg = 0xff7c0000,
.typec_conn_dir = { 0xe580, 0, 16 },
+ .typec_conn_dir_sel = { 0xe580, 8, 16+8 },
.usb3tousb2_en = { 0xe580, 3, 19 },
.external_psm = { 0xe588, 14, 30 },
.pipe_status = { 0xe5c0, 0, 0 },
@@ -444,6 +447,7 @@ static const struct rockchip_usb3phy_port_cfg rk3399_usb3phy_port_cfgs[] = {
{
.reg = 0xff800000,
.typec_conn_dir = { 0xe58c, 0, 16 },
+ .typec_conn_dir_sel = { 0xe58c, 8, 16+8 },
.usb3tousb2_en = { 0xe58c, 3, 19 },
.external_psm = { 0xe594, 14, 30 },
.pipe_status = { 0xe5c0, 16, 16 },
@@ -739,6 +743,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode)
reset_control_deassert(tcphy->tcphy_rst);
+ property_enable(tcphy, &cfg->typec_conn_dir_sel, 0);
property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip);
tcphy_dp_aux_set_flip(tcphy);

View File

@ -0,0 +1,56 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 22 Oct 2021 18:10:18 +0200
Subject: [PATCH 20/36] media: i2c: imx258: Add support for powerdown gpio
On some boards powerdown signal needs to be deasserted for this
sensor to be enabled.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/imx258.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index c249507..be5adcc 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -612,6 +612,8 @@ struct imx258 {
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure;
+ struct gpio_desc *pwdn_gpio;
+
/* Current mode */
const struct imx258_mode *cur_mode;
@@ -1010,6 +1012,8 @@ static int imx258_power_on(struct device *dev)
struct imx258 *imx258 = to_imx258(sd);
int ret;
+ gpiod_set_value_cansleep(imx258->pwdn_gpio, 0);
+
ret = clk_prepare_enable(imx258->clk);
if (ret)
dev_err(dev, "failed to enable clock\n");
@@ -1024,6 +1028,8 @@ static int imx258_power_off(struct device *dev)
clk_disable_unprepare(imx258->clk);
+ gpiod_set_value_cansleep(imx258->pwdn_gpio, 1);
+
return 0;
}
@@ -1284,6 +1290,12 @@ static int imx258_probe(struct i2c_client *client)
if (ret || val != 180)
return -EINVAL;
+ /* request optional power down pin */
+ imx258->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(imx258->pwdn_gpio))
+ return PTR_ERR(imx258->pwdn_gpio);
+
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);

View File

@ -0,0 +1,41 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 22 Oct 2021 18:11:26 +0200
Subject: [PATCH 21/36] media: i2c: imx258: Don't be too strict about clock
rate
On Pinephone Pro, we are not able to set 19.2MHz precisely.
Allow some slack in clock rate.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/imx258.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index be5adcc..e64fadc 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -79,7 +79,9 @@
#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
/* Input clock frequency in Hz */
+#define IMX258_INPUT_CLOCK_FREQ_MIN 19000000
#define IMX258_INPUT_CLOCK_FREQ 19200000
+#define IMX258_INPUT_CLOCK_FREQ_MAX 19400000
struct imx258_reg {
u16 address;
@@ -1277,8 +1279,11 @@ static int imx258_probe(struct i2c_client *client)
} else {
val = clk_get_rate(imx258->clk);
}
- if (val != IMX258_INPUT_CLOCK_FREQ) {
- dev_err(&client->dev, "input clock frequency not supported\n");
+
+ if (val < IMX258_INPUT_CLOCK_FREQ_MIN
+ || val > IMX258_INPUT_CLOCK_FREQ_MAX) {
+ dev_err(&client->dev, "input clock frequency %u not supported\n",
+ val);
return -EINVAL;
}

View File

@ -0,0 +1,57 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 22 Oct 2021 21:44:13 +0200
Subject: [PATCH 22/36] media: i2c: imx258: Add support for reset gpio
It was documented in DT, but not implemented.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/imx258.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index e64fadc..ec6e919 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -615,6 +615,7 @@ struct imx258 {
struct v4l2_ctrl *exposure;
struct gpio_desc *pwdn_gpio;
+ struct gpio_desc *reset_gpio;
/* Current mode */
const struct imx258_mode *cur_mode;
@@ -1020,7 +1021,11 @@ static int imx258_power_on(struct device *dev)
if (ret)
dev_err(dev, "failed to enable clock\n");
- return ret;
+ gpiod_set_value_cansleep(imx258->reset_gpio, 0);
+
+ usleep_range(400, 500);
+
+ return 0;
}
static int imx258_power_off(struct device *dev)
@@ -1030,6 +1035,7 @@ static int imx258_power_off(struct device *dev)
clk_disable_unprepare(imx258->clk);
+ gpiod_set_value_cansleep(imx258->reset_gpio, 1);
gpiod_set_value_cansleep(imx258->pwdn_gpio, 1);
return 0;
@@ -1301,6 +1307,12 @@ static int imx258_probe(struct i2c_client *client)
if (IS_ERR(imx258->pwdn_gpio))
return PTR_ERR(imx258->pwdn_gpio);
+ /* request optional reset pin */
+ imx258->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(imx258->reset_gpio))
+ return PTR_ERR(imx258->reset_gpio);
+
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);

View File

@ -0,0 +1,100 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 22 Oct 2021 21:44:30 +0200
Subject: [PATCH 23/36] media: i2c: imx258: Add support for power supplies
They were documented in DT, but not implemented.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/imx258.c | 39 +++++++++++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c
index ec6e919..2570b51 100644
--- a/drivers/media/i2c/imx258.c
+++ b/drivers/media/i2c/imx258.c
@@ -602,6 +602,15 @@ static const struct imx258_mode supported_modes[] = {
},
};
+/* regulator supplies */
+static const char * const imx258_supply_names[] = {
+ "vana", /* Analog (2.8V) supply */
+ "vdig", /* Digital Core (1.5V) supply */
+ "vif", /* Digital I/O (1.8V) supply */
+};
+
+#define IMX258_SUPPLY_COUNT ARRAY_SIZE(imx258_supply_names)
+
struct imx258 {
struct v4l2_subdev sd;
struct media_pad pad;
@@ -616,6 +625,7 @@ struct imx258 {
struct gpio_desc *pwdn_gpio;
struct gpio_desc *reset_gpio;
+ struct regulator_bulk_data supplies[IMX258_SUPPLY_COUNT];
/* Current mode */
const struct imx258_mode *cur_mode;
@@ -1015,11 +1025,26 @@ static int imx258_power_on(struct device *dev)
struct imx258 *imx258 = to_imx258(sd);
int ret;
+ ret = regulator_bulk_enable(IMX258_SUPPLY_COUNT, imx258->supplies);
+ if (ret) {
+ dev_err(dev, "failed to enable regulators\n");
+ return ret;
+ }
+
+ mdelay(20);
+
gpiod_set_value_cansleep(imx258->pwdn_gpio, 0);
+ mdelay(5);
+
ret = clk_prepare_enable(imx258->clk);
- if (ret)
+ if (ret) {
dev_err(dev, "failed to enable clock\n");
+ regulator_bulk_disable(IMX258_SUPPLY_COUNT, imx258->supplies);
+ return ret;
+ }
+
+ usleep_range(1000, 2000);
gpiod_set_value_cansleep(imx258->reset_gpio, 0);
@@ -1038,6 +1063,8 @@ static int imx258_power_off(struct device *dev)
gpiod_set_value_cansleep(imx258->reset_gpio, 1);
gpiod_set_value_cansleep(imx258->pwdn_gpio, 1);
+ regulator_bulk_disable(IMX258_SUPPLY_COUNT, imx258->supplies);
+
return 0;
}
@@ -1266,7 +1293,7 @@ static void imx258_free_controls(struct imx258 *imx258)
static int imx258_probe(struct i2c_client *client)
{
struct imx258 *imx258;
- int ret;
+ int ret, i;
u32 val = 0;
imx258 = devm_kzalloc(&client->dev, sizeof(*imx258), GFP_KERNEL);
@@ -1301,6 +1328,14 @@ static int imx258_probe(struct i2c_client *client)
if (ret || val != 180)
return -EINVAL;
+ for (i = 0; i < IMX258_SUPPLY_COUNT; i++)
+ imx258->supplies[i].supply = imx258_supply_names[i];
+ ret = devm_regulator_bulk_get(&client->dev,
+ IMX258_SUPPLY_COUNT,
+ imx258->supplies);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to get supplies\n");
+
/* request optional power down pin */
imx258->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
GPIOD_OUT_HIGH);

View File

@ -0,0 +1,52 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 24 Jan 2020 18:25:12 +0100
Subject: [PATCH 091/194] media: ov5640: Add more framerates to the driver
(some of them even work!)
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/ov5640.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index ddbd713..624a3c0 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -112,7 +112,11 @@ enum ov5640_mode_id {
};
enum ov5640_frame_rate {
- OV5640_15_FPS = 0,
+ OV5640_2_FPS = 0,
+ OV5640_3_FPS,
+ OV5640_5_FPS,
+ OV5640_7_FPS,
+ OV5640_15_FPS,
OV5640_30_FPS,
OV5640_60_FPS,
OV5640_NUM_FRAMERATES,
@@ -156,6 +160,10 @@ MODULE_PARM_DESC(virtual_channel,
"MIPI CSI-2 virtual channel (0..3), default 0");
static const int ov5640_framerates[] = {
+ [OV5640_2_FPS] = 2,
+ [OV5640_3_FPS] = 3,
+ [OV5640_5_FPS] = 5,
+ [OV5640_7_FPS] = 7,
[OV5640_15_FPS] = 15,
[OV5640_30_FPS] = 30,
[OV5640_60_FPS] = 60,
@@ -2193,11 +2201,11 @@ static int ov5640_try_frame_interval(struct ov5640_dev *sensor,
u32 width, u32 height)
{
const struct ov5640_mode_info *mode;
- enum ov5640_frame_rate rate = OV5640_15_FPS;
+ enum ov5640_frame_rate rate = OV5640_2_FPS;
int minfps, maxfps, best_fps, fps;
int i;
- minfps = ov5640_framerates[OV5640_15_FPS];
+ minfps = ov5640_framerates[OV5640_2_FPS];
maxfps = ov5640_framerates[OV5640_60_FPS];
if (fi->numerator == 0) {

View File

@ -0,0 +1,47 @@
From: Ondrej Jirman <megous@megous.com>
Date: Fri, 24 Jan 2020 18:25:59 +0100
Subject: [PATCH 158/465] media: ov5640: [Experiment] Try to disable
denoising/sharpening
Not sure how this works exactly. More tests are needed.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/ov5640.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 624a3c0..2f6f97e 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -1772,6 +1772,7 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
unsigned long rate;
int ret;
+ u8 tmp;
dn_mode = mode->dn_mode;
orig_dn_mode = orig_mode->dn_mode;
@@ -1844,6 +1845,22 @@ static int ov5640_set_mode(struct ov5640_dev *sensor)
if (ret < 0)
return ret;
+ ret = ov5640_read_reg(sensor, 0x5308, &tmp);
+ if (ret)
+ return ret;
+
+ ret = ov5640_write_reg(sensor, 0x5308, tmp | 0x10 | 0x40);
+ if (ret)
+ return ret;
+
+ ret = ov5640_write_reg(sensor, 0x5306, 0);
+ if (ret)
+ return ret;
+
+ ret = ov5640_write_reg(sensor, 0x5302, 0);
+ if (ret)
+ return ret;
+
sensor->pending_mode_change = false;
sensor->last_mode = mode;

View File

@ -0,0 +1,25 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 26 Jan 2020 00:19:40 +0100
Subject: [PATCH 093/194] media: ov5640: Sleep after poweroff to ensure next
poweron is not too early
It's easy to use v4l2 userspace api in such a way that user can trigger
a brownout on the sensor instead of a proper powerdown and powerup.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/ov5640.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 2f6f97e..8a53c0c 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -1971,6 +1971,7 @@ static void ov5640_set_power_off(struct ov5640_dev *sensor)
ov5640_power(sensor, false);
regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies);
clk_disable_unprepare(sensor->xclk);
+ msleep(100);
}
static int ov5640_set_power_mipi(struct ov5640_dev *sensor, bool on)

View File

@ -0,0 +1,86 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 26 Jan 2020 00:28:10 +0100
Subject: [PATCH 094/194] media: ov5640: Don't powerup the sensor during
driver probe
It causes autofocus clicking during boot on some devices, and
it's enough to do it when turning on the sensor power by media
pipeline via s_power callback, later on.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/media/i2c/ov5640.c | 40 ++++++++--------------------------------
1 file changed, 8 insertions(+), 32 deletions(-)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 8a53c0c..75f71e6 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -1932,6 +1932,7 @@ static void ov5640_reset(struct ov5640_dev *sensor)
static int ov5640_set_power_on(struct ov5640_dev *sensor)
{
struct i2c_client *client = sensor->i2c_client;
+ u16 chip_id;
int ret;
ret = clk_prepare_enable(sensor->xclk);
@@ -1956,6 +1957,13 @@ static int ov5640_set_power_on(struct ov5640_dev *sensor)
if (ret)
goto power_off;
+ ret = ov5640_read_reg16(sensor, OV5640_REG_CHIP_ID, &chip_id);
+ if (ret) {
+ dev_err(&client->dev, "%s: failed to read chip identifier\n",
+ __func__);
+ goto power_off;
+ }
+
return 0;
power_off:
@@ -3039,34 +3047,6 @@ static int ov5640_get_regulators(struct ov5640_dev *sensor)
sensor->supplies);
}
-static int ov5640_check_chip_id(struct ov5640_dev *sensor)
-{
- struct i2c_client *client = sensor->i2c_client;
- int ret = 0;
- u16 chip_id;
-
- ret = ov5640_set_power_on(sensor);
- if (ret)
- return ret;
-
- ret = ov5640_read_reg16(sensor, OV5640_REG_CHIP_ID, &chip_id);
- if (ret) {
- dev_err(&client->dev, "%s: failed to read chip identifier\n",
- __func__);
- goto power_off;
- }
-
- if (chip_id != 0x5640) {
- dev_err(&client->dev, "%s: wrong chip identifier, expected 0x5640, got 0x%x\n",
- __func__, chip_id);
- ret = -ENXIO;
- }
-
-power_off:
- ov5640_set_power_off(sensor);
- return ret;
-}
-
static int ov5640_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -3184,10 +3164,6 @@ static int ov5640_probe(struct i2c_client *client)
mutex_init(&sensor->lock);
- ret = ov5640_check_chip_id(sensor);
- if (ret)
- goto entity_cleanup;
-
ret = ov5640_init_controls(sensor);
if (ret)
goto entity_cleanup;

View File

@ -1,7 +1,6 @@
From f062022f2a2781d6b8ca63c460b0e72ebac30870 Mon Sep 17 00:00:00 2001
From: Martijn Braam <martijn@brixit.nl>
Date: Mon, 28 Sep 2020 14:26:11 +0200
Subject: [PATCH] media: ov5640: Implement autofocus
Subject: [PATCH 120/194] media: ov5640: Implement autofocus
The autofocus functionality needs a firmware blob loaded into the
internal microcontroller.
@ -11,11 +10,11 @@ this at least makes it possible to focus on the center of the sensor.
Signed-off-by: Martijn Braam <martijn@brixit.nl>
---
drivers/media/i2c/ov5640.c | 254 +++++++++++++++++++++++++++++++++++++
1 file changed, 254 insertions(+)
drivers/media/i2c/ov5640.c | 273 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 273 insertions(+)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index df0a507c211f..08a5304c0e95 100644
index 75f71e6..246563e 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -9,6 +9,7 @@
@ -61,7 +60,7 @@ index df0a507c211f..08a5304c0e95 100644
#define OV5640_REG_TIMING_DVPHO 0x3808
#define OV5640_REG_TIMING_DVPVO 0x380a
#define OV5640_REG_TIMING_HTS 0x380c
@@ -95,6 +109,20 @@
@@ -96,6 +110,20 @@
#define OV5640_REG_SDE_CTRL4 0x5584
#define OV5640_REG_SDE_CTRL5 0x5585
#define OV5640_REG_AVG_READOUT 0x56a1
@ -81,8 +80,8 @@ index df0a507c211f..08a5304c0e95 100644
+#define OV5640_FW_CMD_DEFAULT_ZONES 0x80
enum ov5640_mode_id {
OV5640_MODE_QCIF_176_144 = 0,
@@ -218,6 +246,12 @@ struct ov5640_ctrls {
OV5640_MODE_QQVGA_160_120 = 0,
@@ -222,6 +250,12 @@ struct ov5640_ctrls {
struct v4l2_ctrl *auto_gain;
struct v4l2_ctrl *gain;
};
@ -95,7 +94,7 @@ index df0a507c211f..08a5304c0e95 100644
struct v4l2_ctrl *brightness;
struct v4l2_ctrl *light_freq;
struct v4l2_ctrl *saturation;
@@ -261,6 +295,8 @@ struct ov5640_dev {
@@ -265,6 +299,8 @@ struct ov5640_dev {
bool pending_mode_change;
bool streaming;
@ -104,7 +103,7 @@ index df0a507c211f..08a5304c0e95 100644
};
static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd)
@@ -1967,6 +2003,118 @@ static void ov5640_reset(struct ov5640_dev *sensor)
@@ -1929,6 +1965,118 @@ static void ov5640_reset(struct ov5640_dev *sensor)
usleep_range(20000, 25000);
}
@ -223,7 +222,7 @@ index df0a507c211f..08a5304c0e95 100644
static int ov5640_set_power_on(struct ov5640_dev *sensor)
{
struct i2c_client *client = sensor->i2c_client;
@@ -1988,6 +2117,8 @@ static int ov5640_set_power_on(struct ov5640_dev *sensor)
@@ -1950,6 +2098,8 @@ static int ov5640_set_power_on(struct ov5640_dev *sensor)
goto xclk_off;
}
@ -232,7 +231,7 @@ index df0a507c211f..08a5304c0e95 100644
ov5640_reset(sensor);
ov5640_power(sensor, true);
@@ -2416,6 +2547,35 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
@@ -2467,6 +2617,35 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
is_jpeg ? (BIT(5) | BIT(3)) : 0);
}
@ -268,7 +267,7 @@ index df0a507c211f..08a5304c0e95 100644
/*
* Sensor Controls.
*/
@@ -2532,6 +2692,41 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
@@ -2583,6 +2762,41 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
return ret;
}
@ -310,7 +309,7 @@ index df0a507c211f..08a5304c0e95 100644
static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
{
struct ov5640_ctrls *ctrls = &sensor->ctrls;
@@ -2638,6 +2833,32 @@ static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
@@ -2689,6 +2903,32 @@ static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
(BIT(2) | BIT(1)) : 0);
}
@ -343,7 +342,7 @@ index df0a507c211f..08a5304c0e95 100644
static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
@@ -2659,6 +2880,12 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
@@ -2710,6 +2950,12 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
return val;
sensor->ctrls.exposure->val = val;
break;
@ -356,7 +355,7 @@ index df0a507c211f..08a5304c0e95 100644
}
return 0;
@@ -2690,6 +2917,18 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
@@ -2741,6 +2987,18 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_AUTO_WHITE_BALANCE:
ret = ov5640_set_ctrl_white_balance(sensor, ctrl->val);
break;
@ -375,7 +374,7 @@ index df0a507c211f..08a5304c0e95 100644
case V4L2_CID_HUE:
ret = ov5640_set_ctrl_hue(sensor, ctrl->val);
break;
@@ -2762,6 +3001,20 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
@@ -2813,6 +3071,20 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
0, 1023, 1, 0);
@ -396,7 +395,7 @@ index df0a507c211f..08a5304c0e95 100644
ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
0, 255, 1, 64);
ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
@@ -2795,6 +3048,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
@@ -2846,6 +3118,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
@ -404,6 +403,3 @@ index df0a507c211f..08a5304c0e95 100644
sensor->sd.ctrl_handler = hdl;
return 0;
--
2.25.4

View File

@ -0,0 +1,23 @@
From: Martijn Braam <martijn@brixit.nl>
Date: Wed, 7 Oct 2020 17:33:43 +0200
Subject: [PATCH 121/194] media: ov5640: set default ae target lower
The OV5640 tries to overexpose all photos by about 1 stop. This makes
the exposure target one stop lower.
---
drivers/media/i2c/ov5640.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index 246563e..f01bf29 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -3355,7 +3355,7 @@ static int ov5640_probe(struct i2c_client *client)
&ov5640_mode_data[OV5640_MODE_VGA_640_480];
sensor->last_mode = sensor->current_mode;
- sensor->ae_target = 52;
+ sensor->ae_target = 28;
/* optional indication of physical rotation of sensor */
ret = fwnode_property_read_u32(dev_fwnode(&client->dev), "rotation",

View File

@ -0,0 +1,464 @@
From: =?utf-8?q?Kamil_Trzci=C5=84ski?= <ayufan@ayufan.eu>
Date: Wed, 8 Sep 2021 13:50:04 +0200
Subject: [PATCH 05/36] drm: panel: hx8394: Add driver for HX8394 based
HannStar HSD060BHW4 panel
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
...
Signed-off-by: Kamil Trzciński <ayufan@ayufan.eu>
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/panel/Kconfig | 9 +
drivers/gpu/drm/panel/Makefile | 1 +
drivers/gpu/drm/panel/panel-himax-hx8394.c | 410 +++++++++++++++++++++++++++++
3 files changed, 420 insertions(+)
create mode 100644 drivers/gpu/drm/panel/panel-himax-hx8394.c
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index cfc8d64..166bd4a 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -129,6 +129,15 @@ config DRM_PANEL_FEIYANG_FY07024DI26A30D
Say Y if you want to enable support for panels based on the
Feiyang FY07024DI26A30-D MIPI-DSI interface.
+config DRM_PANEL_HIMAX_HX8394
+ tristate "HIMAX HX8394 MIPI-DSI LCD panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y if you want to enable support for panels based on the
+ HIMAX HX8394 MIPI-DSI interface.
+
config DRM_PANEL_ILITEK_IL9322
tristate "Ilitek ILI9322 320x240 QVGA panels"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index bca4cc1..486926c 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -67,3 +67,4 @@ obj-$(CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA) += panel-truly-nt35597.o
obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
+obj-$(CONFIG_DRM_PANEL_HIMAX_HX8394) += panel-himax-hx8394.o
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
new file mode 100644
index 00000000..14659cb
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for panels based on Himax HX8394 controller, souch as:
+ *
+ * - HannStar HSD060BHW4 5.99" MIPI-DSI panel
+ *
+ * Copyright (C) Kamil Trzciński
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/media-bus-format.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/display_timing.h>
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#define DRV_NAME "panel-himax-hx8394"
+
+struct hx8394 {
+ struct device *dev;
+ struct drm_panel panel;
+ struct gpio_desc *reset_gpio;
+ struct regulator *vcc;
+ struct regulator *iovcc;
+ bool prepared;
+
+ struct dentry *debugfs;
+ const struct hx8394_panel_desc *desc;
+};
+
+struct hx8394_panel_desc {
+ const struct drm_display_mode *mode;
+ unsigned int lanes;
+ unsigned long mode_flags;
+ enum mipi_dsi_pixel_format format;
+ int (*init_sequence)(struct hx8394 *ctx);
+};
+
+static inline struct hx8394 *panel_to_hx8394(struct drm_panel *panel)
+{
+ return container_of(panel, struct hx8394, panel);
+}
+
+#define dsi_generic_write_seq(dsi, seq...) do { \
+ static const u8 d[] = { seq }; \
+ int ret; \
+ ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+#define dsi_dcs_write_seq(dsi, cmd, seq...) do { \
+ static const u8 d[] = { seq }; \
+ int ret; \
+ ret = mipi_dsi_dcs_write(dsi, cmd, d, ARRAY_SIZE(d)); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+
+static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
+{
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+
+ dsi_dcs_write_seq(dsi, 0xb9, 0xff, 0x83, 0x94);
+ dsi_dcs_write_seq(dsi, 0xb1, 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
+ dsi_dcs_write_seq(dsi, 0xba, 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
+ dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x80, 0x78, 0x0c, 0x07);
+ dsi_dcs_write_seq(dsi, 0xb4, 0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55, 0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c, 0x7c);
+ dsi_dcs_write_seq(dsi, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10, 0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00, 0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00, 0x00, 0x0c, 0x40);
+ dsi_dcs_write_seq(dsi, 0xd5, 0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
+ dsi_dcs_write_seq(dsi, 0xd6, 0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
+ dsi_dcs_write_seq(dsi, 0xe0, 0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00, 0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31, 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f);
+ dsi_dcs_write_seq(dsi, 0xcc, 0x0b);
+ dsi_dcs_write_seq(dsi, 0xc0, 0x1f, 0x31);
+ dsi_dcs_write_seq(dsi, 0xb6, 0x7d, 0x7d);
+ dsi_dcs_write_seq(dsi, 0xd4, 0x02);
+ dsi_dcs_write_seq(dsi, 0xbd, 0x01);
+ dsi_dcs_write_seq(dsi, 0xb1, 0x00);
+ dsi_dcs_write_seq(dsi, 0xbd, 0x00);
+ dsi_dcs_write_seq(dsi, 0xc6, 0xed);
+
+ // msleep(0xfa);
+ // dsi_dcs_write_seq(dsi, 0x11);
+ // msleep(0x32);
+ // dsi_dcs_write_seq(dsi, 0x29);
+
+ return 0;
+}
+
+static const struct drm_display_mode hsd060bhw4_mode = {
+ .hdisplay = 720,
+ .hsync_start = 720 + 40,
+ .hsync_end = 720 + 40 + 40,
+ .htotal = 720 + 40 + 40 + 40,
+ .vdisplay = 1440,
+ .vsync_start = 1440 + 18,
+ .vsync_end = 1440 + 18 + 10,
+ .vtotal = 1440 + 18 + 10 + 17,
+ .clock = 69000,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ .width_mm = 68,
+ .height_mm = 136,
+};
+
+static const struct drm_display_mode hsd060bhw4_mode2 = {
+ .hdisplay = 720,
+ .hsync_start = 720 + 50,
+ .hsync_end = 720 + 50 + 10,
+ .htotal = 720 + 50 + 10 + 50,
+ .vdisplay = 1440,
+ .vsync_start = 1440 + 17,
+ .vsync_end = 1440 + 17 + 4,
+ .vtotal = 1440 + 17 + 4 + 10,
+ .clock = 60000,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ .width_mm = 68,
+ .height_mm = 136,
+};
+
+static const struct hx8394_panel_desc hsd060bhw4_desc = {
+ .mode = &hsd060bhw4_mode,
+ .lanes = 4,
+ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST,// | MIPI_DSI_MODE_LPM,//, // 0x843
+ .format = MIPI_DSI_FMT_RGB888,
+ .init_sequence = hsd060bhw4_init_sequence,
+};
+
+static int hx8394_enable(struct drm_panel *panel)
+{
+ struct hx8394 *ctx = panel_to_hx8394(panel);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ int ret;
+
+ ret = ctx->desc->init_sequence(ctx);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
+ return ret;
+ }
+
+ msleep(20);
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ /* Panel is operational 120 msec after reset */
+ msleep(60);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret)
+ return ret;
+
+ dev_dbg(ctx->dev, "Panel init sequence done\n");
+
+ return 0;
+}
+
+static int hx8394_disable(struct drm_panel *panel)
+{
+ struct hx8394 *ctx = panel_to_hx8394(panel);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0)
+ dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0)
+ dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
+
+ return 0;
+}
+
+static int hx8394_unprepare(struct drm_panel *panel)
+{
+ struct hx8394 *ctx = panel_to_hx8394(panel);
+
+ if (!ctx->prepared)
+ return 0;
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ regulator_disable(ctx->iovcc);
+ regulator_disable(ctx->vcc);
+ ctx->prepared = false;
+
+ return 0;
+}
+
+static int hx8394_prepare(struct drm_panel *panel)
+{
+ struct hx8394 *ctx = panel_to_hx8394(panel);
+ int ret;
+
+ if (ctx->prepared)
+ return 0;
+
+ dev_dbg(ctx->dev, "Resetting the panel\n");
+ ret = regulator_enable(ctx->vcc);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
+ return ret;
+ }
+ ret = regulator_enable(ctx->iovcc);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
+ goto disable_vcc;
+ }
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ mdelay(0x32);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(0x64);
+
+ ctx->prepared = true;
+
+ return 0;
+
+disable_vcc:
+ regulator_disable(ctx->vcc);
+ return ret;
+}
+
+static int hx8394_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct hx8394 *ctx = panel_to_hx8394(panel);
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, ctx->desc->mode);
+ if (!mode) {
+ dev_err(ctx->dev, "Failed to add mode %ux%u@%u\n",
+ ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
+ drm_mode_vrefresh(ctx->desc->mode));
+ return -ENOMEM;
+ }
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+ drm_mode_probed_add(connector, mode);
+
+ return 1;
+}
+
+static const struct drm_panel_funcs hx8394_drm_funcs = {
+ .disable = hx8394_disable,
+ .unprepare = hx8394_unprepare,
+ .prepare = hx8394_prepare,
+ .enable = hx8394_enable,
+ .get_modes = hx8394_get_modes,
+};
+
+static int allpixelson_set(void *data, u64 val)
+{
+ struct hx8394 *ctx = data;
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+
+ dev_dbg(ctx->dev, "Setting all pixels on\n");
+ dsi_generic_write_seq(dsi, 0x23);
+ msleep(val * 1000);
+ /* Reset the panel to get video back */
+ drm_panel_disable(&ctx->panel);
+ drm_panel_unprepare(&ctx->panel);
+ drm_panel_prepare(&ctx->panel);
+ drm_panel_enable(&ctx->panel);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(allpixelson_fops, NULL,
+ allpixelson_set, "%llu\n");
+
+static void hx8394_debugfs_init(struct hx8394 *ctx)
+{
+ ctx->debugfs = debugfs_create_dir(DRV_NAME, NULL);
+
+ debugfs_create_file("allpixelson", 0600, ctx->debugfs, ctx,
+ &allpixelson_fops);
+}
+
+static void hx8394_debugfs_remove(struct hx8394 *ctx)
+{
+ debugfs_remove_recursive(ctx->debugfs);
+ ctx->debugfs = NULL;
+}
+
+static int hx8394_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct hx8394 *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
+
+ mipi_dsi_set_drvdata(dsi, ctx);
+
+ ctx->dev = dev;
+ ctx->desc = of_device_get_match_data(dev);
+
+ dsi->mode_flags = ctx->desc->mode_flags;
+ dsi->format = ctx->desc->format;
+ dsi->lanes = ctx->desc->lanes;
+
+ ctx->vcc = devm_regulator_get(dev, "vcc");
+ if (IS_ERR(ctx->vcc))
+ return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
+
+ ctx->iovcc = devm_regulator_get(dev, "iovcc");
+ if (IS_ERR(ctx->iovcc))
+ return dev_err_probe(dev, PTR_ERR(ctx->iovcc),
+ "Failed to request iovcc regulator\n");
+
+ drm_panel_init(&ctx->panel, dev, &hx8394_drm_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return ret;
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ dev_info(dev, "%ux%u@%u %ubpp dsi %udl - ready\n",
+ ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
+ drm_mode_vrefresh(ctx->desc->mode),
+ mipi_dsi_pixel_format_to_bpp(dsi->format), dsi->lanes);
+
+ hx8394_debugfs_init(ctx);
+ return 0;
+}
+
+static void hx8394_shutdown(struct mipi_dsi_device *dsi)
+{
+ struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = drm_panel_unprepare(&ctx->panel);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
+
+ ret = drm_panel_disable(&ctx->panel);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
+}
+
+static int hx8394_remove(struct mipi_dsi_device *dsi)
+{
+ struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ hx8394_shutdown(dsi);
+
+ ret = mipi_dsi_detach(dsi);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
+
+ drm_panel_remove(&ctx->panel);
+
+ hx8394_debugfs_remove(ctx);
+
+ return 0;
+}
+
+static const struct of_device_id hx8394_of_match[] = {
+ { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hx8394_of_match);
+
+static struct mipi_dsi_driver hx8394_driver = {
+ .probe = hx8394_probe,
+ .remove = hx8394_remove,
+ .shutdown = hx8394_shutdown,
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = hx8394_of_match,
+ },
+};
+module_mipi_dsi_driver(hx8394_driver);
+
+MODULE_AUTHOR("Kamil Trzciński <ayufan@ayufan.eu>");
+MODULE_DESCRIPTION("DRM driver for Himax HX8394 based MIPI DSI panels");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,226 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 17 Oct 2021 18:03:05 +0200
Subject: [PATCH 06/36] drm: panel: hx8394: Improve the panel driver (make it
work with DSI fixes)
Powerup/down should be done in prepare/unprepare. Enable/disable is just
for initialization. Fix timings and reset order according to datasheet.
Reset panel on probe.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/panel/panel-himax-hx8394.c | 84 ++++++++++++++++++------------
1 file changed, 52 insertions(+), 32 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index 14659cb..2f69b94 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -89,11 +89,6 @@ static int hsd060bhw4_init_sequence(struct hx8394 *ctx)
dsi_dcs_write_seq(dsi, 0xbd, 0x00);
dsi_dcs_write_seq(dsi, 0xc6, 0xed);
- // msleep(0xfa);
- // dsi_dcs_write_seq(dsi, 0x11);
- // msleep(0x32);
- // dsi_dcs_write_seq(dsi, 0x29);
-
return 0;
}
@@ -141,30 +136,38 @@ static int hx8394_enable(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
+ dev_info(ctx->dev, "enable\n");
+
ret = ctx->desc->init_sequence(ctx);
- if (ret < 0) {
+ if (ret) {
dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
return ret;
}
- msleep(20);
-
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
- if (ret < 0) {
+ if (ret) {
dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
return ret;
}
/* Panel is operational 120 msec after reset */
- msleep(60);
+ msleep(120);
ret = mipi_dsi_dcs_set_display_on(dsi);
- if (ret)
- return ret;
-
- dev_dbg(ctx->dev, "Panel init sequence done\n");
+ if (ret) {
+ dev_err(ctx->dev, "Failed to turn on the display: %d\n", ret);
+ goto sleep_in;
+ }
return 0;
+
+sleep_in:
+ /* This will probably fail, but let's try orderly power off anyway. */
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (!ret)
+ msleep(50);
+
+ return ret;
}
static int hx8394_disable(struct drm_panel *panel)
@@ -173,13 +176,15 @@ static int hx8394_disable(struct drm_panel *panel)
struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
- ret = mipi_dsi_dcs_set_display_off(dsi);
- if (ret < 0)
- dev_err(ctx->dev, "Failed to turn off the display: %d\n", ret);
+ dev_info(ctx->dev, "disable\n");
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
- if (ret < 0)
+ if (ret) {
dev_err(ctx->dev, "Failed to enter sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ msleep(50); /* about 3 frames */
return 0;
}
@@ -187,13 +192,19 @@ static int hx8394_disable(struct drm_panel *panel)
static int hx8394_unprepare(struct drm_panel *panel)
{
struct hx8394 *ctx = panel_to_hx8394(panel);
+ //struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ //int ret;
if (!ctx->prepared)
return 0;
+ dev_info(ctx->dev, "unprepare\n");
+
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
regulator_disable(ctx->iovcc);
regulator_disable(ctx->vcc);
+
ctx->prepared = false;
return 0;
@@ -202,33 +213,38 @@ static int hx8394_unprepare(struct drm_panel *panel)
static int hx8394_prepare(struct drm_panel *panel)
{
struct hx8394 *ctx = panel_to_hx8394(panel);
+ //struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
int ret;
if (ctx->prepared)
return 0;
- dev_dbg(ctx->dev, "Resetting the panel\n");
+ dev_info(ctx->dev, "prepare\n");
+
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+
ret = regulator_enable(ctx->vcc);
- if (ret < 0) {
+ if (ret) {
dev_err(ctx->dev, "Failed to enable vcc supply: %d\n", ret);
return ret;
}
+
ret = regulator_enable(ctx->iovcc);
- if (ret < 0) {
+ if (ret) {
dev_err(ctx->dev, "Failed to enable iovcc supply: %d\n", ret);
goto disable_vcc;
}
- gpiod_set_value_cansleep(ctx->reset_gpio, 1);
- mdelay(0x32);
gpiod_set_value_cansleep(ctx->reset_gpio, 0);
- msleep(0x64);
+
+ msleep(180);
ctx->prepared = true;
return 0;
disable_vcc:
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
regulator_disable(ctx->vcc);
return ret;
}
@@ -273,9 +289,11 @@ static int allpixelson_set(void *data, u64 val)
dev_dbg(ctx->dev, "Setting all pixels on\n");
dsi_generic_write_seq(dsi, 0x23);
msleep(val * 1000);
+
/* Reset the panel to get video back */
drm_panel_disable(&ctx->panel);
drm_panel_unprepare(&ctx->panel);
+
drm_panel_prepare(&ctx->panel);
drm_panel_enable(&ctx->panel);
@@ -309,9 +327,10 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
if (!ctx)
return -ENOMEM;
- ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(ctx->reset_gpio))
- return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), "Failed to get reset gpio\n");
+ return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),
+ "Failed to get reset gpio\n");
mipi_dsi_set_drvdata(dsi, ctx);
@@ -324,7 +343,8 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
ctx->vcc = devm_regulator_get(dev, "vcc");
if (IS_ERR(ctx->vcc))
- return dev_err_probe(dev, PTR_ERR(ctx->vcc), "Failed to request vcc regulator\n");
+ return dev_err_probe(dev, PTR_ERR(ctx->vcc),
+ "Failed to request vcc regulator\n");
ctx->iovcc = devm_regulator_get(dev, "iovcc");
if (IS_ERR(ctx->iovcc))
@@ -342,7 +362,7 @@ static int hx8394_probe(struct mipi_dsi_device *dsi)
ret = mipi_dsi_attach(dsi);
if (ret < 0) {
- dev_err(dev, "mipi_dsi_attach failed (%d). Is host ready?\n", ret);
+ dev_err_probe(dev, ret, "mipi_dsi_attach failed\n");
drm_panel_remove(&ctx->panel);
return ret;
}
@@ -361,13 +381,13 @@ static void hx8394_shutdown(struct mipi_dsi_device *dsi)
struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi);
int ret;
- ret = drm_panel_unprepare(&ctx->panel);
- if (ret < 0)
- dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
-
ret = drm_panel_disable(&ctx->panel);
if (ret < 0)
dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
+
+ ret = drm_panel_unprepare(&ctx->panel);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
}
static int hx8394_remove(struct mipi_dsi_device *dsi)

View File

@ -0,0 +1,29 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 16 Nov 2021 21:19:42 +0100
Subject: [PATCH 08/36] drm: panel: hx8394: Fix mode clock for the pinephone
pro panel
The actual rate that was set by CRU was 66.333 MHz The panel does
not actually work at 69 MHz, now that CRU can generate the requested
clock rate precisely.
Change the clock rate.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/gpu/drm/panel/panel-himax-hx8394.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panel/panel-himax-hx8394.c b/drivers/gpu/drm/panel/panel-himax-hx8394.c
index 2f69b94..7a2f74a 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx8394.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx8394.c
@@ -101,7 +101,7 @@ static const struct drm_display_mode hsd060bhw4_mode = {
.vsync_start = 1440 + 18,
.vsync_end = 1440 + 18 + 10,
.vtotal = 1440 + 18 + 10 + 17,
- .clock = 69000,
+ .clock = 66000, /*XXX: only 66MHz works */
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
.width_mm = 68,
.height_mm = 136,

View File

@ -0,0 +1,97 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 25 Apr 2021 03:16:42 +0200
Subject: input: goodix: Add option to power off the controller during suspend
For whatever reason the controller is not suspended on Pinephone
by the default procedure. It consumes quite a bit of power (~40mW)
during system sleep, and more when the screen is touched.
Let's power off the controller during system sleep instead.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/input/touchscreen/goodix.c | 37 +++++++++++++++++++++++++++++++++++++
drivers/input/touchscreen/goodix.h | 1 +
2 files changed, 38 insertions(+)
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index b5cc917..90a3584 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1133,6 +1133,7 @@ static void goodix_disable_regulators(void *arg)
static int goodix_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
+ struct device_node *np = client->dev.of_node;
struct goodix_ts_data *ts;
const char *cfg_name;
int error;
@@ -1152,6 +1153,7 @@ static int goodix_ts_probe(struct i2c_client *client,
i2c_set_clientdata(client, ts);
init_completion(&ts->firmware_loading_complete);
ts->contact_size = GOODIX_CONTACT_SIZE;
+ ts->poweroff_in_suspend = of_property_read_bool(np, "poweroff-in-suspend");
error = goodix_get_gpio_config(ts);
if (error)
@@ -1261,6 +1263,15 @@ static int __maybe_unused goodix_suspend(struct device *dev)
if (ts->load_cfg_from_disk)
wait_for_completion(&ts->firmware_loading_complete);
+ if (ts->poweroff_in_suspend) {
+ goodix_free_irq(ts);
+ goodix_irq_direction_output(ts, 0);
+ gpiod_direction_output(ts->gpiod_rst, 0);
+ regulator_disable(ts->avdd28);
+ regulator_disable(ts->vddio);
+ return 0;
+ }
+
/* We need gpio pins to suspend/resume */
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
disable_irq(client->irq);
@@ -1306,6 +1317,32 @@ static int __maybe_unused goodix_resume(struct device *dev)
u8 config_ver;
int error;
+ if (ts->poweroff_in_suspend) {
+ error = regulator_enable(ts->avdd28);
+ if (error) {
+ dev_err(dev, "Regulator avdd28 enable failed.\n");
+ return error;
+ }
+
+ error = regulator_enable(ts->vddio);
+ if (error) {
+ dev_err(dev, "Regulator vddio enable failed.\n");
+ return error;
+ }
+
+ error = goodix_reset(ts);
+ if (error) {
+ dev_err(dev, "Controller reset failed.\n");
+ return error;
+ }
+
+ error = goodix_request_irq(ts);
+ if (error)
+ return error;
+
+ return 0;
+ }
+
if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) {
enable_irq(client->irq);
return 0;
diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
index 62138f9..3bb51ea 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -101,6 +101,7 @@ struct goodix_ts_data {
u8 main_clk[GOODIX_MAIN_CLK_LEN];
int bak_ref_len;
u8 *bak_ref;
+ bool poweroff_in_suspend;
};
int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);

View File

@ -0,0 +1,49 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sat, 1 May 2021 01:28:07 +0200
Subject: input: goodix: Don't disable regulators during suspend
It does no harm to disable them, but on Pinephone we have other
peripherals attached to the same power supplies, whose drivers
will not reference the regulator, so powering down the regulators
from Goodix driver will break those other devices.
Until those drivers gain the regulator support, don't disable
the regulators in Goodix driver.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/input/touchscreen/goodix.c | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 90a3584..5f78dc1 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1267,8 +1267,6 @@ static int __maybe_unused goodix_suspend(struct device *dev)
goodix_free_irq(ts);
goodix_irq_direction_output(ts, 0);
gpiod_direction_output(ts->gpiod_rst, 0);
- regulator_disable(ts->avdd28);
- regulator_disable(ts->vddio);
return 0;
}
@@ -1318,18 +1316,6 @@ static int __maybe_unused goodix_resume(struct device *dev)
int error;
if (ts->poweroff_in_suspend) {
- error = regulator_enable(ts->avdd28);
- if (error) {
- dev_err(dev, "Regulator avdd28 enable failed.\n");
- return error;
- }
-
- error = regulator_enable(ts->vddio);
- if (error) {
- dev_err(dev, "Regulator vddio enable failed.\n");
- return error;
- }
-
error = goodix_reset(ts);
if (error) {
dev_err(dev, "Controller reset failed.\n");

View File

@ -0,0 +1,53 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 18 Oct 2021 03:56:14 +0200
Subject: [PATCH 17/36] input: touchscreen: goodix: Respect IRQ flags from DT
when asked to
Sometimes the IRQ flags determined from toucschreen config don't
work well.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/input/touchscreen/goodix.c | 7 ++++++-
drivers/input/touchscreen/goodix.h | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 5f78dc1..91836019 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -400,9 +400,13 @@ static void goodix_free_irq(struct goodix_ts_data *ts)
static int goodix_request_irq(struct goodix_ts_data *ts)
{
+ unsigned long irq_flags = ts->irq_flags;
+ if (ts->use_dt_irqflags)
+ irq_flags = IRQF_ONESHOT;
+
return devm_request_threaded_irq(&ts->client->dev, ts->client->irq,
NULL, goodix_ts_irq_handler,
- ts->irq_flags, ts->client->name, ts);
+ irq_flags, ts->client->name, ts);
}
static int goodix_check_cfg_8(struct goodix_ts_data *ts, const u8 *cfg, int len)
@@ -1149,6 +1153,7 @@ static int goodix_ts_probe(struct i2c_client *client,
if (!ts)
return -ENOMEM;
+ ts->use_dt_irqflags = of_property_read_bool(np, "use-dt-irq-flags");
ts->client = client;
i2c_set_clientdata(client, ts);
init_completion(&ts->firmware_loading_complete);
diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h
index 3bb51ea..0e992a8 100644
--- a/drivers/input/touchscreen/goodix.h
+++ b/drivers/input/touchscreen/goodix.h
@@ -80,6 +80,7 @@ struct goodix_ts_data {
const char *firmware_name;
struct touchscreen_properties prop;
unsigned int max_touch_num;
+ bool use_dt_irqflags;
unsigned int int_trigger_type;
struct regulator *avdd28;
struct regulator *vddio;

View File

@ -0,0 +1,23 @@
From: Ondrej Jirman <megous@megous.com>
Date: Thu, 11 Nov 2021 14:28:41 +0100
Subject: [PATCH 18/36] input: touchscreen: goodix: Add support for GT1158
This controller is used by Pinephone Pro.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
drivers/input/touchscreen/goodix.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 91836019..e2167d8 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -94,6 +94,7 @@ static const struct goodix_chip_data gt9x_chip_data = {
static const struct goodix_chip_id goodix_chip_ids[] = {
{ .id = "1151", .data = &gt1x_chip_data },
+ { .id = "1158", .data = &gt1x_chip_data },
{ .id = "5663", .data = &gt1x_chip_data },
{ .id = "5688", .data = &gt1x_chip_data },
{ .id = "917S", .data = &gt1x_chip_data },

View File

@ -0,0 +1,101 @@
From: Ondrej Jirman <megous@megous.com>
Date: Wed, 22 Sep 2021 19:30:39 +0200
Subject: [PATCH 02/18] arm64: dts: rk3399-pinephone-pro: Fixup DT validation
issues
Fixes:
rk3399-pinephone-pro.dts:751.4-14: Warning (reg_format): /mipi@ff960000/panel/port:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1)
rk3399-pinephone-pro.dtb: Warning (pci_device_reg): Failed prerequisite 'reg_format'
rk3399-pinephone-pro.dtb: Warning (pci_device_bus_num): Failed prerequisite 'reg_format'
rk3399-pinephone-pro.dtb: Warning (i2c_bus_reg): Failed prerequisite 'reg_format'
rk3399-pinephone-pro.dtb: Warning (spi_bus_reg): Failed prerequisite 'reg_format'
rk3399-pinephone-pro.dts:747.8-756.5: Warning (avoid_default_addr_size): /mipi@ff960000/panel/port: Relying on default #address-cells value
rk3399-pinephone-pro.dts:747.8-756.5: Warning (avoid_default_addr_size): /mipi@ff960000/panel/port: Relying on default #size-cells value
rk3399-pinephone-pro.dts:747.8-756.5: Warning (graph_port): /mipi@ff960000/panel/port: graph node unit address error, expected "0"
rk3399-pinephone-pro.dts:748.4-25: Warning (graph_port): /mipi@ff960000/panel/port:#address-cells: graph node '#address-cells' is -1, must be 1
rk3399-pinephone-pro.dts:749.4-22: Warning (graph_port): /mipi@ff960000/panel/port:#size-cells: graph node '#size-cells' is -1, must be 0
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index b53df0d..de8a1f3 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -626,7 +626,6 @@ fusb0: typec-portc@22 {
pinctrl-names = "default";
pinctrl-0 = <&fusb0_int>;
vbus-supply = <&vcc5v0_typec>;
- status = "okay";
connector {
compatible = "usb-c-connector";
@@ -691,23 +690,25 @@ accelerometer@68 {
"0", "0", "1";
};
- lis3mdl: magnetometer@1e {
+ lis3mdl: magnetometer@1c {
compatible = "st,lis3mdl-magn";
reg = <0x1c>;
interrupt-parent = <&gpio1>;
interrupts = <RK_PA1 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&vcc3v3_sys>;
vddio-supply = <&vcc_1v8>;
+ status = "disabled";
};
// not populated currently
- ak09911: compass@0c {
+ ak09911: compass@c {
compatible = "asahi-kasei,ak09911";
reg = <0x0c>;
interrupt-parent = <&gpio1>;
interrupts = <RK_PA1 IRQ_TYPE_LEVEL_LOW>;
vdd-supply = <&vcc_3v0>;
vid-supply = <&vcc_1v8>;
+ status = "disabled";
};
};
@@ -726,6 +727,8 @@ &mipi_dsi {
ports {
mipi_out: port@1 {
+ #address-cells = <0>;
+ #size-cells = <0>;
reg = <1>;
mipi_out_panel: endpoint {
@@ -734,7 +737,7 @@ mipi_out_panel: endpoint {
};
};
- panel {
+ panel@0 {
compatible = "hannstar,hsd060bhw4";
reg = <0>;
backlight = <&backlight>;
@@ -745,11 +748,6 @@ panel {
pinctrl-0 = <&display_rst_l>;
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
- reg = <0>;
-
mipi_in_panel: endpoint {
remote-endpoint = <&mipi_out_panel>;
};
@@ -757,7 +755,6 @@ mipi_in_panel: endpoint {
};
};
-
&pmu_io_domains {
pmu1830-supply = <&vcc_3v0>;
status = "okay";

View File

@ -0,0 +1,34 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 11 Oct 2021 17:32:31 +0200
Subject: [PATCH 03/18] arm64: dts: rk3399-pinephone-pro: Make charging and
peripheral mode work
Signed-of-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index de8a1f3..eb2d15e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -511,8 +511,8 @@ otg_switch: OTG_SWITCH {
regulator-name = "otg_switch";
// TODO: This requires a proper rk818-charger implementation
// without this always-on the type-c is not powered on
- regulator-always-on;
- regulator-boot-on;
+ //regulator-always-on;
+ //regulator-boot-on;
};
};
@@ -1013,7 +1013,7 @@ &usbdrd3_0 {
};
&usbdrd_dwc3_0 {
- dr_mode = "host";
+ dr_mode = "peripheral";
status = "okay";
};

View File

@ -0,0 +1,30 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 18 Oct 2021 03:55:15 +0200
Subject: [PATCH 04/18] arm64: dts: rk3399-pinephone-pro: Fix goodix
toucscreen interrupts
The interrupt type read from the screen does not work well. It generates
constant stream of interrupts.
Change to rising edge interrupt, and enforce it in the driver via
'use-dt-irq-flags'.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index eb2d15e..83eb683 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -594,7 +594,8 @@ touchscreen@14 {
compatible = "goodix,gt917s";
reg = <0x14>;
interrupt-parent = <&gpio3>;
- interrupts = <RK_PB5 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <RK_PB5 IRQ_TYPE_EDGE_RISING>;
+ use-dt-irq-flags;
irq-gpios = <&gpio3 RK_PB5 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_HIGH>;
AVDD28-supply = <&vcc3v0_touch>;

View File

@ -0,0 +1,26 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 18 Oct 2021 03:57:56 +0200
Subject: [PATCH 05/18] arm64: dts: rk3399-pinephone-pro: Correct the pmu1830
io-domain supply
It's connected to vcc_1v8 according to datasheet. Credits to carlos
for noticing!
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 83eb683..59733033 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -757,7 +757,7 @@ mipi_in_panel: endpoint {
};
&pmu_io_domains {
- pmu1830-supply = <&vcc_3v0>;
+ pmu1830-supply = <&vcc_1v8>;
status = "okay";
};

View File

@ -0,0 +1,25 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 18 Oct 2021 03:58:56 +0200
Subject: [PATCH 06/18] arm64: dts: rk3399-pinephone-pro: Power off goodix
touchscreen in sleep
Otherwise it consumes 200mW of power when touched during system sleep.
It can't wake up the phone anyway.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 59733033..96b5170 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -602,6 +602,7 @@ touchscreen@14 {
VDDIO-supply = <&vcc3v0_touch>;
touchscreen-size-x = <720>;
touchscreen-size-y = <1440>;
+ poweroff-in-suspend;
};
light-sensor@48 {

View File

@ -0,0 +1,198 @@
From: Ondrej Jirman <megous@megous.com>
Date: Thu, 21 Oct 2021 20:25:35 +0200
Subject: [PATCH 07/18] arm64: dts: rk3399-pinephone-pro: Add support for both
cameras
IMX258 + OV5640.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 146 ++++++++++++++++++++-
1 file changed, 142 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 96b5170..3e9aa7b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -456,8 +456,6 @@ regulator-state-mem {
vcc1v8_dvp: LDO_REG7 {
regulator-name = "vcc1v8_dvp";
- regulator-always-on;
- regulator-boot-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-state-mem {
@@ -579,10 +577,92 @@ regulator-state-mem {
};
};
+/*
+ * Cameras:
+ *
+ * cif clk out = gpio2 B3 / CIF_CLKOUTA_u
+ *
+ * both on i2c1 GPIO4_A1 (SDA) / GPIO4_A2 (SCL)
+ *
+ * both share power:
+ * VCC1V8_DVP - LDO7 - supplied by VCC7 (VCC3V3_SYS)
+ * DVDD_DVP 1.5V - autoenabled by VCC2V8_DVP depends on VCC1V8_S3 (U118 supplies 1.2V, though, not 1.5V)
+ * VCC2V8_DVP af - autoenabled by VCC1V8_DVP depends on VCC3V3_SYS
+ * AVDD2V8_DVP - autoenabled by VCC1V8_DVP depends on VCC3V3_SYS
+ *
+ * mipi0 = imx258
+ * reset = gpio1 A0
+ * powerdown = GPIO2_B4
+ *
+ * mipi1 = OV5640
+ * powerdown = GPIO2_D4
+ *
+ * bt656-supply = <&vcc1v8_dvp>;
+ */
&i2c1 {
+ status = "okay";
+
+ clock-frequency = <400000>;
i2c-scl-rising-time-ns = <300>;
i2c-scl-falling-time-ns = <15>;
- status = "okay";
+
+ pinctrl-0 = <&i2c1_xfer &cif_clkouta>;
+
+ assigned-clocks = <&cru SCLK_CIF_OUT &cru SCLK_CIF_OUT_SRC>;
+ assigned-clock-parents = <&cru SCLK_CIF_OUT_SRC &cru PLL_GPLL>;
+ assigned-clock-rates = <19200000 0>;
+
+ /* Rear-facing camera */
+ wcam: camera@1a {
+ compatible = "sony,imx258";
+ reg = <0x1a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&wcam_rst &wcam_pdn>;
+
+ clocks = <&cru SCLK_CIF_OUT>;
+ clock-names = "xvclk";
+
+ vif-supply = <&vcc1v8_dvp>;
+ /*XXX: also depends on vcca1v8_codec for I2C bus power */
+
+ reset-gpios = <&gpio1 RK_PA0 GPIO_ACTIVE_LOW>;
+ powerdown-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_HIGH>;
+ rotation = <180>;
+
+ port {
+ wcam_out: endpoint {
+ remote-endpoint = <&mipi_in_wcam>;
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <320000000>;
+ //link-frequencies = /bits/ 64 <633600000>;
+ };
+ };
+ };
+
+ /* Front-facing camera */
+ ucam: camera@3c {
+ compatible = "ovti,ov5640";
+ reg = <0x3c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ucam_pdn>;
+
+ clocks = <&cru SCLK_CIF_OUT>;
+ clock-names = "xclk";
+
+ DOVDD-supply = <&vcc1v8_dvp>;
+ /*XXX: also depends on vcca1v8_codec for I2C bus power */
+
+ powerdown-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;
+ rotation = <180>;
+
+ port {
+ ucam_out: endpoint {
+ remote-endpoint = <&mipi_in_ucam>;
+ data-lanes = <1 2>;
+ clock-lanes = <0>;
+ };
+ };
+ };
};
&i2c3 {
@@ -723,6 +803,50 @@ &io_domains {
gpio1830-supply = <&vcc_3v0>;
};
+&isp0 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ mipi_in_wcam: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&wcam_out>;
+ data-lanes = <1 2 3 4>;
+ };
+ };
+ };
+};
+
+&mipi_dphy_rx0 {
+ status = "okay";
+};
+
+&isp1 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ mipi_in_ucam: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&ucam_out>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+};
+
+&isp0_mmu {
+ status = "okay";
+};
+
+&isp1_mmu {
+ status = "okay";
+};
+
+&mipi_dsi1 {
+ status = "okay";
+};
+
&mipi_dsi {
status = "okay";
clock-master;
@@ -783,6 +907,20 @@ pwrbtn_pin: pwrbtn-pin {
};
};
+ camera {
+ wcam_rst: wcam-rst {
+ rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wcam_pdn: wcam-pdn {
+ rockchip,pins = <2 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ ucam_pdn: ucam-pdn {
+ rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
fusb302x {
fusb0_int: fusb0-int {
rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>;
@@ -1033,4 +1171,4 @@ &vopl {
&vopl_mmu {
status = "okay";
-};
\ No newline at end of file
+};

View File

@ -0,0 +1,71 @@
From: Ondrej Jirman <megous@megous.com>
Date: Wed, 20 Oct 2021 22:41:43 +0200
Subject: [PATCH 08/18] arm64: dts: rk3399-pinephone-pro: Fix SD card power
supply definition
GPIO0_A1 is used for modem's RI. SD card power supply is not changeable.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 27 ++++------------------
1 file changed, 5 insertions(+), 22 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 3e9aa7b..e6aac03 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -215,23 +215,6 @@ vcc1v8_codec: vcc1v8-codec-regulator {
vin-supply = <&vcc3v3_sys>;
};
- /* micro SD card power */
- vcc3v0_sd: vcc3v0-sd {
- compatible = "regulator-fixed";
- enable-active-high;
- gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc0_pwr_h>;
- regulator-name = "vcc3v0_sd";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- vin-supply = <&vcc3v3_sys>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- };
-
/* MIPI DSI panel 1.8v supply */
vcc1v8_lcd: vcc1v8-lcd {
compatible = "regulator-fixed";
@@ -474,8 +457,8 @@ regulator-state-mem {
};
};
- vcc_sd: LDO_REG9 {
- regulator-name = "vcc_sd";
+ vccio_sd: LDO_REG9 {
+ regulator-name = "vccio_sd";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-state-mem {
@@ -799,7 +782,7 @@ &io_domains {
bt656-supply = <&vcc1v8_dvp>;
audio-supply = <&vcca1v8_codec>;
- sdmmc-supply = <&vcc_sd>;
+ sdmmc-supply = <&vccio_sd>;
gpio1830-supply = <&vcc_3v0>;
};
@@ -1034,8 +1017,8 @@ &sdmmc {
max-frequency = <150000000>;
pinctrl-names = "default";
pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
- vmmc-supply = <&vcc3v0_sd>;
- vqmmc-supply = <&vcc_sd>;
+ vmmc-supply = <&vcc3v3_sys>;
+ vqmmc-supply = <&vccio_sd>;
status = "okay";
};

View File

@ -0,0 +1,44 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 25 Oct 2021 17:49:41 +0200
Subject: [PATCH 09/18] arm64: dts: rk3399-pinephone-pro: Correct the battery
specification
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit
XLS with ZCV measurements from the manufacturer say that at 25°C,
ZCV is ~200 mOhm. At 50°C it's at ~100 mOhm. Set some value in between.
Lower the charging current to something less aggressive.
Fix the current sensing resitor value (it's 10 mOhm in the schematic).
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index e6aac03..ffdaaa6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -504,16 +504,16 @@ battery {
4110 4161 4217 4308>;
design_capacity = <2916>;
design_qmax = <2708>;
- bat_res = <65>;
+ bat_res = <150>;
max_input_current = <3000>;
- max_chrg_current = <3000>;
+ max_chrg_current = <2000>;
max_chrg_voltage = <4350>;
sleep_enter_current = <300>;
sleep_exit_current = <300>;
power_off_thresd = <3400>;
zero_algorithm_vol = <3950>;
fb_temperature = <105>;
- sample_res = <20>;
+ sample_res = <10>;
max_soc_offset = <60>;
energy_mode = <0>;
monitor_sec = <5>;

View File

@ -0,0 +1,32 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 26 Oct 2021 01:29:50 +0200
Subject: [PATCH 10/18] arm64: dts: rk3399-pinephone-pro: Cleanup some USB
nodes whitespace
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index ffdaaa6..d9159d4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -1067,7 +1067,7 @@ u2phy0_otg: otg-port {
u2phy0_host: host-port {
status = "okay";
- phy-supply = <&vcc5v0_sys>;
+ phy-supply = <&vcc5v0_sys>;
};
port {
@@ -1086,7 +1086,7 @@ u2phy1_otg: otg-port {
u2phy1_host: host-port {
status = "okay";
- phy-supply = <&vcc5v0_sys>;
+ phy-supply = <&vcc5v0_sys>;
};
};

View File

@ -0,0 +1,33 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 26 Oct 2021 01:30:14 +0200
Subject: [PATCH 11/18] arm64: dts: rk3399-pinephone-pro: Fix PDOs to be more
reasonable
Let's not overtax the battery and provide only 4.5W to external devices.
Even that may be too much, given what PPP can consume by itself.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index d9159d4..9493672 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -696,12 +696,10 @@ connector {
compatible = "usb-c-connector";
data-role = "dual";
label = "USB-C";
- op-sink-microwatt = <1000000>;
+ op-sink-microwatt = <2500000>;
power-role = "dual";
- sink-pdos =
- <PDO_FIXED(5000, 2500, PDO_FIXED_USB_COMM)>;
- source-pdos =
- <PDO_FIXED(5000, 1400, PDO_FIXED_USB_COMM)>;
+ sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+ source-pdos = <PDO_FIXED(5000, 900, PDO_FIXED_USB_COMM)>;
try-power-role = "sink";
extcon-cables = <1 2 5 6 9 10 12 44>;

View File

@ -0,0 +1,24 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 2 Nov 2021 13:28:24 +0100
Subject: [PATCH 12/18] arm64: dts: rk3399-pinephone-pro: Add chassis-type =
"handset" to DT
This way, desktop environment can pick up device type from DT.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 9493672..3f944af 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -17,6 +17,7 @@
/ {
model = "Pine64 PinePhonePro";
compatible = "pine64,pinephone-pro", "rockchip,rk3399";
+ chassis-type = "handset";
chosen {
bootargs = "earlycon=uart8250,mmio32,0xff1a0000";

View File

@ -0,0 +1,29 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 2 Nov 2021 13:29:29 +0100
Subject: [PATCH 13/18] arm64: dts: rk3399-pinephone-pro: Add mmc aliases to
get stable numbering
It's better to have stable meanings for /dev/mmcblk* device files.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 3f944af..58710a6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -19,6 +19,12 @@ / {
compatible = "pine64,pinephone-pro", "rockchip,rk3399";
chassis-type = "handset";
+ aliases {
+ mmc0 = &sdio0;
+ mmc1 = &sdmmc;
+ mmc2 = &sdhci;
+ };
+
chosen {
bootargs = "earlycon=uart8250,mmio32,0xff1a0000";
stdout-path = "serial2:1500000n8";

View File

@ -0,0 +1,23 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 19:30:46 +0100
Subject: [PATCH 14/18] arm64: dts: rk3399-pinephone-pro: Use a new
rk818-battery compatible
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 58710a6..1b4eb26 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -505,7 +505,7 @@ otg_switch: OTG_SWITCH {
};
battery {
- compatible = "rk818-battery";
+ compatible = "rockchip,rk818-battery";
ocv_table = <3400 3675 3689 3716 3740 3756 3768 3780
3793 3807 3827 3853 3896 3937 3974 4007 4066
4110 4161 4217 4308>;

View File

@ -0,0 +1,294 @@
From: Ondrej Jirman <megous@megous.com>
Date: Sun, 7 Nov 2021 19:39:20 +0100
Subject: [PATCH 15/18] arm64: dts: rk3399-pinephone-pro: Full support for
Type-C port
Connect various devices to a extcon bridge. Fix some incorrectly
specified regulators. With this patch, this is now supported:
- PD charger / current limiting
- Alt-DisplayPort mode
- OTG - host/peripheral USB
- B1.2 detection
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 142 +++++++++++++++------
1 file changed, 103 insertions(+), 39 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 1b4eb26..f6eac416 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -12,8 +12,6 @@
#include "rk3399.dtsi"
#include "rk3399-opp.dtsi"
-#define WITHOUT_CDN_DP // TODO: everything works, but it is simpler to test mipi
-
/ {
model = "Pine64 PinePhonePro";
compatible = "pine64,pinephone-pro", "rockchip,rk3399";
@@ -50,6 +48,43 @@ button-down {
};
};
+ bat: battery {
+ compatible = "simple-battery";
+ voltage-min-design-microvolt = <3400000>;
+ voltage-max-design-microvolt = <4350000>;
+ energy-full-design-microwatt-hours = <11400000>;
+ charge-full-design-microamp-hours = <3000000>;
+ precharge-current-microamp = <120000>;
+ charge-term-current-microamp = <150000>;
+ constant-charge-current-max-microamp = <1500000>;
+ constant-charge-voltage-max-microvolt = <4350000>;
+ factory-internal-resistance-micro-ohms = <150000>;
+ resistance-temp-table = <20 150>;
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 =
+ <4308000 100>,
+ <4217000 95>,
+ <4161000 90>,
+ <4110000 85>,
+ <4066000 80>,
+ <4007000 75>,
+ <3974000 70>,
+ <3937000 65>,
+ <3896000 60>,
+ <3853000 55>,
+ <3827000 50>,
+ <3807000 45>,
+ <3793000 40>,
+ <3780000 35>,
+ <3768000 30>,
+ <3756000 25>,
+ <3740000 20>,
+ <3716000 15>,
+ <3689000 10>,
+ <3675000 5>,
+ <3400000 0>;
+ };
+
cluster1_opp_ppp: opp-table1b {
compatible = "operating-points-v2";
opp-shared;
@@ -168,25 +203,35 @@ vcc5v0_sys: vcc5v0-host-regulator {
regulator-max-microvolt = <5000000>;
regulator-always-on;
regulator-boot-on;
- vin-supply = <&vcc_sysin>;
+ vin-supply = <&boost_otg>;
regulator-state-mem {
regulator-on-in-suspend;
};
};
+ /*
+ * This is not a regulator, but GPIO0_A6 is used to disable
+ * VCC_SYS -> VBAT+ switch that helps boost that power path's
+ * current carrying capacity.
+ *
+ * GPIO0_A6 high: path is disabled no matter what
+ * GPIO0_A6 low: path is enabled if there's 5V voltage on
+ * VBUS_TYPEC
+ *
+ * GPIO0_A6 must be high when the phone is providing VBUS_TYPEC
+ * power.
+ */
vcc5v0_typec: vcc5v0-typec-regulator {
compatible = "regulator-fixed";
- //enable-active-high;
+ enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&vcc5v0_typec_en>;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-name = "vcc5v0_typec";
- vin-supply = <&vcc5v0_sys>;
- regulator-always-on;
- regulator-boot-on;
+ vin-supply = <&boost_otg>;
regulator-state-mem {
regulator-on-in-suspend;
@@ -257,6 +302,14 @@ vcca1v8_s3: vcc1v8-s3 {
regulator-always-on;
regulator-boot-on;
};
+
+ typec_extcon_bridge: typec-extcon {
+ compatible = "linux,typec-extcon-bridge";
+ usb-role-switch;
+ orientation-switch;
+ mode-switch;
+ svid = /bits/ 16 <0xff01>;
+ };
};
&cpu_l0 {
@@ -285,12 +338,11 @@ &cpu_b1 {
operating-points-v2 = <&cluster1_opp_ppp>;
};
-#ifndef WITHOUT_CDN_DP
&cdn_dp {
status = "okay";
- extcon = <&fusb0>;
+ extcon = <&typec_extcon_bridge>;
+ phys = <&tcphy0_dp>;
};
-#endif
&emmc_phy {
status = "okay";
@@ -318,7 +370,6 @@ rk818: pmic@1c {
pinctrl-0 = <&pmic_int_l>;
rockchip,system-power-controller;
wakeup-source;
- extcon = <&fusb0>;
vcc1-supply = <&vcc_sysin>;
vcc2-supply = <&vcc_sysin>;
@@ -328,6 +379,7 @@ rk818: pmic@1c {
vcc7-supply = <&vcc3v3_sys>;
vcc8-supply = <&vcc_sysin>;
vcc9-supply = <&vcc3v3_sys>;
+ usb-supply = <&vcc5v0_typec>;
regulators {
vdd_cpu_l: DCDC_REG1 {
@@ -497,13 +549,13 @@ regulator-state-mem {
otg_switch: OTG_SWITCH {
regulator-name = "otg_switch";
- // TODO: This requires a proper rk818-charger implementation
- // without this always-on the type-c is not powered on
- //regulator-always-on;
- //regulator-boot-on;
};
};
+ /*
+ * XXX: Backported BSP stuff, drop this. Use standard
+ * "monitored-battery" property.
+ */
battery {
compatible = "rockchip,rk818-battery";
ocv_table = <3400 3675 3689 3716 3740 3756 3768 3780
@@ -528,6 +580,12 @@ battery {
power_dc2otg = <0>;
otg5v_suspend_enable = <1>;
};
+
+ charger {
+ compatible = "rockchip,rk818-charger";
+ power-supplies = <&fusb0>;
+ monitored-battery = <&bat>;
+ };
};
vdd_cpu_b: regulator@40 {
@@ -697,7 +755,9 @@ fusb0: typec-portc@22 {
interrupts = <RK_PA2 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&fusb0_int>;
- vbus-supply = <&vcc5v0_typec>;
+ extcon = <&typec_extcon_bridge>;
+ usb-role-switch = <&typec_extcon_bridge>;
+ vbus-supply = <&otg_switch>;
connector {
compatible = "usb-c-connector";
@@ -705,12 +765,18 @@ connector {
label = "USB-C";
op-sink-microwatt = <2500000>;
power-role = "dual";
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- source-pdos = <PDO_FIXED(5000, 900, PDO_FIXED_USB_COMM)>;
+ sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
+ source-pdos = <PDO_FIXED(5000, 900, PDO_FIXED_USB_COMM | PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)>;
try-power-role = "sink";
+ mode-switch = <&typec_extcon_bridge>;
+ orientation-switch = <&typec_extcon_bridge>;
- extcon-cables = <1 2 5 6 9 10 12 44>;
- typec-altmodes = <0xff01 1 0x001c0c00 1>;
+ altmodes {
+ dp {
+ svid = <0xff01>;
+ vdo = <0x0c0046>;
+ };
+ };
ports {
#address-cells = <1>;
@@ -1035,7 +1101,7 @@ &sdhci {
};
&tcphy0 {
- extcon = <&fusb0>;
+ extcon = <&typec_extcon_bridge>;
status = "okay";
};
@@ -1065,15 +1131,7 @@ &tsadc {
&u2phy0 {
status = "okay";
-
- u2phy0_otg: otg-port {
- status = "okay";
- };
-
- u2phy0_host: host-port {
- status = "okay";
- phy-supply = <&vcc5v0_sys>;
- };
+ extcon = <&typec_extcon_bridge>;
port {
u2phy0_typec_hs: endpoint {
@@ -1082,17 +1140,22 @@ u2phy0_typec_hs: endpoint {
};
};
-&u2phy1 {
+&u2phy0_otg {
status = "okay";
+};
- u2phy1_otg: otg-port {
- status = "okay";
- };
+&u2phy0_host {
+ status = "okay";
+ phy-supply = <&vcc5v0_sys>;
+};
- u2phy1_host: host-port {
- status = "okay";
- phy-supply = <&vcc5v0_sys>;
- };
+&u2phy1 {
+ status = "okay";
+};
+
+&u2phy1_host {
+ status = "okay";
+ phy-supply = <&vcc5v0_sys>;
};
&uart0 {
@@ -1141,7 +1204,8 @@ &usbdrd3_0 {
};
&usbdrd_dwc3_0 {
- dr_mode = "peripheral";
+ dr_mode = "otg";
+ extcon = <&typec_extcon_bridge>;
status = "okay";
};

View File

@ -0,0 +1,37 @@
From: Ondrej Jirman <megous@megous.com>
Date: Mon, 15 Nov 2021 23:52:40 +0100
Subject: [PATCH 16/18] arm64: dts: rk3399-pinephone-pro: Use DCLK_VOP*_FRAC
to achieve precise rates
By setting parents of DCLK_VOP1_DIV to frac/cpll we can achieve
various clock rates needed by display engine precisely.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index f6eac416..4603788 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -1211,6 +1211,9 @@ &usbdrd_dwc3_0 {
&vopb {
status = "okay";
+ assigned-clocks = <&cru DCLK_VOP0_DIV>, <&cru DCLK_VOP0>, <&cru ACLK_VOP0>, <&cru HCLK_VOP0>;
+ assigned-clock-rates = <0>, <0>, <400000000>, <100000000>;
+ assigned-clock-parents = <&cru PLL_CPLL>, <&cru DCLK_VOP0_FRAC>;
};
&vopb_mmu {
@@ -1219,6 +1222,9 @@ &vopb_mmu {
&vopl {
status = "okay";
+ assigned-clocks = <&cru DCLK_VOP1_DIV>, <&cru DCLK_VOP1>, <&cru ACLK_VOP1>, <&cru HCLK_VOP1>;
+ assigned-clock-rates = <0>, <0>, <400000000>, <100000000>;
+ assigned-clock-parents = <&cru PLL_CPLL>, <&cru DCLK_VOP1_FRAC>;
};
&vopl_mmu {

View File

@ -0,0 +1,78 @@
From: Ondrej Jirman <megous@megous.com>
Date: Tue, 23 Nov 2021 23:26:26 +0100
Subject: [PATCH 17/18] arm64: dts: rk3399-pinephone-pro: Add support for
powering up the modem
Pinephone Pro has the same modem that's already supported by modem-power.
Add support for it do DT.
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 40 ++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 4603788..65cb701 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -253,6 +253,32 @@ regulator-state-mem {
};
};
+ vcc_4g_5v: vcc-4g-5v {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc_4g_5v_en>;
+ regulator-name = "vcc_4g_5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ regulator-always-on;
+ };
+
+ vcc_4g: vcc-4g {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio4 RK_PC7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc_4g_en>;
+ regulator-name = "vcc_4g";
+ regulator-min-microvolt = <3800000>;
+ regulator-max-microvolt = <3800000>;
+ vin-supply = <&vcc_sysin>;
+ regulator-always-on;
+ };
+
vcc1v8_codec: vcc1v8-codec-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -935,6 +961,10 @@ mipi_in_panel: endpoint {
};
};
+&uart3 {
+ status = "okay";
+};
+
&pmu_io_domains {
pmu1830-supply = <&vcc_1v8>;
status = "okay";
@@ -995,6 +1025,16 @@ blue_led_pin: blue-led-pin {
};
};
+ modem {
+ vcc_4g_5v_en: vcc-4g-5v-en-pin {
+ rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc_4g_en: vcc-4g-en-pin {
+ rockchip,pins = <4 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
pmic {
pmic_int_l: pmic-int-l {
rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;

View File

@ -0,0 +1,139 @@
From: Ondrej Jirman <megous@megous.com>
Date: Wed, 24 Nov 2021 01:58:45 +0100
Subject: [PATCH 18/18] arm64: dts: rk3399-pinephone-pro: Add audio support
The codec is complicated, good luck! :D
Signed-off-by: Ondrej Jirman <megous@megous.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 96 ++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 65cb701..4afed92 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -168,6 +168,69 @@ power {
};
};
+ // in1 - digital mic daughhterboard
+ // in2 - headset mic
+ // in3 - modem output (muxed with mono)
+ // spol - earphone
+ // hpo - heaphones
+ // lout - modem input
+ // spaker - amp enabled by SPK_CTL_H
+ //
+ // mclk - GPIO4_A0/I2S_CLK
+ //
+ // some gpio-jack-detection driver?
+ //pinctrl-0 = <&hp_det>; // GPIO4_D4
+
+ rt5640-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "rockchip,rt5640-codec";
+ simple-audio-card,aux-devs = <&speaker_amp>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,mclk-fs = <256>;
+
+ simple-audio-card,widgets =
+ "Microphone", "Headset Microphone",
+ "Microphone", "Internal Microphone",
+ "Headphone", "Headphone Jack",
+ "Speaker", "Internal Earpiece",
+ "Speaker", "Internal Speaker",
+ "Line", "Line In Modem",
+ "Line", "Line Out Modem";
+
+ simple-audio-card,routing =
+ "Headphone Jack", "HPOL",
+ "Headphone Jack", "HPOR",
+ "Internal Earpiece", "SPOLP",
+ "Internal Earpiece", "SPOLN",
+ "Internal Speaker", "Speaker Amp OUTL",
+ "Internal Speaker", "Speaker Amp OUTR",
+ "Speaker Amp INL", "HPOL",
+ "Speaker Amp INR", "HPOR",
+ "DMIC1", "Internal Microphone",
+ "Headset Microphone", "MICBIAS1",
+ "IN2P", "Headset Microphone",
+ "Line Out Modem", "LOUTL",
+ "Line Out Modem", "LOUTR",
+ "IN3P", "Line In Modem",
+ "IN3N", "Line In Modem";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s0>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rt5640>;
+ };
+ };
+
+ speaker_amp: audio-amplifier {
+ compatible = "simple-audio-amplifier";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spk_en>;
+ enable-gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
+ sound-name-prefix = "Speaker Amp";
+ };
+
sdio_pwrseq: sdio-pwrseq {
compatible = "mmc-pwrseq-simple";
clocks = <&rk818 1>;
@@ -737,6 +800,24 @@ ucam_out: endpoint {
};
};
};
+
+ // XXX: modem codec supplies:
+ // - vcc1v8_codec
+ // - vcca3v0_codec
+
+ // supplies: (always on currently)
+ // - vcca3v0_codec
+ // - vcca1v8_codec
+ // - vcc5v0_sys - spk_vcc
+ rt5640: rt5640@1c {
+ compatible = "realtek,rt5640";
+ reg = <0x1c>;
+ clocks = <&cru SCLK_I2S_8CH_OUT>;
+ clock-names = "mclk";
+ realtek,dmic1-data-pin = <1>;
+ realtek,in3-differential;
+ #sound-dai-cells = <0>;
+ };
};
&i2c3 {
@@ -874,6 +955,13 @@ ak09911: compass@c {
};
};
+&i2s0 {
+ rockchip,playback-channels = <2>;
+ rockchip,capture-channels = <2>;
+ pinctrl-0 = <&i2s0_2ch_bus>;
+ status = "okay";
+};
+
&io_domains {
status = "okay";
@@ -1086,6 +1174,14 @@ sound {
vcc1v8_codec_en: vcc1v8-codec-en {
rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>;
};
+
+ hp_det: hp-det {
+ rockchip,pins = <4 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ spk_en: spk-en {
+ rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
};
};

View File

@ -0,0 +1,105 @@
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
Date: Wed, 1 Dec 2021 20:48:51 +0100
Subject: arm64: dts: rk3399-pinephone-pro: Add flash and fix leds
The PinePhone Pro has a similar device to the SGM3140 used in the OG
PinePhone. This commit adds the corresponding device-tree node so the
flash/torch can work on this device.
Moreover, existing LEDs use different names and functions than what
we're used to, change them all to the same names we use on the OG
PinePhone.
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@gmail.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 47 +++++++++++++---------
1 file changed, 28 insertions(+), 19 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 4afed92..e305955 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -127,30 +127,22 @@ leds {
pinctrl-names = "default";
pinctrl-0 = <&red_led_pin &green_led_pin &blue_led_pin>;
- led-standby {
+ led-red {
color = <LED_COLOR_ID_RED>;
- default-state = "off";
- function = LED_FUNCTION_STANDBY;
+ function = LED_FUNCTION_INDICATOR;
gpios = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>;
- label = "red:standby";
- panic-indicator;
- retain-state-suspended;
};
- led-pwr {
+ led-green {
color = <LED_COLOR_ID_GREEN>;
- default-state = "on";
- function = LED_FUNCTION_POWER;
+ function = LED_FUNCTION_INDICATOR;
gpios = <&gpio4 RK_PD5 GPIO_ACTIVE_HIGH>;
- label = "green:disk-activity";
};
- blue-charging {
+ led-blue {
color = <LED_COLOR_ID_BLUE>;
- default-state = "off";
- function = LED_FUNCTION_CHARGING;
- gpios = <&gpio0 RK_PD6 GPIO_ACTIVE_HIGH>;
- label = "blue:charging";
+ function = LED_FUNCTION_INDICATOR;
+ gpios = <&gpio4 RK_PD6 GPIO_ACTIVE_HIGH>;
};
};
@@ -399,6 +391,21 @@ typec_extcon_bridge: typec-extcon {
mode-switch;
svid = /bits/ 16 <0xff01>;
};
+
+ sgm3140: led-controller {
+ compatible = "sgmicro,sgm3140";
+ vin-supply = <&vcc3v3_sys>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&flash_pins>;
+ enable-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
+ flash-gpios = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
+
+ sgm3140_flash: led {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ flash-max-timeout-us = <250000>;
+ };
+ };
};
&cpu_l0 {
@@ -1111,6 +1118,12 @@ green_led_pin: green-led-pin {
blue_led_pin: blue-led-pin {
rockchip,pins = <4 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
};
+
+ flash_pins: flash-pins {
+ rockchip,pins =
+ <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>,
+ <4 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
};
modem {
@@ -1189,10 +1202,6 @@ &pwm0 {
status = "okay";
};
-&pwm1 {
- status = "okay";
-};
-
&pwm2 {
status = "okay";
};

View File

@ -0,0 +1,48 @@
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
Date: Wed, 8 Dec 2021 23:43:08 +0100
Subject: arm64: dts: rk3399-pinephone-pro: add modem RI pin
Taht way the modem can wake the phone on incoming calls/messages.
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@gmail.com>
---
arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index e305955..ef5a58c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -160,6 +160,21 @@ power {
};
};
+ gpio-key-ri {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ri_pin>;
+
+ ring_indicator: ring-indicator {
+ label = "ring-indicator";
+ linux,can-disable;
+ linux,code = <KEY_WAKEUP>;
+ gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>;
+ wakeup-event-action = <EV_ACT_ASSERTED>;
+ wakeup-source;
+ };
+ };
+
// in1 - digital mic daughhterboard
// in2 - headset mic
// in3 - modem output (muxed with mono)
@@ -1127,6 +1142,10 @@ flash_pins: flash-pins {
};
modem {
+ ri_pin: ri-pin {
+ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
vcc_4g_5v_en: vcc-4g-5v-en-pin {
rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
};

View File

@ -0,0 +1,90 @@
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
Date: Thu, 9 Dec 2021 16:52:29 +0100
Subject: arm64: dts: rk3399-pinephone-pro: improve sound device definition
This commit renames the sound card and the "Headphone" widget so they
match the names used by the ALSA UCM profiles.
It also adds a jack detection GPIO to the sound card definition, and
creates a new set of ADC keys for handling headset buttons.
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@gmail.com>
---
.../boot/dts/rockchip/rk3399-pinephone-pro.dts | 41 ++++++++++++++++++----
1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index ef5a58c..e46f36f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -48,6 +48,32 @@ button-down {
};
};
+ headset-keys {
+ compatible = "adc-keys";
+ io-channels = <&saradc 2>;
+ io-channel-names = "buttons";
+ keyup-threshold-microvolt = <900000>;
+ poll-interval = <100>;
+
+ headset-play {
+ label = "Play";
+ linux,code = <KEY_PLAYPAUSE>;
+ press-threshold-microvolt = <650000>;
+ };
+
+ headset-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ press-threshold-microvolt = <750000>;
+ };
+
+ headset-down {
+ label = "Volume Down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ press-threshold-microvolt = <850000>;
+ };
+ };
+
bat: battery {
compatible = "simple-battery";
voltage-min-design-microvolt = <3400000>;
@@ -184,29 +210,30 @@ ring_indicator: ring-indicator {
// spaker - amp enabled by SPK_CTL_H
//
// mclk - GPIO4_A0/I2S_CLK
- //
- // some gpio-jack-detection driver?
- //pinctrl-0 = <&hp_det>; // GPIO4_D4
rt5640-sound {
compatible = "simple-audio-card";
- simple-audio-card,name = "rockchip,rt5640-codec";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_det>;
+ simple-audio-card,name = "PinePhonePro";
simple-audio-card,aux-devs = <&speaker_amp>;
simple-audio-card,format = "i2s";
simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,hp-det-gpio = <&gpio4 RK_PD4 GPIO_ACTIVE_LOW>;
+ simple-audio-card,pin-switches = "Internal Speaker";
simple-audio-card,widgets =
"Microphone", "Headset Microphone",
"Microphone", "Internal Microphone",
- "Headphone", "Headphone Jack",
+ "Headphone", "Headphones",
"Speaker", "Internal Earpiece",
"Speaker", "Internal Speaker",
"Line", "Line In Modem",
"Line", "Line Out Modem";
simple-audio-card,routing =
- "Headphone Jack", "HPOL",
- "Headphone Jack", "HPOR",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
"Internal Earpiece", "SPOLP",
"Internal Earpiece", "SPOLN",
"Internal Speaker", "Speaker Amp OUTL",

View File

@ -1,12 +0,0 @@
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 03b83aa91277..dfc6c7d1b0e7 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -4070,6 +4070,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
}
if (!info) {
bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
+ if (ver_rom & ~0xffffU) return 0;
return -ENODEV;
}

View File

@ -1,49 +0,0 @@
From cb408fb65a08bd45543724c1e9b8f38ae1bebc4a Mon Sep 17 00:00:00 2001
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
Date: Tue, 4 Aug 2020 15:12:59 +0200
Subject: [PATCH 177/183] leds-gpio: make max_brightness configurable
---
drivers/leds/leds-gpio.c | 4 ++++
include/linux/leds.h | 3 ++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 93f5b1b60fde..f8483fab1164 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -108,6 +108,8 @@ static int create_gpio_led(const struct gpio_led *template,
if (ret < 0)
return ret;
+ led_dat->cdev.max_brightness = template->max_brightness;
+
if (template->name) {
led_dat->cdev.name = template->name;
ret = devm_led_classdev_register(parent, &led_dat->cdev);
@@ -177,6 +179,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1;
+ fwnode_property_read_u32(child, "max-brightness", &led.max_brightness);
+
ret = create_gpio_led(&led, led_dat, dev, child, NULL);
if (ret < 0) {
fwnode_handle_put(child);
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 6a8d6409c993..99a80092114d 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -513,7 +513,8 @@ typedef int (*gpio_blink_set_t)(struct gpio_desc *desc, int state,
struct gpio_led {
const char *name;
const char *default_trigger;
- unsigned gpio;
+ unsigned gpio;
+ unsigned max_brightness;
unsigned active_low : 1;
unsigned retain_state_suspended : 1;
unsigned panic_indicator : 1;
--
2.30.0

View File

@ -1,25 +0,0 @@
From 2253c0d31cf17debb97db418bec21ad59cd47c14 Mon Sep 17 00:00:00 2001
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
Date: Tue, 3 Nov 2020 17:04:35 +0100
Subject: [PATCH 178/183] sun8i-codec: fix headphone jack pin name
---
sound/soc/sunxi/sun8i-codec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c
index 6128d861df90..ab751fd7c426 100644
--- a/sound/soc/sunxi/sun8i-codec.c
+++ b/sound/soc/sunxi/sun8i-codec.c
@@ -1272,7 +1272,7 @@ static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = {
static struct snd_soc_jack_pin sun8i_codec_jack_pins[] = {
{
- .pin = "Headphone Jack",
+ .pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
},
{
--
2.30.0

View File

@ -1,130 +0,0 @@
From 465a75a727ae5eb4c94859bfac4742cb14e38b3e Mon Sep 17 00:00:00 2001
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
Date: Fri, 3 Apr 2020 17:13:55 +0200
Subject: [PATCH 179/183] arm64: dts: allwinner: pinephone: improve device tree
On PinePhone, the headset mic bias resistor isn't populated on the
schematics (R811), therefore we need to enable the codec's internal
resistor. Additionnally, the jack detection IRQ's are inverted due to the
connector wiring, so the necessary property is added to the codec node
to made the driver aware of this fact.
We also stop LEDs during suspend to improve battery life, lower
cpu_alert* temperatures so the phone doesn't get too hot and improve the
backlight brightness values so we have a wider usable range.
Finally, the RGB LED max_brightness is set to 1 as it isn't using a PWM
output.
---
.../dts/allwinner/sun50i-a64-pinephone-1.1.dts | 10 +++++-----
.../dts/allwinner/sun50i-a64-pinephone-1.2.dts | 13 ++++++-------
.../dts/allwinner/sun50i-a64-pinephone.dtsi | 18 +++++++++++++-----
3 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
index f084c4f21f12..573f1929da4f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
@@ -29,11 +29,11 @@ &backlight {
* value here was chosen as a safe default.
*/
brightness-levels = <
- 774 793 814 842
- 882 935 1003 1088
- 1192 1316 1462 1633
- 1830 2054 2309 2596
- 2916 3271 3664 4096>;
+ 392 413 436 468
+ 512 571 647 742
+ 857 995 1159 1349
+ 1568 1819 2103 2423
+ 2779 3176 3614 4096>;
num-interpolated-steps = <50>;
default-brightness-level = <400>;
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
index bbf64677c22b..6c3922543fec 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
@@ -34,14 +34,13 @@ &backlight {
* chosen as a safe default.
*/
brightness-levels = <
- 5000 5248 5506 5858 6345
- 6987 7805 8823 10062 11543
- 13287 15317 17654 20319 23336
- 26724 30505 34702 39335 44427
- 50000
- >;
+ 392 413 436 468
+ 512 571 647 742
+ 857 995 1159 1349
+ 1568 1819 2103 2423
+ 2779 3176 3614 4096>;
num-interpolated-steps = <50>;
- default-brightness-level = <500>;
+ default-brightness-level = <400>;
};
&lis3mdl {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
index c55709197804..441358592072 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
@@ -219,21 +219,21 @@
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_BLUE>;
gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
- retain-state-suspended;
+ max-brightness = <1>;
};
led-1 {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_GREEN>;
gpios = <&pio 3 18 GPIO_ACTIVE_HIGH>; /* PD18 */
- retain-state-suspended;
+ max-brightness = <1>;
};
led-2 {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_RED>;
gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
- retain-state-suspended;
+ max-brightness = <1>;
};
};
@@ -380,6 +380,14 @@
cpu-supply = <&reg_dcdc2>;
};
+&cpu_alert0 {
+ temperature = <60000>;
+};
+
+&cpu_alert1 {
+ temperature = <80000>;
+};
+
&csi {
pinctrl-0 = <&csi_pins>, <&csi_mclk_pin>;
status = "okay";
@@ -816,11 +824,11 @@
simple-audio-card,aux-devs = <&codec_analog>, <&speaker_amp>;
simple-audio-card,widgets = "Microphone", "Headset Microphone",
"Microphone", "Internal Microphone",
- "Headphone", "Headphone Jack",
+ "Headphone", "Headphone",
"Speaker", "Internal Earpiece",
"Speaker", "Internal Speaker";
simple-audio-card,routing =
- "Headphone Jack", "HP",
+ "Headphone", "HP",
"Internal Earpiece", "EARPIECE",
"Internal Speaker", "Speaker Amp OUTL",
"Internal Speaker", "Speaker Amp OUTR",
--
2.30.0

View File

@ -1,116 +0,0 @@
From 465a75a727ae5eb4c94859bfac4742cb14e38b3e Mon Sep 17 00:00:00 2001
From: Arnaud Ferraris <arnaud.ferraris@collabora.com>
Date: Fri, 3 Apr 2020 17:13:55 +0200
Subject: [PATCH 179/183] arm64: dts: allwinner: pinephone: improve device tree
On PinePhone, the headset mic bias resistor isn't populated on the
schematics (R811), therefore we need to enable the codec's internal
resistor. Additionnally, the jack detection IRQ's are inverted due to the
connector wiring, so the necessary property is added to the codec node
to made the driver aware of this fact.
We also stop LEDs during suspend to improve battery life, lower
cpu_alert* temperatures so the phone doesn't get too hot and improve the
backlight brightness values so we have a wider usable range.
Finally, the RGB LED max_brightness is set to 1 as it isn't using a PWM
output.
---
.../dts/allwinner/sun50i-a64-pinephone-1.1.dts | 10 +++++-----
.../dts/allwinner/sun50i-a64-pinephone-1.2.dts | 13 ++++++-------
.../dts/allwinner/sun50i-a64-pinephone.dtsi | 18 +++++++++++++-----
3 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
index f084c4f21f12..573f1929da4f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
@@ -29,11 +29,11 @@ &backlight {
* value here was chosen as a safe default.
*/
brightness-levels = <
- 774 793 814 842
- 882 935 1003 1088
- 1192 1316 1462 1633
- 1830 2054 2309 2596
- 2916 3271 3664 4096>;
+ 392 413 436 468
+ 512 571 647 742
+ 857 995 1159 1349
+ 1568 1819 2103 2423
+ 2779 3176 3614 4096>;
num-interpolated-steps = <50>;
default-brightness-level = <400>;
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
index bbf64677c22b..6c3922543fec 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
@@ -34,14 +34,13 @@ &backlight {
* chosen as a safe default.
*/
brightness-levels = <
- 5000 5248 5506 5858 6345
- 6987 7805 8823 10062 11543
- 13287 15317 17654 20319 23336
- 26724 30505 34702 39335 44427
- 50000
- >;
+ 392 413 436 468
+ 512 571 647 742
+ 857 995 1159 1349
+ 1568 1819 2103 2423
+ 2779 3176 3614 4096>;
num-interpolated-steps = <50>;
- default-brightness-level = <500>;
+ default-brightness-level = <400>;
};
&lis3mdl {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
index c55709197804..441358592072 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
@@ -219,21 +219,21 @@
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_BLUE>;
gpios = <&pio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */
- retain-state-suspended;
+ max-brightness = <1>;
};
led-1 {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_GREEN>;
gpios = <&pio 3 18 GPIO_ACTIVE_HIGH>; /* PD18 */
- retain-state-suspended;
+ max-brightness = <1>;
};
led-2 {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_RED>;
gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */
- retain-state-suspended;
+ max-brightness = <1>;
};
};
@@ -380,6 +380,14 @@
cpu-supply = <&reg_dcdc2>;
};
+&cpu_alert0 {
+ temperature = <60000>;
+};
+
+&cpu_alert1 {
+ temperature = <80000>;
+};
+
&csi {
pinctrl-0 = <&csi_pins>, <&csi_mclk_pin>;
status = "okay";
--
2.30.0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,512 +0,0 @@
diff --git a/Makefile b/Makefile
index ed6e7ec60eff6..ffcc7eadc44b8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 15
-SUBLEVEL = 0
+SUBLEVEL = 1
EXTRAVERSION =
NAME = Trick or Treat
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 962041148482c..6c0f7f4f7d1de 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -377,9 +377,6 @@ static int amba_device_try_add(struct amba_device *dev, struct resource *parent)
void __iomem *tmp;
int i, ret;
- WARN_ON(dev->irq[0] == (unsigned int)-1);
- WARN_ON(dev->irq[1] == (unsigned int)-1);
-
ret = request_resource(parent, &dev->res);
if (ret)
goto err_out;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 269437b013280..289c7dc053634 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1078,8 +1078,6 @@ struct amdgpu_device {
char product_name[32];
char serial[20];
- struct amdgpu_autodump autodump;
-
atomic_t throttling_logging_enabled;
struct ratelimit_state throttling_logging_rs;
uint32_t ras_hw_enabled;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 463b9c0283f7e..ec30d81586a79 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -27,7 +27,6 @@
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <linux/pm_runtime.h>
-#include <linux/poll.h>
#include "amdgpu.h"
#include "amdgpu_pm.h"
@@ -37,85 +36,7 @@
#include "amdgpu_securedisplay.h"
#include "amdgpu_fw_attestation.h"
-int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev)
-{
#if defined(CONFIG_DEBUG_FS)
- unsigned long timeout = 600 * HZ;
- int ret;
-
- wake_up_interruptible(&adev->autodump.gpu_hang);
-
- ret = wait_for_completion_interruptible_timeout(&adev->autodump.dumping, timeout);
- if (ret == 0) {
- pr_err("autodump: timeout, move on to gpu recovery\n");
- return -ETIMEDOUT;
- }
-#endif
- return 0;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file)
-{
- struct amdgpu_device *adev = inode->i_private;
- int ret;
-
- file->private_data = adev;
-
- ret = down_read_killable(&adev->reset_sem);
- if (ret)
- return ret;
-
- if (adev->autodump.dumping.done) {
- reinit_completion(&adev->autodump.dumping);
- ret = 0;
- } else {
- ret = -EBUSY;
- }
-
- up_read(&adev->reset_sem);
-
- return ret;
-}
-
-static int amdgpu_debugfs_autodump_release(struct inode *inode, struct file *file)
-{
- struct amdgpu_device *adev = file->private_data;
-
- complete_all(&adev->autodump.dumping);
- return 0;
-}
-
-static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_table_struct *poll_table)
-{
- struct amdgpu_device *adev = file->private_data;
-
- poll_wait(file, &adev->autodump.gpu_hang, poll_table);
-
- if (amdgpu_in_reset(adev))
- return POLLIN | POLLRDNORM | POLLWRNORM;
-
- return 0;
-}
-
-static const struct file_operations autodump_debug_fops = {
- .owner = THIS_MODULE,
- .open = amdgpu_debugfs_autodump_open,
- .poll = amdgpu_debugfs_autodump_poll,
- .release = amdgpu_debugfs_autodump_release,
-};
-
-static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev)
-{
- init_completion(&adev->autodump.dumping);
- complete_all(&adev->autodump.dumping);
- init_waitqueue_head(&adev->autodump.gpu_hang);
-
- debugfs_create_file("amdgpu_autodump", 0600,
- adev_to_drm(adev)->primary->debugfs_root,
- adev, &autodump_debug_fops);
-}
/**
* amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes
@@ -1588,7 +1509,6 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
}
amdgpu_ras_debugfs_create_all(adev);
- amdgpu_debugfs_autodump_init(adev);
amdgpu_rap_debugfs_init(adev);
amdgpu_securedisplay_debugfs_init(adev);
amdgpu_fw_attestation_debugfs_init(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h
index 141a8474e24f2..8b641f40fdf66 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h
@@ -26,10 +26,6 @@
/*
* Debugfs
*/
-struct amdgpu_autodump {
- struct completion dumping;
- struct wait_queue_head gpu_hang;
-};
int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
int amdgpu_debugfs_init(struct amdgpu_device *adev);
@@ -37,4 +33,3 @@ void amdgpu_debugfs_fini(struct amdgpu_device *adev);
void amdgpu_debugfs_fence_init(struct amdgpu_device *adev);
void amdgpu_debugfs_firmware_init(struct amdgpu_device *adev);
void amdgpu_debugfs_gem_init(struct amdgpu_device *adev);
-int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index af9bdf16eefd4..b8d9004fb1635 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -2432,10 +2432,6 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
if (!adev->gmc.xgmi.pending_reset)
amdgpu_amdkfd_device_init(adev);
- r = amdgpu_amdkfd_resume_iommu(adev);
- if (r)
- goto init_failed;
-
amdgpu_fru_get_product_info(adev);
init_failed:
@@ -4466,10 +4462,6 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
if (reset_context->reset_req_dev == adev)
job = reset_context->job;
- /* no need to dump if device is not in good state during probe period */
- if (!adev->gmc.xgmi.pending_reset)
- amdgpu_debugfs_wait_dump(adev);
-
if (amdgpu_sriov_vf(adev)) {
/* stop the data exchange thread */
amdgpu_virt_fini_data_exchange(adev);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 4a416231b24c8..a6afacc3b10cd 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -924,6 +924,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
svm_migrate_init((struct amdgpu_device *)kfd->kgd);
+ if(kgd2kfd_resume_iommu(kfd))
+ goto device_iommu_error;
+
if (kfd_resume(kfd))
goto kfd_resume_error;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 8080bba5b7a76..de9ec5ddb6c72 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -247,6 +247,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
{
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
struct dc_link *link = connector->dc_link;
+ struct dc *dc = (struct dc *)link->dc;
struct dc_link_settings prefer_link_settings;
char *wr_buf = NULL;
const uint32_t wr_buf_size = 40;
@@ -313,7 +314,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
prefer_link_settings.lane_count = param[0];
prefer_link_settings.link_rate = param[1];
- dp_retrain_link_dp_test(link, &prefer_link_settings, false);
+ dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true);
kfree(wr_buf);
return size;
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index de5f9c86b9a44..cafb0608ffb46 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -2140,10 +2140,6 @@ static void __execlists_unhold(struct i915_request *rq)
if (p->flags & I915_DEPENDENCY_WEAK)
continue;
- /* Propagate any change in error status */
- if (rq->fence.error)
- i915_request_set_error_once(w, rq->fence.error);
-
if (w->engine != rq->engine)
continue;
diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c
index 2bf9467b917d1..71991f8638e6b 100644
--- a/drivers/media/firewire/firedtv-avc.c
+++ b/drivers/media/firewire/firedtv-avc.c
@@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
read_pos += program_info_length;
write_pos += program_info_length;
}
- while (read_pos < length) {
+ while (read_pos + 4 < length) {
+ if (write_pos + 4 >= sizeof(c->operand) - 4) {
+ ret = -EINVAL;
+ goto out;
+ }
c->operand[write_pos++] = msg[read_pos++];
c->operand[write_pos++] = msg[read_pos++];
c->operand[write_pos++] = msg[read_pos++];
@@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
c->operand[write_pos++] = es_info_length >> 8;
c->operand[write_pos++] = es_info_length & 0xff;
if (es_info_length > 0) {
+ if (read_pos >= length) {
+ ret = -EINVAL;
+ goto out;
+ }
pmt_cmd_id = msg[read_pos++];
if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",
pmt_cmd_id);
- if (es_info_length > sizeof(c->operand) - 4 -
- write_pos) {
+ if (es_info_length > sizeof(c->operand) - 4 - write_pos ||
+ es_info_length > length - read_pos) {
ret = -EINVAL;
goto out;
}
diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c
index 9363d005e2b61..e0d57e09dab0c 100644
--- a/drivers/media/firewire/firedtv-ci.c
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
} else {
data_length = msg->msg[3];
}
+ if (data_length > sizeof(msg->msg) - data_pos)
+ return -EINVAL;
return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
}
diff --git a/drivers/net/ethernet/sfc/ethtool_common.c b/drivers/net/ethernet/sfc/ethtool_common.c
index bf1443539a1a4..bd552c7dffcb1 100644
--- a/drivers/net/ethernet/sfc/ethtool_common.c
+++ b/drivers/net/ethernet/sfc/ethtool_common.c
@@ -563,20 +563,14 @@ int efx_ethtool_get_link_ksettings(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_link_state *link_state = &efx->link_state;
- u32 supported;
mutex_lock(&efx->mac_lock);
efx_mcdi_phy_get_link_ksettings(efx, cmd);
mutex_unlock(&efx->mac_lock);
/* Both MACs support pause frames (bidirectional and respond-only) */
- ethtool_convert_link_mode_to_legacy_u32(&supported,
- cmd->link_modes.supported);
-
- supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
-
- ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
- supported);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
+ ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
if (LOOPBACK_INTERNAL(efx)) {
cmd->base.speed = link_state->speed;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index ec913ec991f3f..6e91bdb2e08d4 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -604,15 +604,6 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
}
}
- /* FIXME: Only enable bmps support when encryption is enabled.
- * For any reasons, when connected to open/no-security BSS,
- * the wcn36xx controller in bmps mode does not forward
- * 'wake-up' beacons despite AP sends DTIM with station AID.
- * It could be due to a firmware issue or to the way driver
- * configure the station.
- */
- if (vif->type == NL80211_IFTYPE_STATION)
- vif_priv->allow_bmps = true;
break;
case DISABLE_KEY:
if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
@@ -913,7 +904,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
vif->addr,
bss_conf->aid);
vif_priv->sta_assoc = false;
- vif_priv->allow_bmps = false;
wcn36xx_smd_set_link_st(wcn,
bss_conf->bssid,
vif->addr,
diff --git a/drivers/net/wireless/ath/wcn36xx/pmc.c b/drivers/net/wireless/ath/wcn36xx/pmc.c
index 2d0780fefd477..2936aaf532738 100644
--- a/drivers/net/wireless/ath/wcn36xx/pmc.c
+++ b/drivers/net/wireless/ath/wcn36xx/pmc.c
@@ -23,10 +23,7 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
{
int ret = 0;
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-
- if (!vif_priv->allow_bmps)
- return -ENOTSUPP;
-
+ /* TODO: Make sure the TX chain clean */
ret = wcn36xx_smd_enter_bmps(wcn, vif);
if (!ret) {
wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n");
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index add6e527e8330..e9560f35e9bcf 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -128,7 +128,6 @@ struct wcn36xx_vif {
enum wcn36xx_hal_bss_type bss_type;
/* Power management */
- bool allow_bmps;
enum wcn36xx_power_state pw_state;
u8 bss_index;
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 34a9ac1f2b9b1..8b7a01773aec2 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -244,6 +244,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
goto out_regulator_disable;
}
+ reset_control_assert(domain->reset);
+
if (domain->bits.pxx) {
/* request the domain to power up */
regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ,
@@ -266,8 +268,6 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
GPC_PGC_CTRL_PCR);
}
- reset_control_assert(domain->reset);
-
/* delay for reset to propagate */
udelay(5);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 7ee6e4cc0d89e..00d35fe1fef0b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2795,7 +2795,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
{
int retval;
struct usb_device *rhdev;
- struct usb_hcd *shared_hcd;
if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
@@ -2956,26 +2955,13 @@ int usb_add_hcd(struct usb_hcd *hcd,
goto err_hcd_driver_start;
}
- /* starting here, usbcore will pay attention to the shared HCD roothub */
- shared_hcd = hcd->shared_hcd;
- if (!usb_hcd_is_primary_hcd(hcd) && shared_hcd && HCD_DEFER_RH_REGISTER(shared_hcd)) {
- retval = register_root_hub(shared_hcd);
- if (retval != 0)
- goto err_register_root_hub;
-
- if (shared_hcd->uses_new_polling && HCD_POLL_RH(shared_hcd))
- usb_hcd_poll_rh_status(shared_hcd);
- }
-
/* starting here, usbcore will pay attention to this root hub */
- if (!HCD_DEFER_RH_REGISTER(hcd)) {
- retval = register_root_hub(hcd);
- if (retval != 0)
- goto err_register_root_hub;
+ retval = register_root_hub(hcd);
+ if (retval != 0)
+ goto err_register_root_hub;
- if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
- usb_hcd_poll_rh_status(hcd);
- }
+ if (hcd->uses_new_polling && HCD_POLL_RH(hcd))
+ usb_hcd_poll_rh_status(hcd);
return retval;
@@ -3013,7 +2999,6 @@ EXPORT_SYMBOL_GPL(usb_add_hcd);
void usb_remove_hcd(struct usb_hcd *hcd)
{
struct usb_device *rhdev = hcd->self.root_hub;
- bool rh_registered;
dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
@@ -3024,7 +3009,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
spin_lock_irq (&hcd_root_hub_lock);
- rh_registered = hcd->rh_registered;
hcd->rh_registered = 0;
spin_unlock_irq (&hcd_root_hub_lock);
@@ -3034,8 +3018,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
cancel_work_sync(&hcd->died_work);
mutex_lock(&usb_bus_idr_lock);
- if (rh_registered)
- usb_disconnect(&rhdev); /* Sets rhdev to NULL */
+ usb_disconnect(&rhdev); /* Sets rhdev to NULL */
mutex_unlock(&usb_bus_idr_lock);
/*
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 541fe4dcc43a2..902f410874e8e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -692,7 +692,6 @@ int xhci_run(struct usb_hcd *hcd)
if (ret)
xhci_free_command(xhci, command);
}
- set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Finished xhci_run for USB2 roothub");
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 2c1fc9212cf28..548a028f2dabb 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -124,7 +124,6 @@ struct usb_hcd {
#define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */
#define HCD_FLAG_DEAD 6 /* controller has died? */
#define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */
-#define HCD_FLAG_DEFER_RH_REGISTER 8 /* Defer roothub registration */
/* The flags can be tested using these macros; they are likely to
* be slightly faster than test_bit().
@@ -135,7 +134,6 @@ struct usb_hcd {
#define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
#define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
#define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD))
-#define HCD_DEFER_RH_REGISTER(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEFER_RH_REGISTER))
/*
* Specifies if interfaces are authorized by default
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 8929d9abe8aa8..74e5bd2cc9329 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1887,6 +1887,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
QUIRK_FLAG_GET_SAMPLE_RATE),
+ DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
+ QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */

View File

@ -1,11 +0,0 @@
[Trigger]
Type = File
Operation = Install
Operation = Upgrade
Target = boot/Image
Target = usr/lib/initcpio/*
[Action]
Description = Updating %PKGBASE% initcpios...
When = PostTransaction
Exec = /usr/bin/mkinitcpio -p %PKGBASE%

View File

@ -1,118 +0,0 @@
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <linux-kernel-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
X-Spam-Level:
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,
MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
autolearn_force=no version=3.4.0
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
by smtp.lore.kernel.org (Postfix) with ESMTP id 30CB3C433DB
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by mail.kernel.org (Postfix) with ESMTP id F053961971
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:06 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S230259AbhC0NGA (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
Sat, 27 Mar 2021 09:06:00 -0400
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59650 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S229582AbhC0NFz (ORCPT
<rfc822;linux-kernel@vger.kernel.org>);
Sat, 27 Mar 2021 09:05:55 -0400
Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DAA2C0613B1
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:05:55 -0700 (PDT)
Received: by mail-pf1-x435.google.com with SMTP id j25so6773824pfe.2
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:05:55 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20161025;
h=from:to:cc:subject:date:message-id:mime-version
:content-transfer-encoding;
bh=j1vEagJw59z7NUkgTmJto/iZqe4yWAoKFE4cIPL6KSA=;
b=W++BsAIwl+3ucDDq6J9gfd2LQIPwdj2biEakUpnxpy/YsK+3iCoF33X3sftQWOxfP7
IPnjeO9Rde2kHHrwJMlMu2vkeccABUo1mLD6uTVGrEfxwUsN9YJWo9jUzaSY3cyvbGI2
ehpcqqnKgU3Fn5s/X8mIRCamioqbkc4WM23kxCZTaHn+XhPN+SWL6FLKRXDgGS2ivbn1
OER7kHG7/pVx6TS91PpzwDFvN3Rnt6x9672uUa2Evpoapzy9P2POwsDV4zxWpGjlEc44
x99r44072+JXwATmacsPj8yOAksyAgxYYzYtUqJdpS51qpCmDWMBwE12Glc6HXWJKDrZ
V2jw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version
:content-transfer-encoding;
bh=j1vEagJw59z7NUkgTmJto/iZqe4yWAoKFE4cIPL6KSA=;
b=kBUfAu8SPEqgcOJWgnRXoXkAISBVy5hrC8mdP43B3bJdOtUy3ckGem52OQlxU4JiZ9
fRLzgQhtoaEPJwBegty5xhiBi7a9Z8jtP5y9BGPLtHnPY0vj7Q5WoLeJW8VQSdnTfIea
LWI0QFW1FPejnWt1OkpKrg23YuIwnAy4JeS4ppYqwxoJLaA2CK49uIgHZvkO/KUWTZ1u
H4FTpR1COt4JDajdNEO9PXbgAIn7Zhc84m4BrHeFhPPMguGgiORNl8CiVYnEidYMOYB4
xKZysxTMak3CltRje+eBSpYQa9T1mcAv1kMsc7OY2YJYnK7TadU5FcwBnEGYEGtI6pK9
kbyg==
X-Gm-Message-State: AOAM531ZZkAzAjwe4lLioYqlb3vcaxOF8kBIHnAElR+v7R84d5htjzCI
w2CjFLBp7ZYpGnOW93HhwfMMXbvyGk6rb63y
X-Google-Smtp-Source: ABdhPJwtfu5Tfa4UYXfW8whmzPPLMc8XbemaxfI6PdBR3nuuwqL4rugT9FibIaSdi/j6K0J4cIJCqg==
X-Received: by 2002:a63:e906:: with SMTP id i6mr16394983pgh.132.1616850352891;
Sat, 27 Mar 2021 06:05:52 -0700 (PDT)
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.05.51
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Sat, 27 Mar 2021 06:05:52 -0700 (PDT)
From: John Chen <johnchen902@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
John Chen <johnchen902@gmail.com>
Subject: [PATCH 0/4] HID: add Apple Magic Mouse 2 support
Date: Sat, 27 Mar 2021 21:05:04 +0800
Message-Id: <20210327130508.24849-1-johnchen902@gmail.com>
X-Mailer: git-send-email 2.31.0
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-1-johnchen902@gmail.com/>
List-Archive: <https://lore.kernel.org/lkml/>
List-Post: <mailto:linux-kernel@vger.kernel.org>
The HID descriptor of Magic Mouse 2 contains BTN_LEFT, BTN_RIGHT, REL_X,
REL_Y, whether it's charging, whether it's fully charged, and battery
capacity.
$ xxd -p report_descriptor
05010902a101851205091901290215002501950275018102950175068103
05010901a1001601f826ff073601fb46ff046513550d0930093175109502
8106750895028101c00602ff09558555150026ff0075089540b1a2c00600
ff0914a10185900584750195031500250109610585094409468102950581
0175089501150026ff0009658102c000
As hidinput can handle the BTNs and RELs, the Magic Mouse 2 already
functions as a basic mouse. Nevertheless, It should be reasonable to
extend hid-magicmouse to support Magic Mouse 2 as well. Furthermore,
hidinput is patched to handle the battery capacity.
This work is based on Recardo's, which is in turned based on Rohitpid's.
Their GitHub repositories are linked below:
https://github.com/RicardoEPRodrigues/magicmouse-hid
https://github.com/rohitpid/Linux-Magic-Trackpad-2-Driver
John Chen (4):
HID: magicmouse: add Apple Magic Mouse 2 support
HID: magicmouse: fix 3 button emulation of Mouse 2
HID: magicmouse: fix reconnection of Magic Mouse 2
HID: input: map battery capacity (00850065)
drivers/hid/hid-debug.c | 1 +
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-input.c | 11 +++
drivers/hid/hid-magicmouse.c | 156 ++++++++++++++++++++++++++++-------
include/linux/hid.h | 3 +
5 files changed, 140 insertions(+), 32 deletions(-)
--
2.31.0

View File

@ -1,247 +0,0 @@
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <linux-kernel-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
X-Spam-Level:
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
autolearn_force=no version=3.4.0
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
by smtp.lore.kernel.org (Postfix) with ESMTP id 4888EC433C1
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by mail.kernel.org (Postfix) with ESMTP id 0E6E861981
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S230295AbhC0NGh (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
Sat, 27 Mar 2021 09:06:37 -0400
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59740 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S229582AbhC0NGT (ORCPT
<rfc822;linux-kernel@vger.kernel.org>);
Sat, 27 Mar 2021 09:06:19 -0400
Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 82262C0613B1
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:19 -0700 (PDT)
Received: by mail-pg1-x529.google.com with SMTP id v10so6405578pgs.12
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:19 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20161025;
h=from:to:cc:subject:date:message-id:in-reply-to:references
:mime-version:content-transfer-encoding;
bh=/43es5lmfTvSMg9V9lh/7OQVghMj1iNxFqwqD88gyCk=;
b=JA8+yZao+x/DmyoiRUpwr0wP9XgaNgDVez40dXm+yEd6Wlgs1dQvO3DkU8n7trJWcL
TCj7NqBp0z4pf3pSHrTxX7rWZX4yRyZJAXo7fqTPqfN2R0PkRIp5gnvcDv+7/BRM4nqx
3pI6ubgKZ+rxYph8XNAuO94/oOjxgItIhOqYGbLPHwa2eoI60mUbrF/ukBsw8OwQ+Vli
0siGyaoTCPP/h+9uuHJqQJ1yw6CCkCAxMwZXD79abtLytL6WkhuvoFJ6exRYGHawcHMs
bel32ifzIlv+7ULbcTI2uVNhxvdrD51tRSNrAZ77n+Tk8RivXMeSqSzPVngWZCs0uk6s
JryA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
:references:mime-version:content-transfer-encoding;
bh=/43es5lmfTvSMg9V9lh/7OQVghMj1iNxFqwqD88gyCk=;
b=fAhjI90TZfQpcQBqM4rN69d8uN92OH3j+lhm/dYYlmqdchK6ZZsPD3wt6VW8/ObU+0
BpTic3inOmn0aVasSmAkbNxaVAUJ339klb/WnO9RfaemBLXDCBMgGjVr+ofhpIbfKxiZ
0aBswW4Dc2uY39zmxm7wtJ2sRHHwj/Ltdt7B+NYes7Kzohvfg98YLvm8I5mloimR02U9
HRlPKK2YbMcZ5i2Y8Q3faX8356caUUU7l91utK4EXdrVFCbNftXBEmRej6gXSZudCBga
7w6Rgymaox0hfMZzYLWtJJp2fo3BcKA4+TD6bJ1yrxIdPmK59QMGoyMUIKqTIZIjN2c/
gvpg==
X-Gm-Message-State: AOAM531lA6V8bOmQPsuLmZx3iv59gcixbI4HEH5eqWzOJ/N3DRaX/hb9
NavPhvckezEkR22O7uWWvZAUxOplQlRwSsX5
X-Google-Smtp-Source: ABdhPJyaSIYZWu4pp8j7TnxkxYd0BP77HzgDaIZFIDeoL910Tkv+L4VuoQLEw0GNu+5Zxi80enV/YQ==
X-Received: by 2002:a65:498b:: with SMTP id r11mr16491362pgs.364.1616850378733;
Sat, 27 Mar 2021 06:06:18 -0700 (PDT)
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.17
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Sat, 27 Mar 2021 06:06:18 -0700 (PDT)
From: John Chen <johnchen902@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
John Chen <johnchen902@gmail.com>
Subject: [PATCH 1/4] HID: magicmouse: add Apple Magic Mouse 2 support
Date: Sat, 27 Mar 2021 21:05:05 +0800
Message-Id: <20210327130508.24849-2-johnchen902@gmail.com>
X-Mailer: git-send-email 2.31.0
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
References: <20210327130508.24849-1-johnchen902@gmail.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-2-johnchen902@gmail.com/>
List-Archive: <https://lore.kernel.org/lkml/>
List-Post: <mailto:linux-kernel@vger.kernel.org>
Bluetooth device
Vendor 004c (Apple)
Device 0269 (Magic Mouse 2)
Add support for Apple Magic Mouse 2, putting the device in multi-touch
mode.
Co-authored-by: Rohit Pidaparthi <rohitpid@gmail.com>
Co-authored-by: RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>
Signed-off-by: John Chen <johnchen902@gmail.com>
---
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-magicmouse.c | 53 ++++++++++++++++++++++++++++++++----
2 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index e42aaae3138f..fa0edf03570a 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -93,6 +93,7 @@
#define BT_VENDOR_ID_APPLE 0x004c
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
+#define USB_DEVICE_ID_APPLE_MAGICMOUSE2 0x0269
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index abd86903875f..7aad6ca56780 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -54,6 +54,7 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
#define TRACKPAD2_USB_REPORT_ID 0x02
#define TRACKPAD2_BT_REPORT_ID 0x31
#define MOUSE_REPORT_ID 0x29
+#define MOUSE2_REPORT_ID 0x12
#define DOUBLE_REPORT_ID 0xf7
/* These definitions are not precise, but they're close enough. (Bits
* 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
@@ -195,7 +196,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
int id, x, y, size, orientation, touch_major, touch_minor, state, down;
int pressure = 0;
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf;
x = (tdata[1] << 28 | tdata[0] << 20) >> 20;
y = -((tdata[2] << 24 | tdata[1] << 16) >> 20);
@@ -296,7 +298,8 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
input_report_abs(input, ABS_MT_PRESSURE, pressure);
if (report_undeciphered) {
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2)
input_event(input, EV_MSC, MSC_RAW, tdata[7]);
else if (input->id.product !=
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2)
@@ -380,6 +383,34 @@ static int magicmouse_raw_event(struct hid_device *hdev,
* ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
*/
break;
+ case MOUSE2_REPORT_ID:
+ /* Size is either 8 or (14 + 8 * N) */
+ if (size != 8 && (size < 14 || (size - 14) % 8 != 0))
+ return 0;
+ npoints = (size - 14) / 8;
+ if (npoints > 15) {
+ hid_warn(hdev, "invalid size value (%d) for MOUSE2_REPORT_ID\n",
+ size);
+ return 0;
+ }
+ msc->ntouches = 0;
+ for (ii = 0; ii < npoints; ii++)
+ magicmouse_emit_touch(msc, ii, data + ii * 8 + 14);
+
+ /* When emulating three-button mode, it is important
+ * to have the current touch information before
+ * generating a click event.
+ */
+ x = (int)((data[3] << 24) | (data[2] << 16)) >> 16;
+ y = (int)((data[5] << 24) | (data[4] << 16)) >> 16;
+ clicks = data[1];
+
+ /* The following bits provide a device specific timestamp. They
+ * are unused here.
+ *
+ * ts = data[11] >> 6 | data[12] << 2 | data[13] << 10;
+ */
+ break;
case DOUBLE_REPORT_ID:
/* Sometimes the trackpad sends two touch reports in one
* packet.
@@ -392,7 +423,8 @@ static int magicmouse_raw_event(struct hid_device *hdev,
return 0;
}
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
magicmouse_emit_buttons(msc, clicks & 3);
input_report_rel(input, REL_X, x);
input_report_rel(input, REL_Y, y);
@@ -415,7 +447,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
__set_bit(EV_KEY, input->evbit);
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
__set_bit(BTN_LEFT, input->keybit);
__set_bit(BTN_RIGHT, input->keybit);
if (emulate_3button)
@@ -480,7 +513,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
* the origin at the same position, and just uses the additive
* inverse of the reported Y.
*/
- if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) {
+ if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
+ input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
input_set_abs_params(input, ABS_MT_POSITION_X,
MOUSE_MIN_X, MOUSE_MAX_X, 4, 0);
@@ -586,6 +620,7 @@ static int magicmouse_probe(struct hid_device *hdev,
{
const u8 *feature;
const u8 feature_mt[] = { 0xD7, 0x01 };
+ const u8 feature_mt_mouse2[] = { 0xF1, 0x02, 0x01 };
const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 };
const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 };
u8 *buf;
@@ -631,6 +666,9 @@ static int magicmouse_probe(struct hid_device *hdev,
if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
report = hid_register_report(hdev, HID_INPUT_REPORT,
MOUSE_REPORT_ID, 0);
+ else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2)
+ report = hid_register_report(hdev, HID_INPUT_REPORT,
+ MOUSE2_REPORT_ID, 0);
else if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
if (id->vendor == BT_VENDOR_ID_APPLE)
report = hid_register_report(hdev, HID_INPUT_REPORT,
@@ -660,6 +698,9 @@ static int magicmouse_probe(struct hid_device *hdev,
feature_size = sizeof(feature_mt_trackpad2_usb);
feature = feature_mt_trackpad2_usb;
}
+ } else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
+ feature_size = sizeof(feature_mt_mouse2);
+ feature = feature_mt_mouse2;
} else {
feature_size = sizeof(feature_mt);
feature = feature_mt;
@@ -696,6 +737,8 @@ static int magicmouse_probe(struct hid_device *hdev,
static const struct hid_device_id magic_mice[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
+ { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
+ USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 },
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
--
2.31.0

View File

@ -1,134 +0,0 @@
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <linux-kernel-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
X-Spam-Level:
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
autolearn_force=no version=3.4.0
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
by smtp.lore.kernel.org (Postfix) with ESMTP id 06C18C433E1
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:08 +0000 (UTC)
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by mail.kernel.org (Postfix) with ESMTP id D1CE16193D
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:07:07 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S230328AbhC0NGi (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
Sat, 27 Mar 2021 09:06:38 -0400
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59770 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S230266AbhC0NG1 (ORCPT
<rfc822;linux-kernel@vger.kernel.org>);
Sat, 27 Mar 2021 09:06:27 -0400
Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5086BC0613B1
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:27 -0700 (PDT)
Received: by mail-pl1-x634.google.com with SMTP id h8so2235029plt.7
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:27 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20161025;
h=from:to:cc:subject:date:message-id:in-reply-to:references
:mime-version:content-transfer-encoding;
bh=NeWUvZBV3NAy1b0eckELIbBZ7sti/n1sLYnD4r2cjaU=;
b=V7uM0AaI1Vy/mmqpuTVu5F6+98YPDzOa3QS6tRkWeJqhrflMONfCXtOxXVR+CeiPil
OOfaxOtAMeVEW9wE0EU3U/8aNghtzuUvVN+0Tj57+W+4g0ilQOODiDLDu4ZqAo1Q5eDZ
gA+He13KWVwNYaYTNUNParLXG5GYDbblaqABSUDurI1FTjn1US0ZZytlzdZy1GfL9eTj
6AiiVM3A4YdUGUWE7qQQE8jI92o4qKYvaNjn1M+d5ypKCue3NJWeRTSPKLu0QD2qL02+
QPga2RPtmLpztA8/lPGTRpgVNY3C5jdCBZyWgFtvZg5dNoDfe5bQnAmF2J2ka+A7JBSD
VHtw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
:references:mime-version:content-transfer-encoding;
bh=NeWUvZBV3NAy1b0eckELIbBZ7sti/n1sLYnD4r2cjaU=;
b=OQek2lJ5JINezfYdN/FzSPFL1N9Hrs+KstU7K4gEHavdffvSAOBebg2MG5VSzkf93H
o1iOiAOoXY7cx7j7Vx5CFZUuJOLilpC6gPTJpZlaP8YtEFfGkPaUPPh5FSTyM463Sir8
n6DupTSrFUI1y44GOBZ2bM2pf9hRN1Yj1oiCT6upmfoHw0/PaKEZt5aOEI8se7HRJp94
td6+SEZok3uxKEglKEqAG8cnj7Pt4tKVQlg+MI1AQDLQ/ytdYJlMPmrqVyNpnsv44wYa
dxBf0TaMvqn9SYDIDcGct3toAVm5DfVUqXm1nkYcYMOdvPrmLoH52NtCyi5cYC+2TR6i
jUpA==
X-Gm-Message-State: AOAM532sXgN0NNpKjilSMBewUXwwXz+MOfd7J5FRI6zAWA5st7gy5LmE
Sw/QHj4cm3zT07LU1kWYSO9puwFV+yK0Hquf
X-Google-Smtp-Source: ABdhPJyDnhcP7BeBHXX2rPqMXwkOQiZdussDPATmYqyQnp7HAsi0OqWSUVIloMNi3QBpMsmjXTtyew==
X-Received: by 2002:a17:903:2285:b029:e6:faf5:eaff with SMTP id b5-20020a1709032285b02900e6faf5eaffmr19574014plh.70.1616850386727;
Sat, 27 Mar 2021 06:06:26 -0700 (PDT)
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.25
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Sat, 27 Mar 2021 06:06:26 -0700 (PDT)
From: John Chen <johnchen902@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
John Chen <johnchen902@gmail.com>
Subject: [PATCH 2/4] HID: magicmouse: fix 3 button emulation of Mouse 2
Date: Sat, 27 Mar 2021 21:05:06 +0800
Message-Id: <20210327130508.24849-3-johnchen902@gmail.com>
X-Mailer: git-send-email 2.31.0
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
References: <20210327130508.24849-1-johnchen902@gmail.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-3-johnchen902@gmail.com/>
List-Archive: <https://lore.kernel.org/lkml/>
List-Post: <mailto:linux-kernel@vger.kernel.org>
It is observed that, with 3 button emulation, when middle button is
clicked, either the left button or right button is clicked as well. It
is caused by hidinput "correctly" acting on the event, oblivious to the
3 button emulation.
As raw_event has taken care of everything, no further processing is
needed. However, the only way to stop at raw_event is to return an error
(negative) value. Therefore, the processing is stopped at event instead.
Signed-off-by: John Chen <johnchen902@gmail.com>
---
drivers/hid/hid-magicmouse.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 7aad6ca56780..c646b4cd3783 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -440,6 +440,21 @@ static int magicmouse_raw_event(struct hid_device *hdev,
return 1;
}
+static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value)
+{
+ struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+ if (msc->input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 &&
+ field->report->id == MOUSE2_REPORT_ID) {
+ // magic_mouse_raw_event has done all the work. Skip hidinput.
+ //
+ // Specifically, hidinput may modify BTN_LEFT and BTN_RIGHT,
+ // breaking emulate_3button.
+ return 1;
+ }
+ return 0;
+}
+
static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev)
{
int error;
@@ -754,6 +769,7 @@ static struct hid_driver magicmouse_driver = {
.id_table = magic_mice,
.probe = magicmouse_probe,
.raw_event = magicmouse_raw_event,
+ .event = magicmouse_event,
.input_mapping = magicmouse_input_mapping,
.input_configured = magicmouse_input_configured,
};
--
2.31.0

View File

@ -1,265 +0,0 @@
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <linux-kernel-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
X-Spam-Level:
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
autolearn_force=no version=3.4.0
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
by smtp.lore.kernel.org (Postfix) with ESMTP id 9A212C433DB
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by mail.kernel.org (Postfix) with ESMTP id 60FCC61981
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S230394AbhC0NHJ (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
Sat, 27 Mar 2021 09:07:09 -0400
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59810 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S230307AbhC0NGi (ORCPT
<rfc822;linux-kernel@vger.kernel.org>);
Sat, 27 Mar 2021 09:06:38 -0400
Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1EDFCC0613B1
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:38 -0700 (PDT)
Received: by mail-pf1-x432.google.com with SMTP id q5so6741894pfh.10
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:38 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20161025;
h=from:to:cc:subject:date:message-id:in-reply-to:references
:mime-version:content-transfer-encoding;
bh=fWEWnDB7IS15Aoqul4RZDergwEtbUe4NAH8lKjv7p/s=;
b=CGLrSHoDnG8b5CL6asLWP1Ym/QFl+wtwIF8PhKlW7RJ5IhavVtdO6Fd7/cY/3GQTDa
wvX9Q1wfBsakVlG9/sM9CuozOsra6Ec9c1B+0beWTAKj/tBjwvsVHtMoCiqOPL/Vbig6
4zkWMb6dwWSzAgmCqPEaYlyJYqBrDLzzXxqGhchwTfcNgNZQGq0xhh7tZsukEPz4XLIC
LNCy6+hPSVdRG1ADbyPpOGFn3fSeFs5KAwl3y1Cn0TvTPxgpckTLcFz5TsTF/w7VLGW1
bn9Gakn+MaATqxahU0lDwyzI1sMK2er7/ddjV9VugYN4PzgL9DHGu/iGzXGFftDoLdaJ
tBIQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
:references:mime-version:content-transfer-encoding;
bh=fWEWnDB7IS15Aoqul4RZDergwEtbUe4NAH8lKjv7p/s=;
b=PQiPlj7RSTzmBU6u/2xzL9qv8jrelC7cJFFiOHjwKfz43PMzm0nEj6PxY5ZFMSjmbs
JEfC8iDjJh39FJdthBrvaZX4yuTv4QmOdmRMWrN77sQYbZOaKOhbNrCx2/LdHzAFjLBY
qTHW0+siiP/ATBf1M0cSP200UZAjBwU8MRapxAlaIUmlrfr5+oM8ZrL2tMhzDYcn5b51
TwXEVVI5Ep0YZxyGYQ04yaMBZxb1hSKev6UhrFpk96Ukg4IY3qBQBRpjWHIWqZY21aUl
EeDLmlWZaqDbp6UQQrAd2p1kIVyrxKD2Cf4aPnk2JcvzR9qGfMwV8cpR9rqwrXBEiyLj
KZFg==
X-Gm-Message-State: AOAM532lFsZyg8BiLek2pS5Ftc0rOopeD1Q9b7d5Lc7gC8pPIjHcnizK
2/grg+4GExN9zVerojORiZgGkTwU1/c2DswO
X-Google-Smtp-Source: ABdhPJwECFbuV2SwesS0pF6L0s23ghF61g6whXAjcLZpxYe6b6OsgENBMa3gmTj9FFMF+68uJYhPPw==
X-Received: by 2002:a63:1d26:: with SMTP id d38mr17032822pgd.385.1616850397389;
Sat, 27 Mar 2021 06:06:37 -0700 (PDT)
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.36
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Sat, 27 Mar 2021 06:06:37 -0700 (PDT)
From: John Chen <johnchen902@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
John Chen <johnchen902@gmail.com>
Subject: [PATCH 3/4] HID: magicmouse: fix reconnection of Magic Mouse 2
Date: Sat, 27 Mar 2021 21:05:07 +0800
Message-Id: <20210327130508.24849-4-johnchen902@gmail.com>
X-Mailer: git-send-email 2.31.0
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
References: <20210327130508.24849-1-johnchen902@gmail.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-4-johnchen902@gmail.com/>
List-Archive: <https://lore.kernel.org/lkml/>
List-Post: <mailto:linux-kernel@vger.kernel.org>
It is observed that the Magic Mouse 2 would not enter multi-touch mode
unless the mouse is connected before loading the module. It seems to be
a quirk specific to Magic Mouse 2
Retrying after 500ms fixes the problem for me. The delay can't be
reduced much further --- 300ms didn't work for me. Retrying immediately
after receiving an event didn't work either.
Signed-off-by: John Chen <johnchen902@gmail.com>
---
drivers/hid/hid-magicmouse.c | 93 ++++++++++++++++++++++++------------
1 file changed, 63 insertions(+), 30 deletions(-)
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index c646b4cd3783..69aefef9fe07 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -16,6 +16,7 @@
#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include "hid-ids.h"
@@ -128,6 +129,9 @@ struct magicmouse_sc {
u8 size;
} touches[16];
int tracking_ids[16];
+
+ struct hid_device *hdev;
+ struct delayed_work work;
};
static int magicmouse_firm_touch(struct magicmouse_sc *msc)
@@ -629,9 +633,7 @@ static int magicmouse_input_configured(struct hid_device *hdev,
return 0;
}
-
-static int magicmouse_probe(struct hid_device *hdev,
- const struct hid_device_id *id)
+static int magicmouse_enable_multitouch(struct hid_device *hdev)
{
const u8 *feature;
const u8 feature_mt[] = { 0xD7, 0x01 };
@@ -639,10 +641,52 @@ static int magicmouse_probe(struct hid_device *hdev,
const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 };
const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 };
u8 *buf;
+ int ret;
+ int feature_size;
+
+ if (hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
+ if (hdev->vendor == BT_VENDOR_ID_APPLE) {
+ feature_size = sizeof(feature_mt_trackpad2_bt);
+ feature = feature_mt_trackpad2_bt;
+ } else { /* USB_VENDOR_ID_APPLE */
+ feature_size = sizeof(feature_mt_trackpad2_usb);
+ feature = feature_mt_trackpad2_usb;
+ }
+ } else if (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
+ feature_size = sizeof(feature_mt_mouse2);
+ feature = feature_mt_mouse2;
+ } else {
+ feature_size = sizeof(feature_mt);
+ feature = feature_mt;
+ }
+
+ buf = kmemdup(feature, feature_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size,
+ HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+ kfree(buf);
+ return ret;
+}
+
+static void magicmouse_enable_mt_work(struct work_struct *work)
+{
+ struct magicmouse_sc *msc =
+ container_of(work, struct magicmouse_sc, work.work);
+ int ret;
+
+ ret = magicmouse_enable_multitouch(msc->hdev);
+ if (ret < 0)
+ hid_err(msc->hdev, "unable to request touch data (%d)\n", ret);
+}
+
+static int magicmouse_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
+{
struct magicmouse_sc *msc;
struct hid_report *report;
int ret;
- int feature_size;
if (id->vendor == USB_VENDOR_ID_APPLE &&
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
@@ -656,6 +700,8 @@ static int magicmouse_probe(struct hid_device *hdev,
}
msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
+ msc->hdev = hdev;
+ INIT_DEFERRABLE_WORK(&msc->work, magicmouse_enable_mt_work);
msc->quirks = id->driver_data;
hid_set_drvdata(hdev, msc);
@@ -705,28 +751,6 @@ static int magicmouse_probe(struct hid_device *hdev,
}
report->size = 6;
- if (id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
- if (id->vendor == BT_VENDOR_ID_APPLE) {
- feature_size = sizeof(feature_mt_trackpad2_bt);
- feature = feature_mt_trackpad2_bt;
- } else { /* USB_VENDOR_ID_APPLE */
- feature_size = sizeof(feature_mt_trackpad2_usb);
- feature = feature_mt_trackpad2_usb;
- }
- } else if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
- feature_size = sizeof(feature_mt_mouse2);
- feature = feature_mt_mouse2;
- } else {
- feature_size = sizeof(feature_mt);
- feature = feature_mt;
- }
-
- buf = kmemdup(feature, feature_size, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto err_stop_hw;
- }
-
/*
* Some devices repond with 'invalid report id' when feature
* report switching it into multitouch mode is sent to it.
@@ -735,13 +759,14 @@ static int magicmouse_probe(struct hid_device *hdev,
* but there seems to be no other way of switching the mode.
* Thus the super-ugly hacky success check below.
*/
- ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size,
- HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
- kfree(buf);
- if (ret != -EIO && ret != feature_size) {
+ ret = magicmouse_enable_multitouch(hdev);
+ if (ret != -EIO && ret < 0) {
hid_err(hdev, "unable to request touch data (%d)\n", ret);
goto err_stop_hw;
}
+ if (ret == -EIO && id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2) {
+ schedule_delayed_work(&msc->work, msecs_to_jiffies(500));
+ }
return 0;
err_stop_hw:
@@ -749,6 +774,13 @@ static int magicmouse_probe(struct hid_device *hdev,
return ret;
}
+static void magicmouse_remove(struct hid_device *hdev)
+{
+ struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+ cancel_delayed_work_sync(&msc->work);
+ hid_hw_stop(hdev);
+}
+
static const struct hid_device_id magic_mice[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
@@ -768,6 +800,7 @@ static struct hid_driver magicmouse_driver = {
.name = "magicmouse",
.id_table = magic_mice,
.probe = magicmouse_probe,
+ .remove = magicmouse_remove,
.raw_event = magicmouse_raw_event,
.event = magicmouse_event,
.input_mapping = magicmouse_input_mapping,
--
2.31.0

View File

@ -1,155 +0,0 @@
From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path: <linux-kernel-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
X-Spam-Level:
X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED,
DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham
autolearn_force=no version=3.4.0
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
by smtp.lore.kernel.org (Postfix) with ESMTP id 9BE24C433E0
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by mail.kernel.org (Postfix) with ESMTP id 70E6A61993
for <linux-kernel@archiver.kernel.org>; Sat, 27 Mar 2021 13:10:34 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S230334AbhC0NHL (ORCPT <rfc822;linux-kernel@archiver.kernel.org>);
Sat, 27 Mar 2021 09:07:11 -0400
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59832 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S230347AbhC0NGo (ORCPT
<rfc822;linux-kernel@vger.kernel.org>);
Sat, 27 Mar 2021 09:06:44 -0400
Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AAD5C0613B1
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:44 -0700 (PDT)
Received: by mail-pg1-x536.google.com with SMTP id 32so6451842pgm.1
for <linux-kernel@vger.kernel.org>; Sat, 27 Mar 2021 06:06:44 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20161025;
h=from:to:cc:subject:date:message-id:in-reply-to:references
:mime-version:content-transfer-encoding;
bh=5GW0J0I07iFc3HTzTSsHG/cnT3ft+pF2eI68TUZquXs=;
b=jJACN/frvED8BOFNtDXFShzg5zpUEJjtXdexEk/8uljNrUnW9QBLA5orX/2hdcZdS4
9HL492GecBx3KY9Y5P/B3fttZmlHkwWbuUktmVlmaIOZv1jAPTyYz5zJYh0O0ncw9/rk
aPvRb4s1NZHByZ4XoCWbWOd98BvgHHQ/m4Zf1zmP5lYjBVMb2r6qSejuJ5ywQOCBKo9x
Q8SL42BOWrlNlsWmeP+oDEYWSDARHpKlRqQ63Y4LdvV2uS9IF6+bmHotGSRlHSLuFN1b
/PcfuSQynv38/EgH8MeE16VKzAvLXGu/KgcOLLCsSLgPFLqKAk3uQVc5QRLw00niguHp
MMUg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20161025;
h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to
:references:mime-version:content-transfer-encoding;
bh=5GW0J0I07iFc3HTzTSsHG/cnT3ft+pF2eI68TUZquXs=;
b=AueOy/X73fYr+YShlS2LMp2gWnsgDUIFV7eKHphj6Q1dBTHtj/dxdarFAonoqAtMRD
RCpUwakkFtecMcJPGG/2FRZdRmbJg/ksRvalLQhQCN8XYGB4T/o3zmaOUUooitcGC3gj
aeCCryhkv9OzDUYTwPsAzTjrDTkTB3Oh8IvWhfEIcb9x8k+J+OLaIrGozUxhtJkepSRc
Uswy+MJkcl8KfXiawODwnjX7JmWwm2SdpRbsBKjJjs+rad+ECgYEFyt8aqYbTabFtIuj
oaHtcYHS6FLYTFcRbhCcVECQo2OUzvJjPNe5GyHqUxlvmdFI/Wn68/dt5DKSl5CHRjrp
qdPA==
X-Gm-Message-State: AOAM530Dp411JuLoADUDvvtPhkgbdVcoa5u6Mm4STd67xIRk49ZPXT33
uWg1/mAtTfIfNFL2t5NEvBtvsCfrYoBgGzJJ
X-Google-Smtp-Source: ABdhPJw4EeRec5E5FY/fifXp32gxWuRl/ThAsWSiEflIS3aALG3LbhZVwkDmQhbhsG3gD8jRMsQIlw==
X-Received: by 2002:a62:17c4:0:b029:1f5:7cfe:ebc4 with SMTP id 187-20020a6217c40000b02901f57cfeebc4mr17080244pfx.5.1616850403793;
Sat, 27 Mar 2021 06:06:43 -0700 (PDT)
Received: from johnchen902-arch-ryzen.. (2001-b011-3815-3a1f-9afa-9bff-fe6e-3ce2.dynamic-ip6.hinet.net. [2001:b011:3815:3a1f:9afa:9bff:fe6e:3ce2])
by smtp.gmail.com with ESMTPSA id ot17sm6413787pjb.50.2021.03.27.06.06.42
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Sat, 27 Mar 2021 06:06:43 -0700 (PDT)
From: John Chen <johnchen902@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Rohit Pidaparthi <rohitpid@gmail.com>,
RicardoEPRodrigues <ricardo.e.p.rodrigues@gmail.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
John Chen <johnchen902@gmail.com>
Subject: [PATCH 4/4] HID: input: map battery capacity (00850065)
Date: Sat, 27 Mar 2021 21:05:08 +0800
Message-Id: <20210327130508.24849-5-johnchen902@gmail.com>
X-Mailer: git-send-email 2.31.0
In-Reply-To: <20210327130508.24849-1-johnchen902@gmail.com>
References: <20210327130508.24849-1-johnchen902@gmail.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Precedence: bulk
List-ID: <linux-kernel.vger.kernel.org>
X-Mailing-List: linux-kernel@vger.kernel.org
Archived-At: <https://lore.kernel.org/lkml/20210327130508.24849-5-johnchen902@gmail.com/>
List-Archive: <https://lore.kernel.org/lkml/>
List-Post: <mailto:linux-kernel@vger.kernel.org>
This is the capacity in percentage, relative to design capacity.
Specifically, it is present in Apple Magic Mouse 2.
In contrast, usage 00850064 is also the capacity in percentage, but is
relative to full capacity. It is not mapped here because I don't have
such device.
Signed-off-by: John Chen <johnchen902@gmail.com>
---
drivers/hid/hid-debug.c | 1 +
drivers/hid/hid-input.c | 11 +++++++++++
include/linux/hid.h | 3 +++
3 files changed, 15 insertions(+)
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index d7eaf9100370..59f8d716d78f 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -417,6 +417,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
{ 0x85, 0x44, "Charging" },
{ 0x85, 0x45, "Discharging" },
{ 0x85, 0x4b, "NeedReplacement" },
+ { 0x85, 0x65, "AbsoluteStateOfCharge" },
{ 0x85, 0x66, "RemainingCapacity" },
{ 0x85, 0x68, "RunTimeToEmpty" },
{ 0x85, 0x6a, "AverageTimeToFull" },
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 236bccd37760..5dea3669a927 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1074,6 +1074,17 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
goto unknown;
+ case HID_UP_BATTERY:
+ switch (usage->hid) {
+ case HID_BAT_ABSOLUTESTATEOFCHARGE:
+ hidinput_setup_battery(device, HID_INPUT_REPORT, field);
+ usage->type = EV_PWR;
+ device->battery_min = 0;
+ device->battery_max = 100;
+ return;
+ }
+ goto unknown;
+
case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
set_bit(EV_REP, input->evbit);
switch (usage->hid & HID_USAGE) {
diff --git a/include/linux/hid.h b/include/linux/hid.h
index ef702b3f56e3..b40e1abbe11d 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -153,6 +153,7 @@ struct hid_item {
#define HID_UP_CONSUMER 0x000c0000
#define HID_UP_DIGITIZER 0x000d0000
#define HID_UP_PID 0x000f0000
+#define HID_UP_BATTERY 0x00850000
#define HID_UP_HPVENDOR 0xff7f0000
#define HID_UP_HPVENDOR2 0xff010000
#define HID_UP_MSVENDOR 0xff000000
@@ -297,6 +298,8 @@ struct hid_item {
#define HID_DG_TOOLSERIALNUMBER 0x000d005b
#define HID_DG_LATENCYMODE 0x000d0060
+#define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065
+
#define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076
/*
* HID report types --- Ouch! HID spec says 1 2 3!
--
2.31.0

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