diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 2 | ||||
-rw-r--r-- | firmware/drivers/synaptics-rmi.c | 77 | ||||
-rw-r--r-- | firmware/export/synaptics-rmi.h | 63 | ||||
-rw-r--r-- | firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c | 134 | ||||
-rw-r--r-- | firmware/target/arm/imx233/sansa-fuzeplus/button-target.h | 1 |
5 files changed, 277 insertions, 0 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index e5eb0e6e1f..6d4ef9fe2b 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1435,6 +1435,8 @@ target/arm/as3525/lcd-as-e200v2-fuze-fuzev2.S #ifdef SANSA_FUZEPLUS #ifndef SIMULATOR +drivers/generic_i2c.c +drivers/synaptics-rmi.c target/arm/imx233/sansa-fuzeplus/backlight-fuzeplus.c target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c diff --git a/firmware/drivers/synaptics-rmi.c b/firmware/drivers/synaptics-rmi.c new file mode 100644 index 0000000000..c6a1bae168 --- /dev/null +++ b/firmware/drivers/synaptics-rmi.c @@ -0,0 +1,77 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "system.h" +#include "generic_i2c.h" +#include "synaptics-rmi.h" + +static int rmi_cur_page; +static int rmi_i2c_addr; +static int rmi_i2c_bus; + +/* NOTE: + * RMI over i2c supports some special aliases on page 0x2 but this driver don't + * use them */ + +int rmi_init(int i2c_bus_index, int i2c_dev_addr) +{ + rmi_i2c_bus = i2c_bus_index; + rmi_i2c_addr = i2c_dev_addr; + rmi_cur_page = 0x4; + return 0; +} + +static int rmi_select_page(unsigned char page) +{ + /* Lazy page select */ + if(page != rmi_cur_page) + { + rmi_cur_page = page; + return i2c_write_data(rmi_i2c_bus, rmi_i2c_addr, RMI_PAGE_SELECT, &page, 1); + } + else + return 0; +} + +int rmi_read(int address, int byte_count, unsigned char *buffer) +{ + if(rmi_select_page(address >> 8) < 0) + return -1; + return i2c_read_data(rmi_i2c_bus, rmi_i2c_addr, address & 0xff, buffer, byte_count); +} + +int rmi_read_single(int address) +{ + unsigned char c; + int ret = rmi_read(address, 1, &c); + return ret < 0 ? ret : c; +} + +int rmi_write(int address, int byte_count, const unsigned char *buffer) +{ + if(rmi_select_page(address >> 8) < 0) + return -1; + return i2c_write_data(rmi_i2c_bus, rmi_i2c_addr, address & 0xff, buffer, byte_count); +} + +int rmi_write_single(int address, unsigned char byte) +{ + return rmi_write(address, 1, &byte); +} diff --git a/firmware/export/synaptics-rmi.h b/firmware/export/synaptics-rmi.h new file mode 100644 index 0000000000..59fbb807ab --- /dev/null +++ b/firmware/export/synaptics-rmi.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * 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. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef SYNAPTICS_RMI_H +#define SYNAPTICS_RMI_H + +#define RMI_PAGE_SELECT 0xff /* $xxff */ +#define RMI_MAKE_REG(fn, reg) (((fn) << 8) | (reg)) +#define RMI_DEVICE_CONTROL 0x0 /* $0000 */ +#define RMI_INTERRUPT_ENABLE 0x1 /* $0001 */ +#define RMI_INTERRUPT_REQUEST 0x3 /* $0003 */ +#define RMI_PRODUCT_ID 0x210 /* $0210 */ +#define RMI_PRODUCT_ID_LEN 16 +#define RMI_2D_TOUCHPAD_FUNCTION 0x10 +#define RMI_FUNCTION_PRESENCE(fn) RMI_MAKE_REG(0x03, fn) /* $03xx */ +#define RMI_FUNCTION_VERSION(fn) RMI_MAKE_REG(fn, 0) /* $xx00 */ +#define RMI_DATA_REGISTER(data_src) RMI_MAKE_REG(0x4, data_src) /* $04xx */ +/* 2D TouchPad/ClearPad */ +#define RMI_2D_REG(reg) RMI_MAKE_REG(RMI_2D_TOUCHPAD_FUNCTION, reg) +#define RMI_2D_SENSOR_PROP1(sens) RMI_2D_REG(8 * (sens) + 0x2) +#define RMI_2D_SENSOR_PROP2(sens) RMI_2D_REG(8 * (sens) + 0x3) +#define RMI_2D_SENSOR_XMAX_MSB(s) RMI_2D_REG(8 * (s) + 0x4) +#define RMI_2D_SENSOR_XMAX_LSB(s) RMI_2D_REG(8 * (s) + 0x5) +#define RMI_2D_SENSOR_YMAX_MSB(s) RMI_2D_REG(8 * (s) + 0x6) +#define RMI_2D_SENSOR_YMAX_LSB(s) RMI_2D_REG(8 * (s) + 0x7) +#define RMI_2D_SENSOR_RESOLUTION(s) RMI_2D_REG(8 * (s) + 0x8) + +/* Initialize the RMI driver, the i2c_bus_index is the bus index returned by + * the generic_i2c driver; the i2c_dev_addr is the i2c address of the device. + * NOTE: the driver automatically handles the page select mechanism used for + * RMI over i2c and assumes a standard page select register at 0xff. */ +int rmi_init(int i2c_bus_index, int i2c_dev_addr); +/* Read one or more registers. + * WARNING: don't cross a page boundary ! */ +int rmi_read(int address, int byte_count, unsigned char *buffer); +/* Read a single register (return -1 on error) + * WARNING: beware of register consistency (N x read 1 byte != reads N bytes) */ +int rmi_read_single(int address); /* return byte value or <0 in case of error */ +/* Write one of more register + * WARNING: don't cross a page boundary ! */ +int rmi_write(int address, int byte_count, const unsigned char *buffer); +/* Write one register + * WARNING: don't cross a page boundary ! */ +int rmi_write_single(int address, unsigned char byte); + +#endif diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c b/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c index 4882f243aa..1b8116b1b7 100644 --- a/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c +++ b/firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c @@ -22,9 +22,143 @@ #include "system.h" #include "system-target.h" #include "pinctrl-imx233.h" +#include "generic_i2c.h" +#include "synaptics-rmi.h" +#include "lcd.h" + +static void i2c_scl_dir(bool out) +{ + imx233_enable_gpio_output(0, 30, out); +} + +static void i2c_sda_dir(bool out) +{ + imx233_enable_gpio_output(0, 31, out); +} + +static void i2c_scl_out(bool high) +{ + imx233_set_gpio_output(0, 30, high); +} + +static void i2c_sda_out(bool high) +{ + imx233_set_gpio_output(0, 31, high); +} + +static bool i2c_scl_in(void) +{ + return imx233_get_gpio_input_mask(0, 1 << 30); +} + +static bool i2c_sda_in(void) +{ + return imx233_get_gpio_input_mask(0, 1 << 31); +} + +static void i2c_delay(int d) +{ + udelay(d); +} + +struct i2c_interface btn_i2c = +{ + .scl_dir = i2c_scl_dir, + .sda_dir = i2c_sda_dir, + .scl_out = i2c_scl_out, + .sda_out = i2c_sda_out, + .scl_in = i2c_scl_in, + .sda_in = i2c_sda_in, + .delay = i2c_delay, + .delay_hd_sta = 4, + .delay_hd_dat = 5, + .delay_su_dat = 1, + .delay_su_sto = 4, + .delay_su_sta = 5, + .delay_thigh = 4 +}; + +int rmi_i2c_bus = -1; + +void button_debug_screen(void) +{ + char product_id[RMI_PRODUCT_ID_LEN]; + rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id); + + while(1) + { + lcd_clear_display(); + int btns = button_read_device(); + lcd_putsf(0, 0, "button bitmap: %x", btns); + lcd_putsf(0, 1, "RMI: product=%s", product_id); + lcd_putsf(0, 2, "touchpad presence: %x", rmi_read_single(RMI_FUNCTION_PRESENCE(RMI_2D_TOUCHPAD_FUNCTION))); + lcd_putsf(0, 3, "sensor prop: %x", rmi_read_single(RMI_2D_SENSOR_PROP2(0))); + int x_max = rmi_read_single(RMI_2D_SENSOR_XMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_XMAX_LSB(0)); + int y_max = rmi_read_single(RMI_2D_SENSOR_YMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_YMAX_LSB(0)); + lcd_putsf(0, 4, "xmax=%d ymax=%d res=%d", x_max, y_max, + rmi_read_single(RMI_2D_SENSOR_RESOLUTION(0))); + lcd_putsf(0, 5, "din0=%x", imx233_get_gpio_input_mask(0, 0x08000000)); + lcd_putsf(0, 6, "dev ctl: %x", rmi_read_single(RMI_DEVICE_CONTROL)); + lcd_putsf(0, 7, "int en: %x", rmi_read_single(RMI_INTERRUPT_ENABLE)); + lcd_putsf(0, 8, "int req: %x", rmi_read_single(RMI_INTERRUPT_REQUEST)); + union + { + unsigned char data[10]; + struct + { + unsigned char absolute_misc; + unsigned char absolute_z; + unsigned char absolute_x_msb; + unsigned char absolute_x_lsb; + unsigned char absolute_y_msb; + unsigned char absolute_y_lsb; + signed char relative_x; /* signed */ + signed char relative_y; /* signed */ + unsigned char gesture_misc; + unsigned char gesture_flick; + } __attribute__((packed)) s; + }u; + int absolute_x = u.s.absolute_x_msb << 8 | u.s.absolute_x_lsb; + int absolute_y = u.s.absolute_y_msb << 8 | u.s.absolute_y_lsb; + rmi_read(RMI_DATA_REGISTER(0), 10, u.data); + lcd_putsf(0, 9, "abs: %d %d", absolute_x, absolute_y); + lcd_putsf(0, 10, "rel: %d %d", (int)u.s.relative_x, (int)u.s.relative_y); + lcd_putsf(0, 11, "gesture: %x %x", u.s.gesture_misc, u.s.gesture_flick); + + lcd_update(); + + if(btns & BUTTON_POWER) + break; + yield(); + } +} void button_init_device(void) { + rmi_i2c_bus = i2c_add_node(&btn_i2c); + rmi_init(rmi_i2c_bus, 0x40); + + /* Synaptics TouchPad information: + * - product id: 1533 + * - nr function: 1 (0x10 = 2D touchpad) + * 2D Touchpad information (function 0x10) + * - nr data sources: 3 + * - standard layout + * - extra data registers: 7 + * - nr sensors: 1 + * 2D Touchpad Sensor #0 information: + * - has relative data: yes + * - has palm detect: yes + * - has multi finger: yes + * - has enhanced gesture: yes + * - has scroller: no + * - has 2D scrollers: no + * - Maximum X: 3009 + * - Maxumum Y: 1974 + * - Resolution: 82 + * + * ATTENTION line: B0P27 asserted low + */ } int button_read_device(void) diff --git a/firmware/target/arm/imx233/sansa-fuzeplus/button-target.h b/firmware/target/arm/imx233/sansa-fuzeplus/button-target.h index 81bbc34511..f22c06882f 100644 --- a/firmware/target/arm/imx233/sansa-fuzeplus/button-target.h +++ b/firmware/target/arm/imx233/sansa-fuzeplus/button-target.h @@ -26,6 +26,7 @@ void button_init_device(void); int button_read_device(void); +void button_debug_screen(void); /* Main unit's buttons */ #define BUTTON_POWER 0x00000001 |