From eb0fadf2df207133d336b23d3bf98aa3cca1de00 Mon Sep 17 00:00:00 2001 From: Gerben Jan Dijkman Date: Sat, 29 Jan 2022 21:31:23 +0100 Subject: [PATCH] Changed patches --- ...l-org-bug-210681-firmware_rome_error.patch | 12 + ...pio-make-max_brightness-configurable.patch | 49 ++ ...ent-clocks-to-lower-speed-oscillator.patch | 50 ++ .../dts-pinephone-drop-modem-power-node.patch | 175 ++++++ .../media-ov5640-Implement-autofocus.patch | 409 +++++++++++++ .../pinephone-sources/files/panic-led.patch | 12 + .../pinephone-sources/files/pp-keyboard.patch | 549 ------------------ .../pinephone-sources-5.16.3.ebuild | 2 - 8 files changed, 707 insertions(+), 551 deletions(-) create mode 100644 sys-kernel/pinephone-sources/files/0107-quirk-kernel-org-bug-210681-firmware_rome_error.patch create mode 100644 sys-kernel/pinephone-sources/files/0177-leds-gpio-make-max_brightness-configurable.patch create mode 100644 sys-kernel/pinephone-sources/files/ccu-sun50i-a64-reparent-clocks-to-lower-speed-oscillator.patch create mode 100644 sys-kernel/pinephone-sources/files/dts-pinephone-drop-modem-power-node.patch create mode 100644 sys-kernel/pinephone-sources/files/media-ov5640-Implement-autofocus.patch create mode 100644 sys-kernel/pinephone-sources/files/panic-led.patch delete mode 100644 sys-kernel/pinephone-sources/files/pp-keyboard.patch diff --git a/sys-kernel/pinephone-sources/files/0107-quirk-kernel-org-bug-210681-firmware_rome_error.patch b/sys-kernel/pinephone-sources/files/0107-quirk-kernel-org-bug-210681-firmware_rome_error.patch new file mode 100644 index 0000000..7f46da7 --- /dev/null +++ b/sys-kernel/pinephone-sources/files/0107-quirk-kernel-org-bug-210681-firmware_rome_error.patch @@ -0,0 +1,12 @@ +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; + } + diff --git a/sys-kernel/pinephone-sources/files/0177-leds-gpio-make-max_brightness-configurable.patch b/sys-kernel/pinephone-sources/files/0177-leds-gpio-make-max_brightness-configurable.patch new file mode 100644 index 0000000..e844fce --- /dev/null +++ b/sys-kernel/pinephone-sources/files/0177-leds-gpio-make-max_brightness-configurable.patch @@ -0,0 +1,49 @@ +From cb408fb65a08bd45543724c1e9b8f38ae1bebc4a Mon Sep 17 00:00:00 2001 +From: Arnaud Ferraris +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 + diff --git a/sys-kernel/pinephone-sources/files/ccu-sun50i-a64-reparent-clocks-to-lower-speed-oscillator.patch b/sys-kernel/pinephone-sources/files/ccu-sun50i-a64-reparent-clocks-to-lower-speed-oscillator.patch new file mode 100644 index 0000000..2a16042 --- /dev/null +++ b/sys-kernel/pinephone-sources/files/ccu-sun50i-a64-reparent-clocks-to-lower-speed-oscillator.patch @@ -0,0 +1,50 @@ +diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +index 149cfde817cb..0399d8714fd0 100644 +--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +@@ -984,6 +984,8 @@ static int sun50i_a64_ccu_probe(struct p + if (IS_ERR(reg)) + return PTR_ERR(reg); + ++ platform_set_drvdata(pdev, reg); ++ + /* Force the pll-audio variable divider to 3 */ + val = readl(reg + SUN50I_A64_PLL_AUDIO_REG); + val &= ~GENMASK(19, 16); +@@ -1031,12 +1031,36 @@ static const struct of_device_id sun50i_ + { } + }; + ++#define USBPHY_CFG_REG 0x0cc ++ ++static int sun50i_a64_ccu_suspend(struct device *dev) ++{ ++ void __iomem *reg = dev_get_drvdata(dev); ++ ++ writel(readl(reg + USBPHY_CFG_REG) | 0xa00000, reg + USBPHY_CFG_REG); ++ ++ return 0; ++} ++ ++static int sun50i_a64_ccu_resume(struct device *dev) ++{ ++ void __iomem *reg = dev_get_drvdata(dev); ++ ++ writel(readl(reg + USBPHY_CFG_REG) & ~0xa00000, reg + USBPHY_CFG_REG); ++ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(sun50i_a64_ccu_pm_ops, ++ sun50i_a64_ccu_suspend, sun50i_a64_ccu_resume); ++ + static struct platform_driver sun50i_a64_ccu_driver = { + .probe = sun50i_a64_ccu_probe, + .driver = { + .name = "sun50i-a64-ccu", + .suppress_bind_attrs = true, + .of_match_table = sun50i_a64_ccu_ids, ++ .pm = &sun50i_a64_ccu_pm_ops, + }, + }; + builtin_platform_driver(sun50i_a64_ccu_driver); diff --git a/sys-kernel/pinephone-sources/files/dts-pinephone-drop-modem-power-node.patch b/sys-kernel/pinephone-sources/files/dts-pinephone-drop-modem-power-node.patch new file mode 100644 index 0000000..14ebbe2 --- /dev/null +++ b/sys-kernel/pinephone-sources/files/dts-pinephone-drop-modem-power-node.patch @@ -0,0 +1,175 @@ +From 5da6a7e3f4d6e11f4887893672f849d2d4fa5b58 Mon Sep 17 00:00:00 2001 +From: Clayton Craft +Date: Wed, 16 Dec 2020 20:16:14 -0800 +Subject: [PATCH] dts: pinephone: drop modem-power node + +--- + .../allwinner/sun50i-a64-pinephone-1.0.dts | 26 +++--------------- + .../allwinner/sun50i-a64-pinephone-1.1.dts | 27 +++---------------- + .../allwinner/sun50i-a64-pinephone-1.2.dts | 27 +++---------------- + .../dts/allwinner/sun50i-a64-pinephone.dtsi | 12 +++++++++ + 4 files changed, 24 insertions(+), 68 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 0f6faa44ce3e..2cc513772172 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 +@@ -86,28 +86,6 @@ ®_drivevbus { + status = "okay"; + }; + +-&uart3 { +- modem { +- compatible = "quectel,eg25"; +- char-device-name = "modem-power"; +- +- power-supply = <®_vbat_bb>; /* PL7 */ +- +- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ +- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */ +- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ +- +- sleep-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ +- wakeup-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-RI */ +- +- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */ +- dtr-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-DTR */ +- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */ +- +- quectel,qdai = "1,1,0,1,0,0,1,1"; +- }; +-}; +- + &usbphy { + usb-role-switch; + +@@ -118,6 +96,10 @@ usb0_drd_sw: endpoint { + }; + }; + ++&ring_indicator { ++ gpios = <&pio 1 2 GPIO_ACTIVE_LOW>; /* PB2 */ ++}; ++ + &sgm3140 { + flash-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ + enable-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */ +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 95a880fdc9ce..5f3b6a1a142f 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 +@@ -109,34 +109,15 @@ + status = "okay"; + }; + ++&ring_indicator { ++ gpios = <&pio 1 2 GPIO_ACTIVE_LOW>; /* PB2 */ ++}; ++ + &sgm3140 { + enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ + flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */ + }; + +-&uart3 { +- modem { +- compatible = "quectel,eg25"; +- char-device-name = "modem-power"; +- +- power-supply = <®_vbat_bb>; /* PL7 */ +- +- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ +- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */ +- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ +- //status-pwrkey-multiplexed; /* status acts as pwrkey */ +- +- sleep-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ +- wakeup-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-RI */ +- +- dtr-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-DTR */ +- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */ +- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */ +- +- quectel,qdai = "1,1,0,1,0,0,1,1"; +- }; +-}; +- + &usbphy { + usb-role-switch; + +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 23ba72508cfc..889841ca5b8a 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 +@@ -101,34 +101,15 @@ + enable-active-high; + }; + ++&ring_indicator { ++ gpios = <&r_pio 0 6 GPIO_ACTIVE_LOW>; /* PL6 */ ++}; ++ + &sgm3140 { + enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */ + flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */ + }; + +-&uart3 { +- modem { +- compatible = "quectel,eg25"; +- char-device-name = "modem-power"; +- +- power-supply = <®_vbat_bb>; /* PL7 */ +- +- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ +- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */ +- status-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ +- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ +- +- host-ready-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */ +- wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-RI */ +- +- dtr-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-DTR */ +- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */ +- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */ +- +- quectel,qdai = "1,1,0,1,0,0,1,1"; +- }; +-}; +- + &usbphy { + usb-role-switch; + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +index 02d82980cf39..979d01de8d84 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +@@ -192,6 +192,17 @@ ec25_codec: ec25-codec { + compatible = "quectel,ec25"; + }; + ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ ring_indicator: ring-indicator { ++ label = "Ring Indicator"; ++ linux,can-disable; ++ linux,code = ; ++ wakeup-source; ++ }; ++ }; ++ + i2c_csi: i2c-csi { + compatible = "i2c-gpio"; + sda-gpios = <&pio 4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; /* PE13 */ +@@ -256,6 +267,7 @@ reg_usb_5v: usb-5v { + reg_vbat_bb: vbat-bb { + compatible = "regulator-fixed"; + regulator-name = "vbat-bb"; ++ regulator-always-on; + regulator-min-microvolt = <3500000>; + regulator-max-microvolt = <3500000>; + gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */ +-- +2.29.2 + diff --git a/sys-kernel/pinephone-sources/files/media-ov5640-Implement-autofocus.patch b/sys-kernel/pinephone-sources/files/media-ov5640-Implement-autofocus.patch new file mode 100644 index 0000000..68c6581 --- /dev/null +++ b/sys-kernel/pinephone-sources/files/media-ov5640-Implement-autofocus.patch @@ -0,0 +1,409 @@ +From f062022f2a2781d6b8ca63c460b0e72ebac30870 Mon Sep 17 00:00:00 2001 +From: Martijn Braam +Date: Mon, 28 Sep 2020 14:26:11 +0200 +Subject: [PATCH] media: ov5640: Implement autofocus + +The autofocus functionality needs a firmware blob loaded into the +internal microcontroller. + +V4L2 doesn't have an api to control all autofocus functionality, but +this at least makes it possible to focus on the center of the sensor. + +Signed-off-by: Martijn Braam +--- + drivers/media/i2c/ov5640.c | 254 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 254 insertions(+) + +diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c +index df0a507c211f..08a5304c0e95 100644 +--- a/drivers/media/i2c/ov5640.c ++++ b/drivers/media/i2c/ov5640.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -31,7 +32,11 @@ + + #define OV5640_DEFAULT_SLAVE_ID 0x3c + ++#define OV5640_REG_SYS_RESET00 0x3000 ++#define OV5640_REG_SYS_RESET01 0x3001 + #define OV5640_REG_SYS_RESET02 0x3002 ++#define OV5640_REG_SYS_CLOCK_ENABLE00 0x3004 ++#define OV5640_REG_SYS_CLOCK_ENABLE01 0x3005 + #define OV5640_REG_SYS_CLOCK_ENABLE02 0x3006 + #define OV5640_REG_SYS_CTRL0 0x3008 + #define OV5640_REG_SYS_CTRL0_SW_PWDN 0x42 +@@ -41,6 +46,14 @@ + #define OV5640_REG_PAD_OUTPUT_ENABLE01 0x3017 + #define OV5640_REG_PAD_OUTPUT_ENABLE02 0x3018 + #define OV5640_REG_PAD_OUTPUT00 0x3019 ++#define OV5640_REG_FW_CMD_MAIN 0x3022 ++#define OV5640_REG_FW_CMD_ACK 0x3023 ++#define OV5640_REG_FW_CMD_PARA0 0x3024 ++#define OV5640_REG_FW_CMD_PARA1 0x3025 ++#define OV5640_REG_FW_CMD_PARA2 0x3026 ++#define OV5640_REG_FW_CMD_PARA3 0x3027 ++#define OV5640_REG_FW_CMD_PARA4 0x3028 ++#define OV5640_REG_FW_STATUS 0x3029 + #define OV5640_REG_SYSTEM_CONTROL1 0x302e + #define OV5640_REG_SC_PLL_CTRL0 0x3034 + #define OV5640_REG_SC_PLL_CTRL1 0x3035 +@@ -59,6 +72,7 @@ + #define OV5640_REG_AEC_PK_MANUAL 0x3503 + #define OV5640_REG_AEC_PK_REAL_GAIN 0x350a + #define OV5640_REG_AEC_PK_VTS 0x350c ++#define OV5640_REG_VCM_CONTROL4 0x3606 + #define OV5640_REG_TIMING_DVPHO 0x3808 + #define OV5640_REG_TIMING_DVPVO 0x380a + #define OV5640_REG_TIMING_HTS 0x380c +@@ -95,6 +109,20 @@ + #define OV5640_REG_SDE_CTRL4 0x5584 + #define OV5640_REG_SDE_CTRL5 0x5585 + #define OV5640_REG_AVG_READOUT 0x56a1 ++#define OV5640_REG_FIRMWARE_BASE 0x8000 ++ ++#define OV5640_FW_STATUS_S_FIRMWARE 0x7f ++#define OV5640_FW_STATUS_S_STARTUP 0x7e ++#define OV5640_FW_STATUS_S_IDLE 0x70 ++#define OV5640_FW_STATUS_S_FOCUSING 0x00 ++#define OV5640_FW_STATUS_S_FOCUSED 0x10 ++ ++#define OV5640_FW_CMD_TRIGGER_FOCUS 0x03 ++#define OV5640_FW_CMD_CONTINUOUS_FOCUS 0x04 ++#define OV5640_FW_CMD_GET_FOCUS_RESULT 0x07 ++#define OV5640_FW_CMD_RELEASE_FOCUS 0x08 ++#define OV5640_FW_CMD_ZONE_CONFIG 0x12 ++#define OV5640_FW_CMD_DEFAULT_ZONES 0x80 + + enum ov5640_mode_id { + OV5640_MODE_QCIF_176_144 = 0, +@@ -218,6 +246,12 @@ struct ov5640_ctrls { + struct v4l2_ctrl *auto_gain; + struct v4l2_ctrl *gain; + }; ++ struct { ++ struct v4l2_ctrl *focus_auto; ++ struct v4l2_ctrl *af_start; ++ struct v4l2_ctrl *af_stop; ++ struct v4l2_ctrl *af_status; ++ }; + struct v4l2_ctrl *brightness; + struct v4l2_ctrl *light_freq; + struct v4l2_ctrl *saturation; +@@ -261,6 +295,8 @@ struct ov5640_dev { + + bool pending_mode_change; + bool streaming; ++ ++ bool af_initialized; + }; + + static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd) +@@ -1967,6 +2003,118 @@ static void ov5640_reset(struct ov5640_dev *sensor) + usleep_range(20000, 25000); + } + ++static int ov5640_copy_fw_to_device(struct ov5640_dev *sensor, ++ const struct firmware *fw) ++{ ++ struct i2c_client *client = sensor->i2c_client; ++ const u8 *data = (const u8 *)fw->data; ++ u8 fw_status; ++ int i; ++ int ret; ++ ++ // Putting MCU in reset state ++ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x20); ++ if (ret) ++ return ret; ++ ++ // Write firmware ++ for (i = 0; i < fw->size / sizeof(u8); i++) ++ ov5640_write_reg(sensor, ++ OV5640_REG_FIRMWARE_BASE + i, ++ data[i]); ++ ++ // Reset MCU state ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_MAIN, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_ACK, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA0, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA1, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA2, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA3, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_CMD_PARA4, 0x00); ++ ov5640_write_reg(sensor, OV5640_REG_FW_STATUS, 0x7f); ++ ++ // Start AF MCU ++ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x00); ++ if (ret) ++ return ret; ++ ++ dev_info(&client->dev, "firmware upload success\n"); ++ ++ // Wait for firmware to be ready ++ for (i = 0; i < 5; i++) { ++ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status); ++ if (fw_status == OV5640_FW_STATUS_S_IDLE) { ++ dev_info(&client->dev, "fw started after %d ms\n", i * 50); ++ return ret; ++ } ++ msleep(50); ++ } ++ dev_err(&client->dev, "uploaded firmware didn't start, got to 0x%x, retrying...\n", fw_status); ++ ++ // Putting MCU in reset state ++ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x20); ++ if (ret) ++ return ret; ++ // Start AF MCU ++ ret = ov5640_write_reg(sensor, OV5640_REG_SYS_RESET00, 0x00); ++ if (ret) ++ return ret; ++ // Wait for firmware to be ready ++ for (i = 0; i < 5; i++) { ++ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status); ++ if (fw_status == OV5640_FW_STATUS_S_IDLE) { ++ dev_info(&client->dev, "fw started after %d ms\n", i * 50); ++ return ret; ++ } ++ msleep(50); ++ } ++ dev_err(&client->dev, "uploaded firmware didn't start, got to 0x%x\n", fw_status); ++ return -ETIMEDOUT; ++} ++ ++static int ov5640_af_init(struct ov5640_dev *sensor) ++{ ++ struct i2c_client *client = sensor->i2c_client; ++ const char* fwname = "ov5640_af.bin"; ++ const struct firmware *fw; ++ int ret; ++ ++ if (sensor->af_initialized) { ++ return 0; ++ } ++ ++ if (firmware_request_nowarn(&fw, fwname, &client->dev) == 0) { ++ ret = ov5640_copy_fw_to_device(sensor, fw); ++ if (ret == 0) ++ sensor->af_initialized = 1; ++ } else { ++ dev_warn(&client->dev, "%s: no autofocus firmware available (%s)\n", ++ __func__, fwname); ++ ret = -1; ++ } ++ release_firmware(fw); ++ ++ if (ret) ++ return ret; ++ ++ // Enable AF systems ++ ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE00, ++ (BIT(6) | BIT(5)), (BIT(6) | BIT(5))); ++ if (ret) ++ return ret; ++ ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE01, ++ BIT(6), BIT(6)); ++ if (ret) ++ return ret; ++ ++ // Set lens focus driver on ++ ov5640_write_reg(sensor, OV5640_REG_VCM_CONTROL4, 0x3f); ++ if (ret) ++ return ret; ++ ++ return ret; ++} ++ + 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) + goto xclk_off; + } + ++ sensor->af_initialized = 0; ++ + ov5640_reset(sensor); + ov5640_power(sensor, true); + +@@ -2416,6 +2547,35 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor, + is_jpeg ? (BIT(5) | BIT(3)) : 0); + } + ++static int ov5640_fw_command(struct ov5640_dev *sensor, int command) ++{ ++ u8 fw_ack; ++ int i; ++ int ret; ++ ++ ret = ov5640_write_reg(sensor, OV5640_REG_FW_CMD_ACK, 0x01); ++ if(ret) ++ return ret; ++ ++ ret = ov5640_write_reg(sensor, OV5640_REG_FW_CMD_MAIN, command); ++ if(ret) ++ return ret; ++ ++ for (i = 0; i < 100; i++) { ++ ret = ov5640_read_reg(sensor, OV5640_REG_FW_CMD_ACK, &fw_ack); ++ if (ret) ++ return ret; ++ ++ if (fw_ack == 0){ ++ return ret; ++ } ++ ++ msleep(50); ++ } ++ return -ETIMEDOUT; ++} ++ ++ + /* + * Sensor Controls. + */ +@@ -2532,6 +2692,41 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, + return ret; + } + ++static int ov5640_set_ctrl_focus(struct ov5640_dev *sensor, int command) ++{ ++ struct i2c_client *client = sensor->i2c_client; ++ int ret; ++ ++ ret = ov5640_af_init(sensor); ++ if (ret) { ++ dev_err(&client->dev, "%s: no autofocus firmware loaded\n", ++ __func__); ++ return 0; ++ } ++ ++ if (command == OV5640_FW_CMD_RELEASE_FOCUS) { ++ dev_dbg(&client->dev, "%s: Releasing autofocus\n", ++ __func__); ++ return ov5640_fw_command(sensor, OV5640_FW_CMD_RELEASE_FOCUS); ++ } ++ ++ // Restart zone config ++ ret = ov5640_fw_command(sensor, OV5640_FW_CMD_ZONE_CONFIG); ++ if (ret) ++ return ret; ++ ++ // Set default focus zones ++ ret = ov5640_fw_command(sensor, OV5640_FW_CMD_DEFAULT_ZONES); ++ if (ret) ++ return ret; ++ ++ dev_dbg(&client->dev, "%s: Triggering autofocus\n", ++ __func__); ++ ++ // Start focussing ++ return ov5640_fw_command(sensor, command); ++} ++ + 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) + (BIT(2) | BIT(1)) : 0); + } + ++static int ov5640_get_af_status(struct ov5640_dev *sensor) ++{ ++ u8 fw_status; ++ int ret; ++ ++ ret = ov5640_read_reg(sensor, OV5640_REG_FW_STATUS, &fw_status); ++ if (ret) ++ return ret; ++ ++ switch (fw_status) { ++ case OV5640_FW_STATUS_S_FIRMWARE: ++ case OV5640_FW_STATUS_S_STARTUP: ++ return V4L2_AUTO_FOCUS_STATUS_FAILED; ++ break; ++ case OV5640_FW_STATUS_S_IDLE: ++ return V4L2_AUTO_FOCUS_STATUS_IDLE; ++ break; ++ case OV5640_FW_STATUS_S_FOCUSED: ++ return V4L2_AUTO_FOCUS_STATUS_REACHED; ++ break; ++ default: ++ return V4L2_AUTO_FOCUS_STATUS_BUSY; ++ break; ++ } ++} ++ + 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) + return val; + sensor->ctrls.exposure->val = val; + break; ++ case V4L2_CID_FOCUS_AUTO: ++ val = ov5640_get_af_status(sensor); ++ if (val < 0) ++ return val; ++ sensor->ctrls.af_status->val = val; ++ break; + } + + return 0; +@@ -2690,6 +2917,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; ++ case V4L2_CID_FOCUS_AUTO: ++ if (ctrl->val) ++ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_CONTINUOUS_FOCUS); ++ else ++ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_RELEASE_FOCUS); ++ break; ++ case V4L2_CID_AUTO_FOCUS_START: ++ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_TRIGGER_FOCUS); ++ break; ++ case V4L2_CID_AUTO_FOCUS_STOP: ++ ret = ov5640_set_ctrl_focus(sensor, OV5640_FW_CMD_RELEASE_FOCUS); ++ break; + 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) + ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, + 0, 1023, 1, 0); + ++ /* Autofocus */ ++ ctrls->focus_auto = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_AUTO, ++ 0, 1, 1, 0); ++ ctrls->af_start = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_FOCUS_START, ++ 0, 1, 1, 0); ++ ctrls->af_stop = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_FOCUS_STOP, ++ 0, 1, 1, 0); ++ ctrls->af_status = v4l2_ctrl_new_std(hdl, ops, ++ V4L2_CID_AUTO_FOCUS_STATUS, 0, ++ (V4L2_AUTO_FOCUS_STATUS_BUSY | ++ V4L2_AUTO_FOCUS_STATUS_REACHED | ++ V4L2_AUTO_FOCUS_STATUS_FAILED), ++ 0, V4L2_AUTO_FOCUS_STATUS_IDLE); ++ + 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) + 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); ++ v4l2_ctrl_cluster(4, &ctrls->focus_auto); + + sensor->sd.ctrl_handler = hdl; + return 0; +-- +2.25.4 + diff --git a/sys-kernel/pinephone-sources/files/panic-led.patch b/sys-kernel/pinephone-sources/files/panic-led.patch new file mode 100644 index 0000000..2bb4843 --- /dev/null +++ b/sys-kernel/pinephone-sources/files/panic-led.patch @@ -0,0 +1,12 @@ +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +index 1c555456b..05fab5d79 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +@@ -78,6 +78,7 @@ green { + }; + + led-2 { ++ linux,default-trigger = "panic"; + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&pio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */ diff --git a/sys-kernel/pinephone-sources/files/pp-keyboard.patch b/sys-kernel/pinephone-sources/files/pp-keyboard.patch deleted file mode 100644 index 690ee9f..0000000 --- a/sys-kernel/pinephone-sources/files/pp-keyboard.patch +++ /dev/null @@ -1,549 +0,0 @@ -From d1d849cae12db71aa81ceedaedc1b17a34790367 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Sat, 19 Jun 2021 18:36:05 -0500 -Subject: [PATCH] Input: kb151 - Add a driver for the KB151 keyboard - -This keyboard is found in the official Pine64 PinePhone keyboard case. -It is connected over I2C and runs a libre firmware. - -Signed-off-by: Samuel Holland ---- - .../dts/allwinner/sun50i-a64-pinephone.dtsi | 64 +++++ - drivers/input/keyboard/Kconfig | 10 + - drivers/input/keyboard/Makefile | 1 + - drivers/input/keyboard/kb151.c | 246 ++++++++++++++++++ - 4 files changed, 321 insertions(+) - create mode 100644 drivers/input/keyboard/kb151.c - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi -index 4ede9fe66020c..0bdc6eceec609 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi -@@ -551,6 +551,70 @@ - /* Connected to pogo pins (external spring based pinheader for user addons) */ - &i2c2 { - status = "okay"; -+ -+ keyboard@15 { -+ compatible = "pine64,kb151"; -+ reg = <0x15>; -+ interrupt-parent = <&r_pio>; -+ interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */ -+ keypad,num-rows = <6>; -+ keypad,num-columns = <12>; -+ linux,keymap = ; -+ wakeup-source; -+ }; - }; - - &i2s2 { -diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig -index 40a070a2e7f5b..0259e9133f469 100644 ---- a/drivers/input/keyboard/Kconfig -+++ b/drivers/input/keyboard/Kconfig -@@ -353,6 +353,16 @@ config KEYBOARD_HP7XX - To compile this driver as a module, choose M here: the - module will be called jornada720_kbd. - -+config KEYBOARD_KB151 -+ tristate "Pine64 KB151 Keyboard" -+ depends on I2C -+ select CRC8 -+ select INPUT_MATRIXKMAP -+ help -+ Say Y here to enable support for the KB151 keyboard used in the -+ Pine64 PinePhone keyboard case. This driver supports the FLOSS -+ firmware available at https://megous.com/git/pinephone-keyboard/ -+ - config KEYBOARD_LM8323 - tristate "LM8323 keypad chip" - depends on I2C -diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile -index 1d689fdd5c00f..87fda7b961913 100644 ---- a/drivers/input/keyboard/Makefile -+++ b/drivers/input/keyboard/Makefile -@@ -33,6 +33,7 @@ obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o - obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o - obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o - obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o -+obj-$(CONFIG_KEYBOARD_KB151) += kb151.o - obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o - obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o - obj-$(CONFIG_KEYBOARD_LM8333) += lm8333.o -diff --git a/drivers/input/keyboard/kb151.c b/drivers/input/keyboard/kb151.c -new file mode 100644 -index 0000000000000..595275d4f9d96 ---- /dev/null -+++ b/drivers/input/keyboard/kb151.c -@@ -0,0 +1,246 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+// -+// Copyright (C) 2021 Samuel Holland -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define KB151_CRC8_POLYNOMIAL 0x07 -+ -+#define KB151_DEVICE_ID_HI 0x00 -+#define KB151_DEVICE_ID_HI_VALUE 0x4b -+#define KB151_DEVICE_ID_LO 0x01 -+#define KB151_DEVICE_ID_LO_VALUE 0x42 -+#define KB151_FW_REVISION 0x02 -+#define KB151_FW_FEATURES 0x03 -+#define KB151_MATRIX_SIZE 0x06 -+#define KB151_SCAN_CRC 0x07 -+#define KB151_SCAN_DATA 0x08 -+#define KB151_SYS_CONFIG 0x20 -+#define KB151_SYS_CONFIG_DISABLE_SCAN BIT(0) -+ -+struct kb151 { -+ struct input_dev *input; -+ u8 crc_table[CRC8_TABLE_SIZE]; -+ u8 row_shift; -+ u8 rows; -+ u8 cols; -+ u8 buf_swap; -+ u8 buf[]; -+}; -+ -+static void kb151_update(struct i2c_client *client) -+{ -+ struct kb151 *kb151 = i2c_get_clientdata(client); -+ unsigned short *keymap = kb151->input->keycode; -+ struct device *dev = &client->dev; -+ size_t buf_len = kb151->cols + 1; -+ u8 *old_buf = kb151->buf; -+ u8 *new_buf = kb151->buf; -+ int col, crc, ret, row; -+ -+ if (kb151->buf_swap) -+ old_buf += buf_len; -+ else -+ new_buf += buf_len; -+ -+ ret = i2c_smbus_read_i2c_block_data(client, KB151_SCAN_CRC, -+ buf_len, new_buf); -+ if (ret != buf_len) { -+ dev_err(dev, "Failed to read scan data: %d\n", ret); -+ return; -+ } -+ -+ dev_info(dev, "%02x | %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", -+ new_buf[0], new_buf[1], new_buf[2], new_buf[3], new_buf[4], new_buf[5], -+ new_buf[6], new_buf[7], new_buf[8], new_buf[9], new_buf[10], new_buf[11], -+ new_buf[12]); -+ crc = crc8(kb151->crc_table, new_buf + 1, kb151->cols, CRC8_INIT_VALUE); -+ if (crc != new_buf[0]) { -+ dev_err(dev, "Bad scan data (%02x != %02x)\n", -+ crc, new_buf[0]); -+ return; -+ } -+ dev_info(dev, "Good scan data (%02x == %02x)\n", -+ crc, new_buf[0]); -+ -+ for (col = 0; col < kb151->cols; ++col) { -+ u8 old = *(++old_buf); -+ u8 new = *(++new_buf); -+ u8 changed = old ^ new; -+ -+ for (row = 0; row < kb151->rows; ++row) { -+ int code = MATRIX_SCAN_CODE(row, col, kb151->row_shift); -+ u8 pressed = new & BIT(row); -+ -+ if (!(changed & BIT(row))) -+ continue; -+ -+ dev_dbg(&client->dev, "row %u col %u %sed\n", -+ row, col, pressed ? "press" : "releas"); -+ input_report_key(kb151->input, keymap[code], pressed); -+ } -+ } -+ input_sync(kb151->input); -+ -+ kb151->buf_swap = !kb151->buf_swap; -+} -+ -+static int kb151_open(struct input_dev *input) -+{ -+ struct i2c_client *client = input_get_drvdata(input); -+ struct device *dev = &client->dev; -+ int ret, val; -+ -+ ret = i2c_smbus_read_byte_data(client, KB151_SYS_CONFIG); -+ if (ret < 0) { -+ dev_err(dev, "Failed to read config: %d\n", ret); -+ return ret; -+ } -+ -+ val = ret & ~KB151_SYS_CONFIG_DISABLE_SCAN; -+ ret = i2c_smbus_write_byte_data(client, KB151_SYS_CONFIG, val); -+ if (ret) { -+ dev_err(dev, "Failed to write config: %d\n", ret); -+ return ret; -+ } -+ -+ kb151_update(client); -+ -+ enable_irq(client->irq); -+ -+ return 0; -+} -+ -+static void kb151_close(struct input_dev *input) -+{ -+ struct i2c_client *client = input_get_drvdata(input); -+ struct device *dev = &client->dev; -+ int ret, val; -+ -+ disable_irq(client->irq); -+ -+ ret = i2c_smbus_read_byte_data(client, KB151_SYS_CONFIG); -+ if (ret < 0) { -+ dev_err(dev, "Failed to read config: %d\n", ret); -+ return; -+ } -+ -+ val = ret | KB151_SYS_CONFIG_DISABLE_SCAN; -+ ret = i2c_smbus_write_byte_data(client, KB151_SYS_CONFIG, val); -+ if (ret) { -+ dev_err(dev, "Failed to write config: %d\n", ret); -+ } -+} -+ -+static irqreturn_t kb151_irq_thread(int irq, void *data) -+{ -+ struct i2c_client *client = data; -+ -+ kb151_update(client); -+ -+ return IRQ_HANDLED; -+} -+ -+static int kb151_probe(struct i2c_client *client) -+{ -+ struct device *dev = &client->dev; -+ u8 info[KB151_MATRIX_SIZE + 1]; -+ unsigned int kb_rows, kb_cols; -+ unsigned int rows, cols; -+ struct kb151 *kb151; -+ int ret; -+ -+ ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info); -+ if (ret != sizeof(info)) -+ return ret; -+ -+ if (info[KB151_DEVICE_ID_HI] != KB151_DEVICE_ID_HI_VALUE || -+ info[KB151_DEVICE_ID_LO] != KB151_DEVICE_ID_LO_VALUE) -+ return -ENODEV; -+ -+ dev_info(dev, "Found KB151 with firmware %d.%d (features=%#x)\n", -+ info[KB151_FW_REVISION] >> 4, -+ info[KB151_FW_REVISION] & 0xf, -+ info[KB151_FW_FEATURES]); -+ -+ ret = matrix_keypad_parse_properties(dev, &rows, &cols); -+ if (ret) -+ return ret; -+ -+ kb_rows = info[KB151_MATRIX_SIZE] & 0xf; -+ kb_cols = info[KB151_MATRIX_SIZE] >> 4; -+ if (rows > kb_rows || cols != kb_cols) { -+ dev_err(dev, "Keyboard matrix is %ux%u, but key map is %ux%u\n", -+ kb_rows, kb_cols, rows, cols); -+ return -EINVAL; -+ } -+ -+ /* Allocate two buffers, and include space for the CRC. */ -+ kb151 = devm_kzalloc(dev, struct_size(kb151, buf, 2 * (cols + 1)), GFP_KERNEL); -+ if (!kb151) -+ return -ENOMEM; -+ -+ i2c_set_clientdata(client, kb151); -+ -+ crc8_populate_msb(kb151->crc_table, KB151_CRC8_POLYNOMIAL); -+ -+ kb151->row_shift = get_count_order(cols); -+ kb151->rows = rows; -+ kb151->cols = cols; -+ -+ kb151->input = devm_input_allocate_device(dev); -+ if (!kb151->input) -+ return -ENOMEM; -+ -+ input_set_drvdata(kb151->input, client); -+ -+ kb151->input->name = client->name; -+ kb151->input->phys = "kb151/input0"; -+ kb151->input->id.bustype = BUS_I2C; -+ kb151->input->open = kb151_open; -+ kb151->input->close = kb151_close; -+ -+ __set_bit(EV_REP, kb151->input->evbit); -+ -+ ret = matrix_keypad_build_keymap(NULL, NULL, rows, cols, -+ NULL, kb151->input); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to build keymap\n"); -+ -+ ret = devm_request_threaded_irq(dev, client->irq, -+ NULL, kb151_irq_thread, -+ IRQF_ONESHOT | IRQF_NO_AUTOEN, -+ client->name, client); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to request IRQ\n"); -+ -+ ret = input_register_device(kb151->input); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to register input\n"); -+ -+ return 0; -+} -+ -+static const struct of_device_id kb151_of_match[] = { -+ { .compatible = "pine64,kb151" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, kb151_of_match); -+ -+static struct i2c_driver kb151_driver = { -+ .probe_new = kb151_probe, -+ .driver = { -+ .name = "kb151", -+ .of_match_table = kb151_of_match, -+ }, -+}; -+module_i2c_driver(kb151_driver); -+ -+MODULE_AUTHOR("Samuel Holland "); -+MODULE_DESCRIPTION("Pine64 KB151 keyboard driver"); -+MODULE_LICENSE("GPL"); -From 2423aac2d6f5db55da99e11fd799ee66fe6f54c6 Mon Sep 17 00:00:00 2001 -From: Samuel Holland -Date: Mon, 9 Aug 2021 19:30:18 -0500 -Subject: [PATCH] Input: kb151 - Add support for the FN layer - -Signed-off-by: Samuel Holland ---- - .../dts/allwinner/sun50i-a64-pinephone.dtsi | 34 +++++++++++++++++-- - drivers/input/keyboard/kb151.c | 33 ++++++++++-------- - 2 files changed, 51 insertions(+), 16 deletions(-) - -diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi -index 0bdc6eceec609..68f5730cf164c 100644 ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi -@@ -557,7 +557,7 @@ - reg = <0x15>; - interrupt-parent = <&r_pio>; - interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */ -- keypad,num-rows = <6>; -+ keypad,num-rows = <12>; - keypad,num-columns = <12>; - linux,keymap = ; -+ MATRIX_KEY(5, 5, KEY_RIGHTALT) -+ -+ /* FN layer */ -+ MATRIX_KEY(6, 1, KEY_BACKSLASH) -+ MATRIX_KEY(6, 2, KEY_BACKSLASH) -+ MATRIX_KEY(6, 3, KEY_DOLLAR) -+ MATRIX_KEY(6, 4, KEY_EURO) -+ MATRIX_KEY(6, 5, KEY_GRAVE) -+ MATRIX_KEY(6, 6, KEY_GRAVE) -+ MATRIX_KEY(6, 7, KEY_MINUS) -+ MATRIX_KEY(6, 8, KEY_EQUAL) -+ MATRIX_KEY(6, 9, KEY_MINUS) -+ MATRIX_KEY(6, 10, KEY_EQUAL) -+ MATRIX_KEY(6, 11, KEY_DELETE) -+ -+ MATRIX_KEY(8, 0, KEY_SYSRQ) -+ MATRIX_KEY(8, 10, KEY_INSERT) -+ -+ MATRIX_KEY(9, 0, KEY_LEFTSHIFT) -+ MATRIX_KEY(9, 8, KEY_HOME) -+ MATRIX_KEY(9, 9, KEY_UP) -+ MATRIX_KEY(9, 10, KEY_END) -+ -+ MATRIX_KEY(10, 1, KEY_LEFTCTRL) -+ MATRIX_KEY(10, 6, KEY_LEFT) -+ MATRIX_KEY(10, 8, KEY_RIGHT) -+ MATRIX_KEY(10, 9, KEY_DOWN) -+ -+ MATRIX_KEY(11, 2, KEY_FN) -+ MATRIX_KEY(11, 3, KEY_LEFTALT) -+ MATRIX_KEY(11, 5, KEY_RIGHTALT)>; - wakeup-source; - }; - }; -diff --git a/drivers/input/keyboard/kb151.c b/drivers/input/keyboard/kb151.c -index 595275d4f9d96..bb6250efe9341 100644 ---- a/drivers/input/keyboard/kb151.c -+++ b/drivers/input/keyboard/kb151.c -@@ -29,6 +29,7 @@ struct kb151 { - u8 row_shift; - u8 rows; - u8 cols; -+ u8 fn_state; - u8 buf_swap; - u8 buf[]; - }; -@@ -55,7 +56,7 @@ static void kb151_update(struct i2c_client *client) - return; - } - -- dev_info(dev, "%02x | %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", -+ dev_dbg(dev, "%02x | %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - new_buf[0], new_buf[1], new_buf[2], new_buf[3], new_buf[4], new_buf[5], - new_buf[6], new_buf[7], new_buf[8], new_buf[9], new_buf[10], new_buf[11], - new_buf[12]); -@@ -65,8 +66,6 @@ static void kb151_update(struct i2c_client *client) - crc, new_buf[0]); - return; - } -- dev_info(dev, "Good scan data (%02x == %02x)\n", -- crc, new_buf[0]); - - for (col = 0; col < kb151->cols; ++col) { - u8 old = *(++old_buf); -@@ -74,14 +73,20 @@ static void kb151_update(struct i2c_client *client) - u8 changed = old ^ new; - - for (row = 0; row < kb151->rows; ++row) { -- int code = MATRIX_SCAN_CODE(row, col, kb151->row_shift); - u8 pressed = new & BIT(row); -+ u8 map_row = row + (kb151->fn_state ? kb151->rows : 0); -+ int code = MATRIX_SCAN_CODE(map_row, col, kb151->row_shift); - - if (!(changed & BIT(row))) - continue; - - dev_dbg(&client->dev, "row %u col %u %sed\n", -- row, col, pressed ? "press" : "releas"); -+ map_row, col, pressed ? "press" : "releas"); -+ if (keymap[code] == KEY_FN) { -+ dev_dbg(&client->dev, "FN is now %s\n", -+ pressed ? "pressed" : "released"); -+ kb151->fn_state = pressed; -+ } else - input_report_key(kb151->input, keymap[code], pressed); - } - } -@@ -151,7 +156,7 @@ static int kb151_probe(struct i2c_client *client) - struct device *dev = &client->dev; - u8 info[KB151_MATRIX_SIZE + 1]; - unsigned int kb_rows, kb_cols; -- unsigned int rows, cols; -+ unsigned int map_rows, map_cols; - struct kb151 *kb151; - int ret; - -@@ -168,20 +173,20 @@ static int kb151_probe(struct i2c_client *client) - info[KB151_FW_REVISION] & 0xf, - info[KB151_FW_FEATURES]); - -- ret = matrix_keypad_parse_properties(dev, &rows, &cols); -+ ret = matrix_keypad_parse_properties(dev, &map_rows, &map_cols); - if (ret) - return ret; - - kb_rows = info[KB151_MATRIX_SIZE] & 0xf; - kb_cols = info[KB151_MATRIX_SIZE] >> 4; -- if (rows > kb_rows || cols != kb_cols) { -+ if (map_rows != 2 * kb_rows || map_cols != kb_cols) { - dev_err(dev, "Keyboard matrix is %ux%u, but key map is %ux%u\n", -- kb_rows, kb_cols, rows, cols); -+ kb_rows, kb_cols, map_rows, map_cols); - return -EINVAL; - } - - /* Allocate two buffers, and include space for the CRC. */ -- kb151 = devm_kzalloc(dev, struct_size(kb151, buf, 2 * (cols + 1)), GFP_KERNEL); -+ kb151 = devm_kzalloc(dev, struct_size(kb151, buf, 2 * (kb_cols + 1)), GFP_KERNEL); - if (!kb151) - return -ENOMEM; - -@@ -189,9 +194,9 @@ static int kb151_probe(struct i2c_client *client) - - crc8_populate_msb(kb151->crc_table, KB151_CRC8_POLYNOMIAL); - -- kb151->row_shift = get_count_order(cols); -- kb151->rows = rows; -- kb151->cols = cols; -+ kb151->row_shift = get_count_order(kb_cols); -+ kb151->rows = kb_rows; -+ kb151->cols = kb_cols; - - kb151->input = devm_input_allocate_device(dev); - if (!kb151->input) -@@ -207,7 +212,7 @@ static int kb151_probe(struct i2c_client *client) - - __set_bit(EV_REP, kb151->input->evbit); - -- ret = matrix_keypad_build_keymap(NULL, NULL, rows, cols, -+ ret = matrix_keypad_build_keymap(NULL, NULL, map_rows, map_cols, - NULL, kb151->input); - if (ret) - return dev_err_probe(dev, ret, "Failed to build keymap\n"); diff --git a/sys-kernel/pinephone-sources/pinephone-sources-5.16.3.ebuild b/sys-kernel/pinephone-sources/pinephone-sources-5.16.3.ebuild index 2a07047..056fd2a 100644 --- a/sys-kernel/pinephone-sources/pinephone-sources-5.16.3.ebuild +++ b/sys-kernel/pinephone-sources/pinephone-sources-5.16.3.ebuild @@ -25,8 +25,6 @@ SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI} ${MEGI_PATCH_URI} -> all-${ PATCHES=( #Megi patch set ${DISTDIR}/all-${PV}.patch - # Pinephone Keyboard - ${FILESDIR}/pp-keyboard.patch # Drop Megi's Modem-Power "${FILESDIR}"/dts-pinephone-drop-modem-power-node.patch # Implement Martijn's improvements for the cameras