Prepration for PPP and 5.16 support
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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, ¶ms->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, ¶ms->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
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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 = <®_dldo1>;
 | 
			
		||||
+	status = "okay";
 | 
			
		||||
+
 | 
			
		||||
+	panel@0 {
 | 
			
		||||
+		compatible = "feixin,k101-im2ba02";
 | 
			
		||||
+		reg = <0>;
 | 
			
		||||
+		avdd-supply = <®_dc1sw>;
 | 
			
		||||
+		dvdd-supply = <®_dc1sw>;
 | 
			
		||||
+		cvdd-supply = <®_ldo_io1>;
 | 
			
		||||
+		reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
 | 
			
		||||
+		backlight = <&backlight>;
 | 
			
		||||
+	};
 | 
			
		||||
+};
 | 
			
		||||
-- 
 | 
			
		||||
2.25.4
 | 
			
		||||
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -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,
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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,
 | 
			
		||||
@@ -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,
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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");
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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 = ␣
 | 
			
		||||
 
 | 
			
		||||
+	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;
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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 = <®_dcdc1>;
 | 
			
		||||
 	vcc-pc-supply = <®_dcdc1>;
 | 
			
		||||
 	vcc-pd-supply = <®_dcdc1>;
 | 
			
		||||
-	/* pinctrl would enable this even if no camera is powered,
 | 
			
		||||
-	 * which is wrong/not necessary
 | 
			
		||||
-	 *
 | 
			
		||||
-	 * vcc-pe-supply = <®_aldo1>; (also used by pogo pins i2c)
 | 
			
		||||
-	 */
 | 
			
		||||
+	vcc-pe-supply = <®_aldo1>; /* (also used by pogo pins i2c) */
 | 
			
		||||
 	vcc-pf-supply = <®_dcdc1>;
 | 
			
		||||
 	vcc-pg-supply = <®_dldo4>;
 | 
			
		||||
 	vcc-ph-supply = <®_dcdc1>;
 | 
			
		||||
-- 
 | 
			
		||||
2.30.1
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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>");
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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, ®);
 | 
			
		||||
+	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, ®);
 | 
			
		||||
+	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, ®);
 | 
			
		||||
+		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, ®);
 | 
			
		||||
+		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, ®);
 | 
			
		||||
+	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, ®);
 | 
			
		||||
+	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, ®);
 | 
			
		||||
+		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, ®);
 | 
			
		||||
+		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, ®);
 | 
			
		||||
+		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, ®);
 | 
			
		||||
+		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, ®);
 | 
			
		||||
+		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>");
 | 
			
		||||
@@ -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:
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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, ®);
 | 
			
		||||
+	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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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) {
 | 
			
		||||
@@ -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) {
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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, ®);
 | 
			
		||||
+		if (ret < 0)
 | 
			
		||||
+			return ret;
 | 
			
		||||
+
 | 
			
		||||
 		/* unmask TOGDONE interrupt */
 | 
			
		||||
 		ret = fusb302_i2c_clear_bits(chip, FUSB_REG_MASKA,
 | 
			
		||||
 					     FUSB_REG_MASKA_TOGDONE);
 | 
			
		||||
@@ -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");
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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) {
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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",
 | 
			
		||||
@@ -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");
 | 
			
		||||
@@ -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)
 | 
			
		||||
@@ -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,
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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");
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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 = >1x_chip_data },
 | 
			
		||||
+	{ .id = "1158", .data = >1x_chip_data },
 | 
			
		||||
 	{ .id = "5663", .data = >1x_chip_data },
 | 
			
		||||
 	{ .id = "5688", .data = >1x_chip_data },
 | 
			
		||||
 	{ .id = "917S", .data = >1x_chip_data },
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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";
 | 
			
		||||
@@ -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";
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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>;
 | 
			
		||||
@@ -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";
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
@@ -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
 | 
			
		||||
+};
 | 
			
		||||
@@ -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";
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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>;
 | 
			
		||||
@@ -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>;
 | 
			
		||||
 	};
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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>;
 | 
			
		||||
@@ -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";
 | 
			
		||||
@@ -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";
 | 
			
		||||
@@ -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>;
 | 
			
		||||
@@ -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";
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
@@ -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>;
 | 
			
		||||
@@ -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>;
 | 
			
		||||
+		};
 | 
			
		||||
 	};
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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";
 | 
			
		||||
 };
 | 
			
		||||
@@ -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>;
 | 
			
		||||
 		};
 | 
			
		||||
@@ -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",
 | 
			
		||||
@@ -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;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
@@ -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 = <®_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
 | 
			
		||||
 | 
			
		||||
@@ -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 = <®_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
											
										
									
								
							@@ -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 */
 | 
			
		||||
@@ -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%
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -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
		Reference in New Issue
	
	Block a user