build/patch/kernel/archive/rockchip64-4.4/check/0008-add-mcu-driver-for-rockpi-lcd-module.patch

315 lines
7.3 KiB
Diff
Raw Normal View History

From e791d8951d749bcfddd9741c730fed4cafb0f38e Mon Sep 17 00:00:00 2001
From: brian <brian@vamrs.com>
Date: Tue, 30 Oct 2018 11:18:48 +0800
Subject: [PATCH 08/97] add mcu driver for rockpi lcd module
Change-Id: I4d9eb75bc69bb59ffe2b7b110431c9ceab2cb3b8
---
arch/arm64/configs/rockchip_linux_defconfig | 1 +
drivers/misc/Kconfig | 7 +
drivers/misc/Makefile | 1 +
drivers/misc/rockpi_mcu.c | 242 ++++++++++++++++++++
drivers/misc/rockpi_mcu.h | 14 ++
5 files changed, 265 insertions(+)
create mode 100644 drivers/misc/rockpi_mcu.c
create mode 100644 drivers/misc/rockpi_mcu.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 77fa126eb1f2..eec5802fd989 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -564,6 +564,13 @@ config GPIO_DET
help
Enable this driver will support gpio detection.
+config ROCKPI_MCU
+ tristate "rockpi mcu"
+ default y
+ depends on I2C
+ help
+ Control the power of touch screen for rockpi board.
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b58f922dd5a0..059722165095 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -61,3 +61,4 @@ obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o
obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
obj-$(CONFIG_USB_CAM_GPIO) += usb_cam_gpio.o
+obj-$(CONFIG_ROCKPI_MCU) += rockpi_mcu.o
diff --git a/drivers/misc/rockpi_mcu.c b/drivers/misc/rockpi_mcu.c
new file mode 100644
index 000000000000..38e7af802119
--- /dev/null
+++ b/drivers/misc/rockpi_mcu.c
@@ -0,0 +1,242 @@
+/*
+ *
+ * Rockpi 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 <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include "rockpi_mcu.h"
+
+static struct rockpi_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);
+ printk("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 rockpi_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] != 0xDE && recv_buf[0] != 0xC3) {
+ LOG_ERR("read wrong info\n");
+ ret = -EINVAL;
+ goto error;
+
+ }
+ return 0;
+
+error:
+ return ret;
+}
+
+int rockpi_mcu_screen_power_up(void)
+{
+ int res = 0;
+ if (!connected)
+ return -ENODEV;
+
+ LOG_INFO("\n");
+
+ res = send_cmds(g_mcu_data->client, "8500");
+ if(res < 0)
+ printk("send 8500 failed\n");
+ msleep(800);
+ res = send_cmds(g_mcu_data->client, "8501");
+ if(res < 0)
+ printk("send 8501 failed\n");
+ msleep(800);
+ res = send_cmds(g_mcu_data->client, "8104");
+ if(res < 0)
+ printk("send 8104 failed\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rockpi_mcu_screen_power_up);
+
+int rockpi_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(rockpi_mcu_set_bright);
+
+int rockpi_mcu_is_connected(void)
+{
+ return connected;
+}
+EXPORT_SYMBOL_GPL(rockpi_mcu_is_connected);
+
+static int rockpi_mcu_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct rockpi_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 rockpi_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 rockpi_mcu_remove(struct i2c_client *client)
+{
+ struct rockpi_mcu_data *mcu_data = i2c_get_clientdata(client);
+ connected = 0;
+ kfree(mcu_data);
+ return 0;
+}
+
+static const struct i2c_device_id rockpi_mcu_id[] = {
+ {"rockpi_mcu", 0},
+ {},
+};
+
+static struct i2c_driver rockpi_mcu_driver = {
+ .driver = {
+ .name = "rockpi_mcu",
+ },
+ .probe = rockpi_mcu_probe,
+ .remove = rockpi_mcu_remove,
+ .id_table = rockpi_mcu_id,
+};
+module_i2c_driver(rockpi_mcu_driver);
+
+MODULE_DESCRIPTION("rockpi Board TouchScreen MCU driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/rockpi_mcu.h b/drivers/misc/rockpi_mcu.h
new file mode 100644
index 000000000000..5be872fa3b5d
--- /dev/null
+++ b/drivers/misc/rockpi_mcu.h
@@ -0,0 +1,14 @@
+#ifndef _ROCKPI_MCU_H_
+#define _ROCKPI_MCU_H_
+
+#define LOG_INFO(fmt,arg...) pr_info("rockpi-mcu: %s: "fmt, __func__, ##arg);
+#define LOG_ERR(fmt,arg...) pr_err("rockpi-mcu: %s: "fmt, __func__, ##arg);
+
+#define MAX_I2C_LEN 255
+
+struct rockpi_mcu_data {
+ struct device *dev;
+ struct i2c_client *client;
+};
+
+#endif
--
2.25.1