summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/board-touch.c
blob: a759a688f5b30047784d5cdd5e62dafed27dab0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
 * arch/arm/mach-tegra/board-touch.c
 *
 * Copyright (c) 2011, NVIDIA Corporation.
 *
 * 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 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.
 */

#define VERBOSE_DEBUG	1	/* When set, emit verbose debug messages.	*/
#define MULTI_SKU	1	/* When set, multi-driver detection is enabled.	*/
				/* When clear, DEFAULT_SKU is used.		*/

#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/gpio.h>

#include "board.h"
#if defined(CONFIG_MACH_VENTANA)
#include "board-ventana.h"
#elif defined(CONFIG_MACH_CARDHU)
#include "board-cardhu.h"
#elif defined(CONFIG_MACH_TEGRA_ENTERPRISE)
#include "board-enterprise.h"
#endif
#include "gpio-names.h"
#include "touch.h"

#define SKU_MASK	0xFF00	/* Mask BoardInfo before testing sku.	*/
#define UNKNOWN_SKU	0xFF00	/* When BoardInfo not programmed...	*/


/****************************************************************************
	This touch screen driver interface is a generic interface, designed
	to support any number of touch screen devices.  It is also designed to
	allow multiple touchscreen drivers and dynamic detection of the touch
	screen.  The touch screen is detected by reading the BoardInfo EEPROM
	structure.  The 'sku' field indicates which touch screen is implemented.

	In the event that the BoardInfo EEPROM is not programmed, this interface
	design allows for a default driver to be loaded anyways.

	In order to support multi-driver implementations, each touch screen must
	register itself in this file, and implement a few basic items.  The
	basic implementation is as follows:

#if defined(CONFIG_TOUCHSCREEN_YOUR_TOUCHSCREEN_DRIVER_NAME)
	#include <your_touch.h>
	extern struct tegra_touchscreen_init ts_init_data;
	#define YOUR_TOUCHSCREEN_SKU1	VALUE1	// This is the value in BoardInfo.sku
	#define YOUR_TOUCHSCREEN_SKU2	VALUE2	// Another value from BoardInfo.sku
	#define YOUR_TOUCHSCREEN_SKU-N	VALUE-N	// Yet another BoardInfo.sku value
	#if defined(DEFAULT_SKU) && (MULTI_SKU == 1) //Make  sure only one SKU is defined.
	#if defined(DEFAULT_SKU) && (MULTI_SKU == 0)
	#error ERROR!  When MULTI_SKU=0, only one touch screen driver is supported at a time.\
	Check your _defconfig file and remove all but one touch screen driver instances.
	#else
	#ifndef DEFAULT_SKU
	#define DEFAULT_SKU		FAV_SKU	// When MULTI_SKU=0, default to this SKU
	#endif
	#endif
#endif
****************************************************************************/


/*** PANJIT Support ********************************************************/
#if defined(CONFIG_TOUCHSCREEN_PANJIT_I2C)
#include <linux/i2c/panjit_ts.h>
extern struct tegra_touchscreen_init panjit_init_data;
#define PANJIT_TOUCHSCREEN_SKU	0x0000
#if defined(DEFAULT_SKU) && (MULTI_SKU == 0)
#error ERROR!  When MULTI_SKU=0, only one touch screen driver is supported at a time.\
Check your _defconfig file and remove all but one touch screen driver instances.
#else
#ifndef DEFAULT_SKU
#define DEFAULT_SKU		PANJIT_TOUCHSCREEN_SKU
#endif
#endif
#endif

/*** ATMEL Multitouch Support **********************************************/
#if defined(CONFIG_TOUCHSCREEN_ATMEL_MT_T9) || defined(CONFIG_TOUCHSCREEN_ATMEL_MXT)
extern struct tegra_touchscreen_init atmel_mxt_init_data;
#if defined(CONFIG_TOUCHSCREEN_ATMEL_MXT)
extern void init_sku2000(void);
#define ATMEL_TOUCHSCREEN_SKU2000	0x0B00
#endif
#define ATMEL_TOUCHSCREEN_SKU		0x0A00
#define ATMEL_TOUCHSCREEN_ENTERPRISE	0x0C00
#if defined(DEFAULT_SKU) && (MULTI_SKU == 0)
#error ERROR!  When MULTI_SKU=0, only one touch screen driver is supported at a time.\
Check your _defconfig file and remove all but one touch screen driver instances.
#else
#ifndef DEFAULT_SKU
#define DEFAULT_SKU		ATMEL_TOUCHSCREEN_SKU
#endif
#endif
#endif


int __init generic_touch_init(struct tegra_touchscreen_init *tsdata)
{
	int ret;
	if (VERBOSE_DEBUG >= 1)
		pr_info("### TOUCHSCREEN:  Inside generic_touch_init()\n");

	ret = gpio_request(tsdata->rst_gpio, "touch-reset");
	if (ret < 0) {
		pr_err("%s(): gpio_request() fails for gpio %d (touch-reset)\n",
			__func__, tsdata->rst_gpio);
		return ret;
	}

	ret = gpio_request(tsdata->irq_gpio, "touch-irq");
	if (ret < 0) {
		pr_err("%s(): gpio_request() fails for gpio %d (touch-irq)\n",
			__func__, tsdata->irq_gpio);
		gpio_free(tsdata->rst_gpio);
		return ret;
	}

	gpio_direction_output(tsdata->rst_gpio, 0);
	gpio_direction_input(tsdata->irq_gpio);

	tegra_gpio_enable(tsdata->irq_gpio);
	tegra_gpio_enable(tsdata->rst_gpio);

	if (tsdata->sv_gpio1.valid)
		gpio_set_value(tsdata->sv_gpio1.gpio, tsdata->sv_gpio1.value);
	if (tsdata->sv_gpio1.delay)
		msleep(tsdata->sv_gpio1.delay);
	if (tsdata->sv_gpio2.valid)
		gpio_set_value(tsdata->sv_gpio2.gpio, tsdata->sv_gpio2.value);
	if (tsdata->sv_gpio2.delay)
		msleep(tsdata->sv_gpio2.delay);

	i2c_register_board_info(tsdata->ts_boardinfo.busnum,
		tsdata->ts_boardinfo.info,
		tsdata->ts_boardinfo.n);
	return 0;
}

int __init touch_init(void)
{
	int retval = 0;
	int sku = 0xFFFF;
	struct board_info BoardInfo;

	if (VERBOSE_DEBUG >= 1)
		pr_info("### Touch Init...\n");

	tegra_get_board_info(&BoardInfo);

#if defined(CONFIG_MACH_CARDHU)
#if defined(CONFIG_TOUCHSCREEN_ATMEL_MT_T9)
	if (BoardInfo.board_id == BOARD_PM269)
		BoardInfo.sku = ATMEL_TOUCHSCREEN_SKU;
#endif
#endif

	if (VERBOSE_DEBUG >= 1)
		pr_info("### BoardInfo.sku = %04X\n", BoardInfo.sku);

#if MULTI_SKU
	sku = BoardInfo.sku & SKU_MASK;
#else
	sku = DEFAULT_SKU;
#endif

	if (VERBOSE_DEBUG >= 1)
		pr_info("### sku = %04X\n", sku);

	switch (sku) {
#if defined(CONFIG_TOUCHSCREEN_ATMEL_MT_T9) || defined(CONFIG_TOUCHSCREEN_ATMEL_MXT)
#if defined(CONFIG_TOUCHSCREEN_ATMEL_MXT)
	case ATMEL_TOUCHSCREEN_SKU2000:
		init_sku2000();
		/* Fall through	*/
#endif

	case ATMEL_TOUCHSCREEN_SKU:
	case ATMEL_TOUCHSCREEN_ENTERPRISE:
		retval = generic_touch_init(&atmel_mxt_init_data);
		break;
#endif
#if defined(CONFIG_TOUCHSCREEN_PANJIT_I2C)
	case PANJIT_TOUCHSCREEN_SKU:
		retval = generic_touch_init(&panjit_init_data);
		break;
#endif

	case UNKNOWN_SKU:
		pr_info("*** ERROR ***\n");
		pr_info("    Invalid BoardInfo EEPROM.  ");
		pr_info("    BoardInfo.sku is programmed with 0xFFFF.\n");
		pr_info("    No touch screen support.\n");
		break;

	default:
		pr_info("*** ERROR ***\n");
		pr_info("    Invalid BoardInfo EEPROM.  ");
		pr_info("    BoardInfo.sku contains unknown SKU: %04X\n", BoardInfo.sku);
		pr_info("    No touch screen support.\n");
		break;
	}

	return retval;
}