summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootloader/imx233.c6
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/synaptics-rmi.c77
-rw-r--r--firmware/export/synaptics-rmi.h63
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c134
-rw-r--r--firmware/target/arm/imx233/sansa-fuzeplus/button-target.h1
6 files changed, 283 insertions, 0 deletions
diff --git a/bootloader/imx233.c b/bootloader/imx233.c
index cded5a119a..868d6e499f 100644
--- a/bootloader/imx233.c
+++ b/bootloader/imx233.c
@@ -35,6 +35,8 @@
35#include "disk.h" 35#include "disk.h"
36#include "panic.h" 36#include "panic.h"
37#include "power.h" 37#include "power.h"
38#include "pinctrl-imx233.h"
39#include "system-target.h"
38 40
39int show_logo(void); 41int show_logo(void);
40 42
@@ -58,6 +60,10 @@ void main(void)
58 60
59 button_init_device(); 61 button_init_device();
60 62
63 button_debug_screen();
64
65 power_off();
66
61 ret = storage_init(); 67 ret = storage_init();
62 if(ret < 0) 68 if(ret < 0)
63 error(EATA, ret, true); 69 error(EATA, ret, true);
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
1435 1435
1436#ifdef SANSA_FUZEPLUS 1436#ifdef SANSA_FUZEPLUS
1437#ifndef SIMULATOR 1437#ifndef SIMULATOR
1438drivers/generic_i2c.c
1439drivers/synaptics-rmi.c
1438target/arm/imx233/sansa-fuzeplus/backlight-fuzeplus.c 1440target/arm/imx233/sansa-fuzeplus/backlight-fuzeplus.c
1439target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c 1441target/arm/imx233/sansa-fuzeplus/lcd-fuzeplus.c
1440target/arm/imx233/sansa-fuzeplus/button-fuzeplus.c 1442target/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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "system.h"
22#include "generic_i2c.h"
23#include "synaptics-rmi.h"
24
25static int rmi_cur_page;
26static int rmi_i2c_addr;
27static int rmi_i2c_bus;
28
29/* NOTE:
30 * RMI over i2c supports some special aliases on page 0x2 but this driver don't
31 * use them */
32
33int rmi_init(int i2c_bus_index, int i2c_dev_addr)
34{
35 rmi_i2c_bus = i2c_bus_index;
36 rmi_i2c_addr = i2c_dev_addr;
37 rmi_cur_page = 0x4;
38 return 0;
39}
40
41static int rmi_select_page(unsigned char page)
42{
43 /* Lazy page select */
44 if(page != rmi_cur_page)
45 {
46 rmi_cur_page = page;
47 return i2c_write_data(rmi_i2c_bus, rmi_i2c_addr, RMI_PAGE_SELECT, &page, 1);
48 }
49 else
50 return 0;
51}
52
53int rmi_read(int address, int byte_count, unsigned char *buffer)
54{
55 if(rmi_select_page(address >> 8) < 0)
56 return -1;
57 return i2c_read_data(rmi_i2c_bus, rmi_i2c_addr, address & 0xff, buffer, byte_count);
58}
59
60int rmi_read_single(int address)
61{
62 unsigned char c;
63 int ret = rmi_read(address, 1, &c);
64 return ret < 0 ? ret : c;
65}
66
67int rmi_write(int address, int byte_count, const unsigned char *buffer)
68{
69 if(rmi_select_page(address >> 8) < 0)
70 return -1;
71 return i2c_write_data(rmi_i2c_bus, rmi_i2c_addr, address & 0xff, buffer, byte_count);
72}
73
74int rmi_write_single(int address, unsigned char byte)
75{
76 return rmi_write(address, 1, &byte);
77}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef SYNAPTICS_RMI_H
22#define SYNAPTICS_RMI_H
23
24#define RMI_PAGE_SELECT 0xff /* $xxff */
25#define RMI_MAKE_REG(fn, reg) (((fn) << 8) | (reg))
26#define RMI_DEVICE_CONTROL 0x0 /* $0000 */
27#define RMI_INTERRUPT_ENABLE 0x1 /* $0001 */
28#define RMI_INTERRUPT_REQUEST 0x3 /* $0003 */
29#define RMI_PRODUCT_ID 0x210 /* $0210 */
30#define RMI_PRODUCT_ID_LEN 16
31#define RMI_2D_TOUCHPAD_FUNCTION 0x10
32#define RMI_FUNCTION_PRESENCE(fn) RMI_MAKE_REG(0x03, fn) /* $03xx */
33#define RMI_FUNCTION_VERSION(fn) RMI_MAKE_REG(fn, 0) /* $xx00 */
34#define RMI_DATA_REGISTER(data_src) RMI_MAKE_REG(0x4, data_src) /* $04xx */
35/* 2D TouchPad/ClearPad */
36#define RMI_2D_REG(reg) RMI_MAKE_REG(RMI_2D_TOUCHPAD_FUNCTION, reg)
37#define RMI_2D_SENSOR_PROP1(sens) RMI_2D_REG(8 * (sens) + 0x2)
38#define RMI_2D_SENSOR_PROP2(sens) RMI_2D_REG(8 * (sens) + 0x3)
39#define RMI_2D_SENSOR_XMAX_MSB(s) RMI_2D_REG(8 * (s) + 0x4)
40#define RMI_2D_SENSOR_XMAX_LSB(s) RMI_2D_REG(8 * (s) + 0x5)
41#define RMI_2D_SENSOR_YMAX_MSB(s) RMI_2D_REG(8 * (s) + 0x6)
42#define RMI_2D_SENSOR_YMAX_LSB(s) RMI_2D_REG(8 * (s) + 0x7)
43#define RMI_2D_SENSOR_RESOLUTION(s) RMI_2D_REG(8 * (s) + 0x8)
44
45/* Initialize the RMI driver, the i2c_bus_index is the bus index returned by
46 * the generic_i2c driver; the i2c_dev_addr is the i2c address of the device.
47 * NOTE: the driver automatically handles the page select mechanism used for
48 * RMI over i2c and assumes a standard page select register at 0xff. */
49int rmi_init(int i2c_bus_index, int i2c_dev_addr);
50/* Read one or more registers.
51 * WARNING: don't cross a page boundary ! */
52int rmi_read(int address, int byte_count, unsigned char *buffer);
53/* Read a single register (return -1 on error)
54 * WARNING: beware of register consistency (N x read 1 byte != reads N bytes) */
55int rmi_read_single(int address); /* return byte value or <0 in case of error */
56/* Write one of more register
57 * WARNING: don't cross a page boundary ! */
58int rmi_write(int address, int byte_count, const unsigned char *buffer);
59/* Write one register
60 * WARNING: don't cross a page boundary ! */
61int rmi_write_single(int address, unsigned char byte);
62
63#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 @@
22#include "system.h" 22#include "system.h"
23#include "system-target.h" 23#include "system-target.h"
24#include "pinctrl-imx233.h" 24#include "pinctrl-imx233.h"
25#include "generic_i2c.h"
26#include "synaptics-rmi.h"
27#include "lcd.h"
28
29static void i2c_scl_dir(bool out)
30{
31 imx233_enable_gpio_output(0, 30, out);
32}
33
34static void i2c_sda_dir(bool out)
35{
36 imx233_enable_gpio_output(0, 31, out);
37}
38
39static void i2c_scl_out(bool high)
40{
41 imx233_set_gpio_output(0, 30, high);
42}
43
44static void i2c_sda_out(bool high)
45{
46 imx233_set_gpio_output(0, 31, high);
47}
48
49static bool i2c_scl_in(void)
50{
51 return imx233_get_gpio_input_mask(0, 1 << 30);
52}
53
54static bool i2c_sda_in(void)
55{
56 return imx233_get_gpio_input_mask(0, 1 << 31);
57}
58
59static void i2c_delay(int d)
60{
61 udelay(d);
62}
63
64struct i2c_interface btn_i2c =
65{
66 .scl_dir = i2c_scl_dir,
67 .sda_dir = i2c_sda_dir,
68 .scl_out = i2c_scl_out,
69 .sda_out = i2c_sda_out,
70 .scl_in = i2c_scl_in,
71 .sda_in = i2c_sda_in,
72 .delay = i2c_delay,
73 .delay_hd_sta = 4,
74 .delay_hd_dat = 5,
75 .delay_su_dat = 1,
76 .delay_su_sto = 4,
77 .delay_su_sta = 5,
78 .delay_thigh = 4
79};
80
81int rmi_i2c_bus = -1;
82
83void button_debug_screen(void)
84{
85 char product_id[RMI_PRODUCT_ID_LEN];
86 rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id);
87
88 while(1)
89 {
90 lcd_clear_display();
91 int btns = button_read_device();
92 lcd_putsf(0, 0, "button bitmap: %x", btns);
93 lcd_putsf(0, 1, "RMI: product=%s", product_id);
94 lcd_putsf(0, 2, "touchpad presence: %x", rmi_read_single(RMI_FUNCTION_PRESENCE(RMI_2D_TOUCHPAD_FUNCTION)));
95 lcd_putsf(0, 3, "sensor prop: %x", rmi_read_single(RMI_2D_SENSOR_PROP2(0)));
96 int x_max = rmi_read_single(RMI_2D_SENSOR_XMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_XMAX_LSB(0));
97 int y_max = rmi_read_single(RMI_2D_SENSOR_YMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_YMAX_LSB(0));
98 lcd_putsf(0, 4, "xmax=%d ymax=%d res=%d", x_max, y_max,
99 rmi_read_single(RMI_2D_SENSOR_RESOLUTION(0)));
100 lcd_putsf(0, 5, "din0=%x", imx233_get_gpio_input_mask(0, 0x08000000));
101 lcd_putsf(0, 6, "dev ctl: %x", rmi_read_single(RMI_DEVICE_CONTROL));
102 lcd_putsf(0, 7, "int en: %x", rmi_read_single(RMI_INTERRUPT_ENABLE));
103 lcd_putsf(0, 8, "int req: %x", rmi_read_single(RMI_INTERRUPT_REQUEST));
104 union
105 {
106 unsigned char data[10];
107 struct
108 {
109 unsigned char absolute_misc;
110 unsigned char absolute_z;
111 unsigned char absolute_x_msb;
112 unsigned char absolute_x_lsb;
113 unsigned char absolute_y_msb;
114 unsigned char absolute_y_lsb;
115 signed char relative_x; /* signed */
116 signed char relative_y; /* signed */
117 unsigned char gesture_misc;
118 unsigned char gesture_flick;
119 } __attribute__((packed)) s;
120 }u;
121 int absolute_x = u.s.absolute_x_msb << 8 | u.s.absolute_x_lsb;
122 int absolute_y = u.s.absolute_y_msb << 8 | u.s.absolute_y_lsb;
123 rmi_read(RMI_DATA_REGISTER(0), 10, u.data);
124 lcd_putsf(0, 9, "abs: %d %d", absolute_x, absolute_y);
125 lcd_putsf(0, 10, "rel: %d %d", (int)u.s.relative_x, (int)u.s.relative_y);
126 lcd_putsf(0, 11, "gesture: %x %x", u.s.gesture_misc, u.s.gesture_flick);
127
128 lcd_update();
129
130 if(btns & BUTTON_POWER)
131 break;
132 yield();
133 }
134}
25 135
26void button_init_device(void) 136void button_init_device(void)
27{ 137{
138 rmi_i2c_bus = i2c_add_node(&btn_i2c);
139 rmi_init(rmi_i2c_bus, 0x40);
140
141 /* Synaptics TouchPad information:
142 * - product id: 1533
143 * - nr function: 1 (0x10 = 2D touchpad)
144 * 2D Touchpad information (function 0x10)
145 * - nr data sources: 3
146 * - standard layout
147 * - extra data registers: 7
148 * - nr sensors: 1
149 * 2D Touchpad Sensor #0 information:
150 * - has relative data: yes
151 * - has palm detect: yes
152 * - has multi finger: yes
153 * - has enhanced gesture: yes
154 * - has scroller: no
155 * - has 2D scrollers: no
156 * - Maximum X: 3009
157 * - Maxumum Y: 1974
158 * - Resolution: 82
159 *
160 * ATTENTION line: B0P27 asserted low
161 */
28} 162}
29 163
30int button_read_device(void) 164int 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 @@
26 26
27void button_init_device(void); 27void button_init_device(void);
28int button_read_device(void); 28int button_read_device(void);
29void button_debug_screen(void);
29 30
30/* Main unit's buttons */ 31/* Main unit's buttons */
31#define BUTTON_POWER 0x00000001 32#define BUTTON_POWER 0x00000001