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"; }; +&dsi0{ + 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 39747ff..c852640 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include "skeleton64.dtsi" 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 e0bbaa27..4d00308c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -180,3 +180,5 @@ obj-$(CONFIG_RK_NAND) += rk_nand/ obj-$(CONFIG_RK_HEADSET) += headset_observe/ obj-$(CONFIG_RK_FLASH) += rkflash/ obj-y += rk_nand/ + +obj-y += tinkerboard/ \ No newline at end of file diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b58f922..a6a30ca 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -59,5 +59,6 @@ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o +obj-$(CONFIG_TINKER_MCU) += tinker_mcu.o obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o obj-$(CONFIG_USB_CAM_GPIO) += usb_cam_gpio.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