From dfce9c177f90c1a5f3966443ea3b49543c67b6f7 Mon Sep 17 00:00:00 2001 From: Dees_Troy Date: Mon, 27 Feb 2012 11:23:46 -0600 Subject: [PATCH] Move digitizer power management into ts_srv Change-Id: Ie540b9619d3c79e0ce31589caae3aa979404da34 --- liblights/lights.c | 137 ++-------------------------- touchscreen_drv/Android.mk | 3 +- touchscreen_drv/digitizer.c | 176 ++++++++++++++++++++++++++++++++++++ touchscreen_drv/digitizer.h | 30 ++++++ touchscreen_drv/ts_srv.c | 11 ++- 5 files changed, 224 insertions(+), 133 deletions(-) create mode 100644 touchscreen_drv/digitizer.c create mode 100644 touchscreen_drv/digitizer.h diff --git a/liblights/lights.c b/liblights/lights.c index 1001e0a4518..8f45223d1b5 100644 --- a/liblights/lights.c +++ b/liblights/lights.c @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include #include @@ -57,8 +55,7 @@ static const uint16_t notif_led_program_reset[] = { 0x9c0f, 0x9c8f, 0x03ff, 0xc000 }; -/** TS power stuff */ -static int vdd_fd, xres_fd, wake_fd, i2c_fd, ts_state; +static int ts_state; void send_ts_socket(char *send_data) { // Connects to the touchscreen socket @@ -72,123 +69,12 @@ void send_ts_socket(char *send_data) { strcpy(unaddr.sun_path, TS_SOCKET_LOCATION); len = strlen(unaddr.sun_path) + sizeof(unaddr.sun_family); if (connect(ts_fd, (struct sockaddr *)&unaddr, len) >= 0) { - send(ts_fd, send_data, 1, 0); + send(ts_fd, send_data, sizeof(*send_data), 0); } close(ts_fd); } } -void touchscreen_power(int enable) -{ - struct i2c_rdwr_ioctl_data i2c_ioctl_data; - struct i2c_msg i2c_msg; - __u8 i2c_buf[16]; - int rc; - - if (enable) { - int retry_count = 0; - send_ts_socket("O"); -try_again: - /* Set reset so the chip immediatelly sees it */ - lseek(xres_fd, 0, SEEK_SET); - rc = write(xres_fd, "1", 1); - LOGE_IF(rc != 1, "TSpower, failed set xres"); - - /* Then power on */ - lseek(vdd_fd, 0, SEEK_SET); - rc = write(vdd_fd, "1", 1); - LOGE_IF(rc != 1, "TSpower, failed to enable vdd"); - - /* Sleep some more for the voltage to stabilize */ - usleep(50000); - - lseek(wake_fd, 0, SEEK_SET); - rc = write(wake_fd, "1", 1); - LOGE_IF(rc != 1, "TSpower, failed to assert wake"); - - lseek(xres_fd, 0, SEEK_SET); - rc = write(xres_fd, "0", 1); - LOGE_IF(rc != 1, "TSpower, failed to reset xres"); - - usleep(50000); - - lseek(wake_fd, 0, SEEK_SET); - rc = write(wake_fd, "0", 1); - LOGE_IF(rc != 1, "TSpower, failed to deassert wake"); - - usleep(50000); - - i2c_ioctl_data.nmsgs = 1; - i2c_ioctl_data.msgs = &i2c_msg; - - i2c_msg.addr = 0x67; - i2c_msg.flags = 0; - i2c_msg.buf = i2c_buf; - - i2c_msg.len = 2; - i2c_buf[0] = 0x08; i2c_buf[1] = 0; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl1 failed %d errno %d\n", rc, errno); - /* Ok, so the TS failed to wake, we need to retry a few times - * before totally giving up */ - if ((rc != 1) && (retry_count++ < 3)) { - lseek(vdd_fd, 0, SEEK_SET); - rc = write(vdd_fd, "0", 1); - usleep(10000); - LOGE("TS wakeup retry #%d\n", retry_count); - goto try_again; - } - - i2c_msg.len = 6; - i2c_buf[0] = 0x31; i2c_buf[1] = 0x01; i2c_buf[2] = 0x08; - i2c_buf[3] = 0x0C; i2c_buf[4] = 0x0D; i2c_buf[5] = 0x0A; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl2 failed %d errno %d\n", rc, errno); - - i2c_msg.len = 2; - i2c_buf[0] = 0x30; i2c_buf[1] = 0x0F; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl3 failed %d errno %d\n", rc, errno); - - i2c_buf[0] = 0x40; i2c_buf[1] = 0x02; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl4 failed %d errno %d\n", rc, errno); - - i2c_buf[0] = 0x41; i2c_buf[1] = 0x10; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl5 failed %d errno %d\n", rc, errno); - - i2c_buf[0] = 0x0A; i2c_buf[1] = 0x04; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl6 failed %d errno %d\n", rc, errno); - - i2c_buf[0] = 0x08; i2c_buf[1] = 0x03; - rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); - LOGE_IF( rc != 1, "TSPower, ioctl7 failed %d errno %d\n", rc, errno); - - lseek(wake_fd, 0, SEEK_SET); - rc = write(wake_fd, "1", 1); - LOGE_IF(rc != 1, "TSpower, failed to assert wake again"); - } else { - lseek(vdd_fd, 0, SEEK_SET); - rc = write(vdd_fd, "0", 1); - LOGE_IF(rc != 1, "TSpower, failed to disable vdd"); - - /* Weird, but on 4G touchpads even after vdd is off there is still - * stream of data from ctp that only disappears after we reset the - * touchscreen, even though it's supposedly powered off already - */ - lseek(xres_fd, 0, SEEK_SET); - rc = write(xres_fd, "1", 1); - usleep(10000); - lseek(xres_fd, 0, SEEK_SET); - rc = write(xres_fd, "0", 1); - /* XXX, should be correllated with LIFTOFF_TIMEOUT in ts driver */ - usleep(80000); - send_ts_socket("C"); - } -} - static int write_int(char const *path, int value) { int fd; @@ -329,15 +215,15 @@ static int set_light_backlight(struct light_device_t *dev, pthread_mutex_lock(&g_lock); err = write_int(LCD_FILE, brightness); - /* TS power magic hack */ + /* Tell touchscreen to turn on or off */ if (brightness > 0 && ts_state == 0) { LOGI("Enabling touch screen"); ts_state = 1; - touchscreen_power(1); + send_ts_socket("O"); } else if (brightness == 0 && ts_state == 1) { LOGI("Disabling touch screen"); ts_state = 0; - touchscreen_power(0); + send_ts_socket("C"); } pthread_mutex_unlock(&g_lock); @@ -350,7 +236,8 @@ static int close_lights(struct light_device_t *dev) if (dev) free(dev); - touchscreen_power(0); + ts_state = 0; + send_ts_socket("C"); return 0; } @@ -383,16 +270,6 @@ static int open_lights(const struct hw_module_t *module, char const *name, *device = (struct hw_device_t *)dev; - /* TS file descriptors. Ignore errors. */ - vdd_fd = open("/sys/devices/platform/cy8ctma395/vdd", O_WRONLY); - LOGE_IF(vdd_fd < 0, "TScontrol: Cannot open vdd - %d", errno); - xres_fd = open("/sys/devices/platform/cy8ctma395/xres", O_WRONLY); - LOGE_IF(xres_fd < 0, "TScontrol: Cannot open xres - %d", errno); - wake_fd = open("/sys/user_hw/pins/ctp/wake/level", O_WRONLY); - LOGE_IF(wake_fd < 0, "TScontrol: Cannot open wake - %d", errno); - i2c_fd = open("/dev/i2c-5", O_RDWR); - LOGE_IF(i2c_fd < 0, "TScontrol: Cannot open i2c dev - %d", errno); - init_notification_led(); return 0; diff --git a/touchscreen_drv/Android.mk b/touchscreen_drv/Android.mk index 0c67258b16e..47079023974 100644 --- a/touchscreen_drv/Android.mk +++ b/touchscreen_drv/Android.mk @@ -7,7 +7,8 @@ include $(CLEAR_VARS) #LOCAL_C_INCLUDES:= uim.h LOCAL_SRC_FILES:= \ - ts_srv.c + ts_srv.c \ + digitizer.c LOCAL_CFLAGS:= -g -c -W -Wall -O2 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp -funsafe-math-optimizations -D_POSIX_SOURCE -I/home/green/touchpad/hp_tenderloin_kernel/include LOCAL_MODULE:=ts_srv LOCAL_MODULE_TAGS:= eng diff --git a/touchscreen_drv/digitizer.c b/touchscreen_drv/digitizer.c new file mode 100644 index 00000000000..33396ee2d2a --- /dev/null +++ b/touchscreen_drv/digitizer.c @@ -0,0 +1,176 @@ +/* + * This is a userspace power management driver for the digitizer in the HP + * Touchpad to turn the digitizer on and off. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Copyright (c) 2012 CyanogenMod Touchpad Project. + * + * + */ + +#include +#include +#include +#include +#include +#include + +#include "digitizer.h" + +static int vdd_fd, xres_fd, wake_fd, i2c_fd, ts_state; + +void touchscreen_power(int enable) +{ + struct i2c_rdwr_ioctl_data i2c_ioctl_data; + struct i2c_msg i2c_msg; + __u8 i2c_buf[16]; + int rc; + + if (enable && !ts_state) { + int retry_count = 0; +try_again: + /* Set reset so the chip immediatelly sees it */ + lseek(xres_fd, 0, SEEK_SET); + rc = write(xres_fd, "1", 1); + if (rc != 1) + printf("TSpower, failed set xres"); + + /* Then power on */ + lseek(vdd_fd, 0, SEEK_SET); + rc = write(vdd_fd, "1", 1); + if (rc != 1) + printf("TSpower, failed to enable vdd"); + + /* Sleep some more for the voltage to stabilize */ + usleep(50000); + + lseek(wake_fd, 0, SEEK_SET); + rc = write(wake_fd, "1", 1); + if (rc != 1) + printf("TSpower, failed to assert wake"); + + lseek(xres_fd, 0, SEEK_SET); + rc = write(xres_fd, "0", 1); + if (rc != 1) + printf("TSpower, failed to reset xres"); + + usleep(50000); + + lseek(wake_fd, 0, SEEK_SET); + rc = write(wake_fd, "0", 1); + if (rc != 1) + printf("TSpower, failed to deassert wake"); + + usleep(50000); + + i2c_ioctl_data.nmsgs = 1; + i2c_ioctl_data.msgs = &i2c_msg; + + i2c_msg.addr = 0x67; + i2c_msg.flags = 0; + i2c_msg.buf = i2c_buf; + + i2c_msg.len = 2; + i2c_buf[0] = 0x08; i2c_buf[1] = 0; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl1 failed %d errno %d\n", rc, errno); + /* Ok, so the TS failed to wake, we need to retry a few times + * before totally giving up */ + if ((rc != 1) && (retry_count++ < MAX_DIGITIZER_RETRY)) { + lseek(vdd_fd, 0, SEEK_SET); + rc = write(vdd_fd, "0", 1); + usleep(10000); + printf("TS wakeup retry #%d\n", retry_count); + goto try_again; + } + + i2c_msg.len = 6; + i2c_buf[0] = 0x31; i2c_buf[1] = 0x01; i2c_buf[2] = 0x08; + i2c_buf[3] = 0x0C; i2c_buf[4] = 0x0D; i2c_buf[5] = 0x0A; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl2 failed %d errno %d\n", rc, errno); + + i2c_msg.len = 2; + i2c_buf[0] = 0x30; i2c_buf[1] = 0x0F; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl3 failed %d errno %d\n", rc, errno); + + i2c_buf[0] = 0x40; i2c_buf[1] = 0x02; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl4 failed %d errno %d\n", rc, errno); + + i2c_buf[0] = 0x41; i2c_buf[1] = 0x10; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl5 failed %d errno %d\n", rc, errno); + + i2c_buf[0] = 0x0A; i2c_buf[1] = 0x04; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl6 failed %d errno %d\n", rc, errno); + + i2c_buf[0] = 0x08; i2c_buf[1] = 0x03; + rc = ioctl(i2c_fd,I2C_RDWR,&i2c_ioctl_data); + if (rc != 1) + printf("TSPower, ioctl7 failed %d errno %d\n", rc, errno); + + lseek(wake_fd, 0, SEEK_SET); + rc = write(wake_fd, "1", 1); + if (rc != 1) + printf("TSpower, failed to assert wake again"); + ts_state = 1; + } else if (ts_state) { + lseek(vdd_fd, 0, SEEK_SET); + rc = write(vdd_fd, "0", 1); + if (rc != 1) + printf("TSpower, failed to disable vdd"); + + /* Weird, but on 4G touchpads even after vdd is off there is still + * stream of data from ctp that only disappears after we reset the + * touchscreen, even though it's supposedly powered off already + */ + lseek(xres_fd, 0, SEEK_SET); + rc = write(xres_fd, "1", 1); + usleep(10000); + lseek(xres_fd, 0, SEEK_SET); + rc = write(xres_fd, "0", 1); + /* XXX, should be correllated with LIFTOFF_TIMEOUT in ts driver */ + usleep(80000); + ts_state = 0; + } +} + +void init_digitizer_fd(void) { + /* TS file descriptors. Ignore errors. */ + vdd_fd = open("/sys/devices/platform/cy8ctma395/vdd", O_WRONLY); + if (vdd_fd < 0) + printf("TScontrol: Cannot open vdd - %d", errno); + xres_fd = open("/sys/devices/platform/cy8ctma395/xres", O_WRONLY); + if (xres_fd < 0) + printf("TScontrol: Cannot open xres - %d", errno); + wake_fd = open("/sys/user_hw/pins/ctp/wake/level", O_WRONLY); + if (wake_fd < 0) + printf("TScontrol: Cannot open wake - %d", errno); + i2c_fd = open("/dev/i2c-5", O_RDWR); + if (i2c_fd < 0) + printf("TScontrol: Cannot open i2c dev - %d", errno); + +} \ No newline at end of file diff --git a/touchscreen_drv/digitizer.h b/touchscreen_drv/digitizer.h new file mode 100644 index 00000000000..4b46ea791cb --- /dev/null +++ b/touchscreen_drv/digitizer.h @@ -0,0 +1,30 @@ +/* + * This is a userspace power management driver for the digitizer in the HP + * Touchpad to turn the digitizer on and off. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * + * Copyright (c) 2012 CyanogenMod Touchpad Project. + * + * + */ + +// Maximum number of times to retry powering on the digitizer +#define MAX_DIGITIZER_RETRY 3 + +void touchscreen_power(int enable); + +void init_digitizer_fd(void); \ No newline at end of file diff --git a/touchscreen_drv/ts_srv.c b/touchscreen_drv/ts_srv.c index 46306a67375..71d732e4400 100644 --- a/touchscreen_drv/ts_srv.c +++ b/touchscreen_drv/ts_srv.c @@ -46,6 +46,8 @@ #include #include +#include "digitizer.h" + #if 1 // This is for Android #define UINPUT_LOCATION "/dev/uinput" @@ -82,7 +84,7 @@ #define RECV_BUF_SIZE 1540 #define LIFTOFF_TIMEOUT 25000 -#define SOCKET_BUFFER_SIZE 1 +#define SOCKET_BUFFER_SIZE 10 #define MAX_TOUCH 10 // Max touches that will be reported @@ -1261,8 +1263,10 @@ void process_socket_buffer(char *buffer[], int buffer_len, int *uart_fd, #if DEBUG_SOCKET printf("uart closed: %i\n", return_val); #endif + touchscreen_power(0); } if (buf == 79 /* 'O' */ && *uart_fd < 0) { + touchscreen_power(1); open_uart(uart_fd); #if DEBUG_SOCKET printf("uart opened at %i\n", *uart_fd); @@ -1288,7 +1292,7 @@ void process_socket_buffer(char *buffer[], int buffer_len, int *uart_fd, current_mode[0] = read_settings_file(); send_ret = send(accept_fd, (char*)current_mode, - sizeof(current_mode), 0); + sizeof(*current_mode), 0); #if DEBUG_SOCKET if (send_ret <= 0) printf("Unable to send data to socket\n"); @@ -1316,6 +1320,9 @@ int main(int argc, char** argv) if (sched_setscheduler(0 /* that's us */, SCHED_FIFO, &sparam)) perror("Cannot set RT priority, ignoring: "); + init_digitizer_fd(); + touchscreen_power(1); + open_uart(&uart_fd); open_uinput();