From 8bf6e833a040c696bba37b6fb04db37d8123b06e Mon Sep 17 00:00:00 2001 From: Tonymac32 Date: Sun, 5 Nov 2017 01:32:44 -0400 Subject: [PATCH] Tinker Board support RPI 7" DSI Display Use device tree instead of platform machine definition, which had been preventing integrating support. Display and touchscreen support both functional --- .../145_rockchip_tinker_touchscreen.patch | 2744 +++++++++++++++++ .../146_rockchip_tinker_dsi.patch | 234 ++ 2 files changed, 2978 insertions(+) create mode 100644 patch/kernel/rockchip-default/145_rockchip_tinker_touchscreen.patch create mode 100644 patch/kernel/rockchip-default/146_rockchip_tinker_dsi.patch diff --git a/patch/kernel/rockchip-default/145_rockchip_tinker_touchscreen.patch b/patch/kernel/rockchip-default/145_rockchip_tinker_touchscreen.patch new file mode 100644 index 0000000000..cd26a8a6f6 --- /dev/null +++ b/patch/kernel/rockchip-default/145_rockchip_tinker_touchscreen.patch @@ -0,0 +1,2744 @@ +diff --git a/arch/arm/boot/dts/rk3288-miniarm.dts b/arch/arm/boot/dts/rk3288-miniarm.dts +index d0c42be..3d7e74e 100644 +--- a/arch/arm/boot/dts/rk3288-miniarm.dts ++++ b/arch/arm/boot/dts/rk3288-miniarm.dts +@@ -223,6 +223,15 @@ + status = "ok"; + }; + ++&mipi_dsi{ ++ status = "okay"; ++ mipi_panel: mipi-panel { ++ compatible ="asus,tc358762"; ++ reg = <0>; ++ status = "okay"; ++ }; ++}; ++ + &gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +@@ -449,6 +458,16 @@ + + &i2c3 { + status = "okay"; ++ ++ tinker_ft5406:tinker_ft5406@38 { ++ compatible = "tinker_ft5406"; ++ reg = <0x38>; ++ }; ++ ++ tinker_mcu:tinker_mcu@45 { ++ compatible = "tinker_mcu"; ++ reg = <0x45>; ++ }; + }; + + &i2c4 { +diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi +index 7a597ee..85aac90 100644 +--- a/arch/arm/boot/dts/rk3288.dtsi ++++ b/arch/arm/boot/dts/rk3288.dtsi +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + #include "skeleton.dtsi" + + / { +@@ -1171,7 +1172,7 @@ gpu_thermal: gpu_thermal { + mipi_dsi: mipi@ff960000 { + compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; + reg = <0xff960000 0x4000>; +- interrupts = ; ++ interrupts = ; + clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>; + clock-names = "ref", "pclk"; + rockchip,grf = <&grf>; +diff --git a/drivers/Kconfig b/drivers/Kconfig +index a1a41f2..5d85e38 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -204,4 +204,6 @@ source "drivers/rk_nand/Kconfig" + + source "drivers/headset_observe/Kconfig" + ++source "drivers/tinkerboard/Kconfig" ++ + endmenu +diff --git a/drivers/Makefile b/drivers/Makefile +index eb16de1..dad01b6 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -176,3 +176,5 @@ obj-$(CONFIG_NVMEM) += nvmem/ + obj-$(CONFIG_FPGA) += fpga/ + obj-$(CONFIG_RK_NAND) += rk_nand/ + obj-$(CONFIG_RK_HEADSET) += headset_observe/ ++ ++obj-y += tinkerboard/ +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index 4868840..cf45d58 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -57,4 +57,5 @@ obj-$(CONFIG_GENWQE) += genwqe/ + obj-$(CONFIG_ECHO) += echo/ + obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o + obj-$(CONFIG_CXL_BASE) += cxl/ +-obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o ++obj-$(CONFIG_UID_CPUTIME) += uid_cputime.o ++obj-$(CONFIG_TINKER_MCU) += tinker_mcu.o +diff --git a/drivers/misc/tinker_mcu.c b/drivers/misc/tinker_mcu.c +new file mode 100644 +index 0000000..e1929ea +--- /dev/null ++++ b/drivers/misc/tinker_mcu.c +@@ -0,0 +1,232 @@ ++/* ++ * ++ * Tinker board Touchscreen MCU driver. ++ * ++ * Copyright (c) 2016 ASUSTek Computer Inc. ++ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tinker_mcu.h" ++ ++static struct tinker_mcu_data *g_mcu_data; ++static int connected = 0; ++ ++static int is_hex(char num) ++{ ++ //0-9, a-f, A-F ++ if ((47 < num && num < 58) || (64 < num && num < 71) || (96 < num && num < 103)) ++ return 1; ++ return 0; ++} ++ ++static int string_to_byte(const char *source, unsigned char *destination, int size) ++{ ++ int i = 0, counter = 0; ++ char c[3] = {0}; ++ unsigned char bytes; ++ ++ if (size%2 == 1) ++ return -EINVAL; ++ ++ for(i = 0; i < size; i++){ ++ if(!is_hex(source[i])) { ++ return -EINVAL; ++ } ++ if(0 == i%2){ ++ c[0] = source[i]; ++ c[1] = source[i+1]; ++ sscanf(c, "%hhx", &bytes); ++ destination[counter] = bytes; ++ counter++; ++ } ++ } ++ return 0; ++} ++ ++static int send_cmds(struct i2c_client *client, const char *buf) ++{ ++ int ret, size = strlen(buf); ++ unsigned char byte_cmd[size/2]; ++ ++ if ((size%2) != 0) { ++ LOG_ERR("size should be even\n"); ++ return -EINVAL; ++ } ++ ++ LOG_INFO("%s\n", buf); ++ ++ string_to_byte(buf, byte_cmd, size); ++ ++ ret = i2c_master_send(client, byte_cmd, size/2); ++ if (ret <= 0) { ++ LOG_ERR("send command failed, ret = %d\n", ret); ++ return ret!=0 ? ret : -ECOMM; ++ } ++ msleep(20); ++ return 0; ++} ++ ++static int recv_cmds(struct i2c_client *client, char *buf, int size) ++{ ++ int ret; ++ ++ ret = i2c_master_recv(client, buf, size); ++ if (ret <= 0) { ++ LOG_ERR("receive commands failed, %d\n", ret); ++ return ret!=0 ? ret : -ECOMM; ++ } ++ msleep(20); ++ return 0; ++} ++ ++static int init_cmd_check(struct tinker_mcu_data *mcu_data) ++{ ++ int ret; ++ char recv_buf[1] = {0}; ++ ++ ret = send_cmds(mcu_data->client, "80"); ++ if (ret < 0) ++ goto error; ++ ++ recv_cmds(mcu_data->client, recv_buf, 1); ++ if (ret < 0) ++ goto error; ++ ++ LOG_INFO("recv_cmds: 0x%X\n", recv_buf[0]); ++ if (recv_buf[0] != 0xC3) { ++ LOG_ERR("read wrong info\n"); ++ ret = -EINVAL; ++ goto error; ++ ++ } ++ return 0; ++ ++error: ++ return ret; ++} ++ ++int tinker_mcu_screen_power_up(void) ++{ ++ if (!connected) ++ return -ENODEV; ++ ++ LOG_INFO("\n"); ++ send_cmds(g_mcu_data->client, "8500"); ++ msleep(800); ++ send_cmds(g_mcu_data->client, "8501"); ++ send_cmds(g_mcu_data->client, "8104"); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(tinker_mcu_screen_power_up); ++ ++int tinker_mcu_set_bright(int bright) ++{ ++ unsigned char cmd[2]; ++ int ret; ++ ++ if (!connected) ++ return -ENODEV; ++ ++ if (bright > 0xff || bright < 0) ++ return -EINVAL; ++ ++ LOG_INFO("bright = 0x%x\n", bright); ++ ++ cmd[0] = 0x86; ++ cmd[1] = bright; ++ ++ ret = i2c_master_send(g_mcu_data->client, cmd, 2); ++ if (ret <= 0) { ++ LOG_ERR("send command failed, ret = %d\n", ret); ++ return ret != 0 ? ret : -ECOMM; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(tinker_mcu_set_bright); ++ ++int tinker_mcu_is_connected(void) ++{ ++ return connected; ++} ++EXPORT_SYMBOL_GPL(tinker_mcu_is_connected); ++ ++static int tinker_mcu_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct tinker_mcu_data *mcu_data; ++ int ret; ++ ++ LOG_INFO("address = 0x%x\n", client->addr); ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ LOG_ERR("I2C check functionality failed\n"); ++ return -ENODEV; ++ } ++ ++ mcu_data = kzalloc(sizeof(struct tinker_mcu_data), GFP_KERNEL); ++ if (mcu_data == NULL) { ++ LOG_ERR("no memory for device\n"); ++ return -ENOMEM; ++ } ++ ++ mcu_data->client = client; ++ i2c_set_clientdata(client, mcu_data); ++ g_mcu_data = mcu_data; ++ ++ ret = init_cmd_check(mcu_data); ++ if (ret < 0) { ++ LOG_ERR("init_cmd_check failed, %d\n", ret); ++ goto error; ++ } ++ connected = 1; ++ ++ return 0; ++ ++error: ++ kfree(mcu_data); ++ return ret; ++} ++ ++static int tinker_mcu_remove(struct i2c_client *client) ++{ ++ struct tinker_mcu_data *mcu_data = i2c_get_clientdata(client); ++ connected = 0; ++ kfree(mcu_data); ++ return 0; ++} ++ ++static const struct i2c_device_id tinker_mcu_id[] = { ++ {"tinker_mcu", 0}, ++ {}, ++}; ++ ++static struct i2c_driver tinker_mcu_driver = { ++ .driver = { ++ .name = "tinker_mcu", ++ }, ++ .probe = tinker_mcu_probe, ++ .remove = tinker_mcu_remove, ++ .id_table = tinker_mcu_id, ++}; ++module_i2c_driver(tinker_mcu_driver); ++ ++MODULE_DESCRIPTION("Tinker Board TouchScreen MCU driver"); ++MODULE_LICENSE("GPL v2"); +\ No newline at end of file +diff --git a/drivers/misc/tinker_mcu.h b/drivers/misc/tinker_mcu.h +new file mode 100644 +index 0000000..2a96ac1 +--- /dev/null ++++ b/drivers/misc/tinker_mcu.h +@@ -0,0 +1,14 @@ ++#ifndef _TINKER_MCU_H_ ++#define _TINKER_MCU_H_ ++ ++#define LOG_INFO(fmt,arg...) pr_info("tinker-mcu: %s: "fmt, __func__, ##arg); ++#define LOG_ERR(fmt,arg...) pr_err("tinker-mcu: %s: "fmt, __func__, ##arg); ++ ++#define MAX_I2C_LEN 255 ++ ++struct tinker_mcu_data { ++ struct device *dev; ++ struct i2c_client *client; ++}; ++ ++#endif +\ No newline at end of file +diff --git a/drivers/tinkerboard/Kconfig b/drivers/tinkerboard/Kconfig +new file mode 100644 +index 0000000..660b55b +--- /dev/null ++++ b/drivers/tinkerboard/Kconfig +@@ -0,0 +1 @@ ++source "drivers/tinkerboard/dsi/Kconfig" +\ No newline at end of file +diff --git a/drivers/tinkerboard/Makefile b/drivers/tinkerboard/Makefile +new file mode 100644 +index 0000000..3288d03 +--- /dev/null ++++ b/drivers/tinkerboard/Makefile +@@ -0,0 +1 @@ ++obj-y += dsi/ +\ No newline at end of file +diff --git a/drivers/tinkerboard/dsi/Kconfig b/drivers/tinkerboard/dsi/Kconfig +new file mode 100644 +index 0000000..03027f5 +--- /dev/null ++++ b/drivers/tinkerboard/dsi/Kconfig +@@ -0,0 +1,33 @@ ++config DRM_PANEL_TOSHIBA_TC358762 ++ tristate "support for toshiba tc358762" ++ depends on OF && I2C ++ depends on BACKLIGHT_CLASS_DEVICE ++ select VIDEOMODE_HELPERS ++ help ++ Say Y here if you want to enable support for toshiba tc358762 bridge. ++ To compile this driver as a module, choose M here. ++ ++config ROCKCHIP_DW_MIPI_DSI2 ++ tristate "Rockchip specific extensions for Synopsys DW MIPI DSI" ++ depends on DRM_ROCKCHIP ++ depends on !ROCKCHIP_DW_MIPI_DSI ++ select DRM_MIPI_DSI ++ help ++ This selects support for Rockchip SoC specific extensions ++ for the Synopsys DesignWare HDMI driver. If you want to ++ enable MIPI DSI on RK3288 based SoC, you should selet this ++ option. ++ ++config TINKER_MCU ++ tristate "tinker mcu" ++ default y ++ depends on I2C ++ help ++ Control the power of touch screen for tinker board. ++ ++config TOUCHSCREEN_TINKER_FT5406 ++ tristate "tinker ft5406" ++ default y ++ depends on I2C ++ help ++Control ft5406 touch ic. +\ No newline at end of file +diff --git a/drivers/tinkerboard/dsi/Makefile b/drivers/tinkerboard/dsi/Makefile +new file mode 100644 +index 0000000..378ebf5 +--- /dev/null ++++ b/drivers/tinkerboard/dsi/Makefile +@@ -0,0 +1,4 @@ ++obj-$(CONFIG_DRM_PANEL_TOSHIBA_TC358762) += panel-toshiba-tc358762.o ++obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI2) += dw-mipi-dsi.o ++#obj-$(CONFIG_TINKER_MCU) += tinker_mcu.o ++obj-$(CONFIG_TOUCHSCREEN_TINKER_FT5406) += tinker_ft5406.o +\ No newline at end of file +diff --git a/drivers/tinkerboard/dsi/dw-mipi-dsi.c b/drivers/tinkerboard/dsi/dw-mipi-dsi.c +new file mode 100644 +index 0000000..c67786d +--- /dev/null ++++ b/drivers/tinkerboard/dsi/dw-mipi-dsi.c +@@ -0,0 +1,1295 @@ ++/* ++ * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include