PageRenderTime 62ms CodeModel.GetById 23ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/ANDROID_2.6.32-DS/ANDROID_2.6.32/drivers/input/touchscreen/rohm/rohm_bu21020.c

https://bitbucket.org/weilonge/vt8500-linux-kernel
C | 850 lines | 589 code | 124 blank | 137 comment | 82 complexity | 8a421147599f2d56bc18c430a8ca3651 MD5 | raw file
  1/* drivers/input/touchscreen/rohm_bu21020.c
  2 * BU21020 touchscreen driver
  3 *
  4 * Copyright (C) 2010 ROHM SEMICONDUCTOR Co. Ltd.
  5 *
  6 * Author: CT Cheng <ct.cheng@rohm.com.tw>
  7*/
  8#include <linux/kernel.h>
  9#include <linux/module.h>
 10#include <linux/input.h>
 11#include <linux/interrupt.h>
 12#include <linux/delay.h>
 13#include <linux/gpio.h>
 14#include <linux/spi/spi.h>
 15#include <linux/hrtimer.h>
 16#include <linux/spi/rohm_bu21020.h>
 17#include <linux/cdev.h>
 18#include <linux/fs.h>
 19#include <linux/poll.h>
 20//#include "BU21020_firmware.h" /* BU21020 internal firmware */
 21#include "bu21020.h"
 22
 23#define ROHM_TS_ABS_X_MIN 	0
 24#define ROHM_TS_ABS_X_MAX 	799
 25#define ROHM_TS_ABS_Y_MIN 	0
 26#define ROHM_TS_ABS_Y_MAX 	479
 27
 28#define BU21020_HZ     (10000000)
 29
 30// Register map
 31#define BU21020_REG_X1H (0x20)
 32#define BU21020_REG_X1L (0x21)
 33#define BU21020_REG_Y1H (0x22)
 34#define BU21020_REG_Y1L (0x23)
 35#define BU21020_REG_X2H (0x24)
 36#define BU21020_REG_X2L (0x25)
 37#define BU21020_REG_Y2H (0x26)
 38#define BU21020_REG_Y2L (0x27)
 39// Command
 40#define BU21020_CMD_W(addr) (addr)  /* single write */
 41#define BU21020_CMD_R(addr) (addr | 0x80)  /* single read */
 42
 43
 44#undef SW_AVG
 45/********************************************/
 46#ifdef SW_AVG
 47
 48#define BUFF_ARRAY  16
 49#define DISTANCE_X 6
 50#define DISTANCE_Y 6
 51#define AVG_BOUND_X 4
 52#define AVG_BOUND_Y 4
 53#define S_DISTANCE_X 6
 54#define S_DISTANCE_Y 6
 55#define S_AVG_BOUND_X 4
 56#define S_AVG_BOUND_Y 4
 57
 58#define MULTI_SKIP_TIMES 15
 59
 60#define SKIP_AVG_1 1
 61#define SKIP_AVG_2 1
 62struct touch_point
 63{
 64	unsigned int x;
 65	unsigned int y;
 66	unsigned int buff_x[BUFF_ARRAY];
 67	unsigned int buff_y[BUFF_ARRAY];
 68	unsigned char buff_cnt;
 69	/* Previous coordinate of touch point after moving average calculating */
 70	unsigned int old_avg_x;
 71	unsigned int old_avg_y;
 72};
 73
 74struct touch_point tp1, tp2;
 75#endif
 76
 77extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
 78extern int wmt_setsyspara(char *varname, char *varval);
 79
 80#define UBOOT_PARA_USED
 81#define IOCTL_GET_CAL 0x1601
 82#define IOCTL_SET_CAL 0x1602
 83#define IOCTL_GET_RAW 0x1603
 84#define IOCTL_SET_RAW 0x1604
 85#define IOCTL_SET_RESOLUTION 0x1605
 86#define IOCTL_DO_FILTER 0x1606
 87#define IOCTL_SET_FILTER_DISTANCE 0x1607
 88#define IOCTL_SET_SPI_FREQ 0x1608
 89#define IOCTL_GET_SPI_FREQ 0x1609
 90#define IOCTL_SET_DELAY_TIME 0x160A
 91#define IOCTL_GET_DELAY_TIME 0x160B
 92
 93#define TS_IOC_MAGIC  't'
 94
 95#define TS_IOCTL_CAL_START    _IO(TS_IOC_MAGIC,   1)
 96#define TS_IOCTL_CAL_DONE     _IOW(TS_IOC_MAGIC,  2, int*)
 97#define TS_IOCTL_GET_RAWDATA  _IOR(TS_IOC_MAGIC,  3, int*)
 98
 99struct private_wmt_ts_s {
100	/* module parameters */
101	char *buf;
102	/* char dev struct */
103	struct cdev cdev;
104};
105
106
107static struct workqueue_struct *rohm_wq;
108
109static struct private_wmt_ts_s private_ts;
110static int private_wmt_dev_major = 160;
111static int private_wmt_dev_minor = 0 ;
112struct class *class_wmt_ts;
113
114static pm_message_t ts_pm_state  = {
115	.event = PM_EVENT_ON,
116};
117
118struct calibration_parameter g_CalcParam = {
119	.a1 = 32602,
120	.b1 = 339,
121	.c1 = -1973856,
122	.a2 = -99,
123	.b2 = 23003,
124	.c2 = -3520935,
125	.delta = 37654,
126};
127
128struct bu21020 
129{
130	struct spi_device	*spi;
131
132	struct input_dev	*idev;
133	char			phys[32];
134
135	struct hrtimer timer;
136	struct work_struct  work;
137
138};
139
140/*
141 * brief : set calibration information from BOOT ROM
142 */
143int set_twoD_calibration_info(void) {
144	int retval;
145	char buf[160];
146	sprintf(buf, "%d %d %d %d %d %d %d",
147		g_CalcParam.a1,
148		g_CalcParam.b1,
149		g_CalcParam.c1,
150		g_CalcParam.a2,
151		g_CalcParam.b2,
152		g_CalcParam.c2,
153		g_CalcParam.delta
154	);
155#ifdef UBOOT_PARA_USED
156	retval = wmt_setsyspara("wmt.io.ts.2dcal", buf);
157#endif
158	retval = 0;
159
160	return retval;
161}
162
163int get_twoD_calibration_info(void) {
164        int retval;
165	char *varname = "wmt.io.ts.2dcal";
166#ifdef UBOOT_PARA_USED
167	int varlen = 160;
168#endif
169	unsigned char buf[160];
170#ifdef UBOOT_PARA_USED
171	retval = wmt_getsyspara(varname, buf, &varlen);
172#else
173	retval = 1;
174#endif
175	if (retval != 0) {
176		printk("Use default Calibration points\n");
177		return retval;
178	} else
179		printk("%s = %s\n",varname, buf);
180
181	sscanf(buf, "%d %d %d %d %d %d %d",
182	    &g_CalcParam.a1,
183	    &g_CalcParam.b1,
184	    &g_CalcParam.c1,
185	    &g_CalcParam.a2,
186	    &g_CalcParam.b2,
187	    &g_CalcParam.c2,
188	    &g_CalcParam.delta);
189
190	return retval;
191}
192
193static inline void SPI_ByteWrite(struct spi_device *spi, u8 address, u8 data)
194{
195	char tx_buf[2];
196	int ret;
197
198	tx_buf[0] = address;
199	tx_buf[1] = data;
200	ret = spi_write(spi, tx_buf, 2);
201
202	if (ret != 0)
203		printk("spi write err\n");
204	/*
205	else
206		printk("<1> Write reg(0x%x): 0x%x\n", address, data);
207	*/
208}
209
210static inline u8 SPI_ByteRead(struct spi_device *spi, u8 address)
211{	
212	u8  result;	
213	result = spi_w8r8(spi, BU21020_CMD_R(address));
214	return result;
215}
216
217#ifdef SW_AVG
218
219//-----------------------------------------------------------------------------
220//
221//Coord_Avg
222//
223//-----------------------------------------------------------------------------
224static void Coord_Avg (struct touch_point *tp)
225{
226	unsigned long temp_x = 0, temp_y = 0, temp_n = 0;
227	unsigned int i;
228	////////////////////////////////////////
229	// X1,Y1 Moving Avg
230	////////////////////////////////////////
231	if ((tp->x != 0) && (tp->y != 0)) {			               			  			      				
232		if(tp->buff_cnt >= SKIP_AVG_1) {  
233		    if(((abs(tp->buff_x[0] - tp->x) > DISTANCE_X) && (abs(tp->buff_y[0] - tp->y) > DISTANCE_Y)) ||
234		       ((abs(tp->buff_x[0] - tp->x) > S_DISTANCE_X) && (abs(tp->buff_y[0] - tp->y) < S_DISTANCE_Y)) ||
235			   ((abs(tp->buff_x[0] - tp->x) < S_DISTANCE_X) && (abs(tp->buff_y[0] - tp->y) > S_DISTANCE_Y)) ||			   
236			   (((tp->old_avg_x != 0) && (abs(tp->old_avg_x - tp->x) > AVG_BOUND_X)) && 
237			   ( (tp->old_avg_y != 0) && (abs(tp->old_avg_y - tp->y) > AVG_BOUND_Y))) ||
238			   (((tp->old_avg_x != 0) && (abs(tp->old_avg_x - tp->x) > S_AVG_BOUND_X)) && 			
239			   ( (tp->old_avg_y != 0) && (abs(tp->old_avg_y - tp->y) < S_AVG_BOUND_Y)))||
240			   (((tp->old_avg_x != 0) && (abs(tp->old_avg_x - tp->x) < S_AVG_BOUND_X)) && 			
241			   ( (tp->old_avg_y != 0) && (abs(tp->old_avg_y - tp->y) > S_AVG_BOUND_Y)))) {
242				for (i = 0; i < tp->buff_cnt; i++) {
243					tp->buff_x[tp->buff_cnt - i] = tp->buff_x[tp->buff_cnt - i - 1];
244					tp->buff_y[tp->buff_cnt - i] = tp->buff_y[tp->buff_cnt - i - 1];
245				}
246				tp->buff_x[0] = tp->x;
247				tp->buff_y[0] = tp->y;
248 
249				temp_x = 0; temp_y = 0; temp_n = 0;
250        
251				for (i = 0; i <= tp->buff_cnt; i++) {
252					temp_x += ((unsigned long) (tp->buff_x[i] * (tp->buff_cnt - i + 1)));
253					temp_y += ((unsigned long) (tp->buff_y[i] * (tp->buff_cnt - i + 1)));
254					temp_n += (unsigned long) (tp->buff_cnt - i + 1);
255				}            
256				tp->x = temp_x / temp_n;
257				tp->y = temp_y / temp_n;
258		
259				tp->old_avg_x = tp->x;
260				tp->old_avg_y = tp->y;  	
261				if (tp->buff_cnt < (BUFF_ARRAY-1))
262					tp->buff_cnt++;
263			} else {	  
264				tp->x = tp->old_avg_x;
265				tp->y = tp->old_avg_y;	
266			} 
267		} else {
268			for (i = 0; i < tp->buff_cnt; i++) {
269				tp->buff_x[tp->buff_cnt - i] = tp->buff_x[tp->buff_cnt - i - 1];
270				tp->buff_y[tp->buff_cnt - i] = tp->buff_y[tp->buff_cnt - i - 1];
271			}	
272			tp->buff_x[0] = tp->x;
273			tp->buff_y[0] = tp->y;
274			if(tp->buff_cnt < (BUFF_ARRAY-1))
275				tp->buff_cnt++;
276			tp->old_avg_x = tp->x;
277			tp->old_avg_y = tp->y;
278			tp->x = 0;
279			tp->y = 0;			
280
281		}
282	} else {//End/ of "if((x1 != 0) && (y1 != 0))"
283		tp->buff_cnt = 0;
284		if((tp->buff_x[0] != 0) && (tp->buff_y[0] != 0)) {
285			tp->x = tp->buff_x[0];
286			tp->y = tp->buff_y[0];
287		} else {
288			tp->x = 0;
289			tp->y = 0;
290		}
291		tp->buff_x[0] = 0;
292		tp->buff_y[0] = 0;
293		tp->old_avg_x = 0;
294		tp->old_avg_y = 0;
295	}
296
297
298}
299#endif
300
301static u16 cal_data[2];
302
303static void twoDconvert(u32 *cal_x, u32 *cal_y )
304{
305	int UncalX;
306	int UncalY;
307	int x,y;
308	UncalX = (int) *cal_x;
309	UncalY = (int) *cal_y;
310	x = (g_CalcParam.a1 * UncalX + g_CalcParam.b1 * UncalY +
311	     g_CalcParam.c1) / g_CalcParam.delta;
312	y = (g_CalcParam.a2 * UncalX + g_CalcParam.b2 * UncalY +
313	     g_CalcParam.c2) / g_CalcParam.delta;
314
315	if (x < 0)
316		x = 0;
317
318	if (y < 0)
319		y = 0;
320	*cal_x = (u32)x;
321	*cal_y = (u32)y;
322}
323
324
325static void rohm_ts_work_func(struct work_struct *work)
326{
327	//define ouput data start
328	unsigned int finger;
329	unsigned int x1, y1, x2, y2; 
330
331	struct bu21020 *tsc = container_of(work, struct bu21020, work);
332
333	//Get the coordinate of point 1 and point 2
334	/*
335	x1 = (SPI_ByteRead(tsc->spi, BU21020_REG_X1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X1L);
336	y1 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y1L);
337	x2 = (SPI_ByteRead(tsc->spi, BU21020_REG_X2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X2L);
338	y2 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y2L);
339	*/
340	y1 = (SPI_ByteRead(tsc->spi, BU21020_REG_X1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X1L);
341	x1 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y1L);
342	y2 = (SPI_ByteRead(tsc->spi, BU21020_REG_X2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X2L);
343	x2 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y2L);
344	//printk(" x1 = %3d, y1 = %3d,x2 = %3d, y2 = %3d,   \n", x1, y1, x2, y2);
345
346	cal_data[0] = x1;
347	cal_data[1] = y1;
348	
349	if (x1 != 0 && y1 != 0)
350		twoDconvert(&x1, &y1);
351	if (x2 != 0 && y2 != 0)
352		twoDconvert(&x2, &y2);
353
354	/*
355	printk(" x1 = %3d, y1 = %3d,x2 = %3d, y2 = %3d,   \n", x1, y1, x2, y2);
356	*/
357
358	SPI_ByteWrite(tsc->spi, 0x3E, 0xFF);
359
360#ifdef SW_AVG
361	tp1.x = x1;
362	tp1.y = y1;
363	Coord_Avg(&tp1);
364	x1 = tp1.x;
365	y1 = tp1.y;
366	tp2.x = x2;
367	tp2.y = y2;
368	Coord_Avg(&tp2);
369	x2 = tp2.x;
370	y2 = tp2.y;
371#endif
372	
373 	if (((y1 > 0) && (x1 > 0)) && ((y2 > 0) && (x2 > 0))) {
374		finger = 2;
375	} else if (((y1 > 0) && (x1 > 0)) || ((y2 > 0) && (x2 > 0))) {
376		finger = 1;
377
378		if ((x2 != 0) && (y2 != 0)) {
379			x1 = x2;
380			y1 = y2;
381			x2 = 0;
382			y2 = 0;
383		}
384	} else {
385 		finger = 0;
386 	}
387	/*
388	printk(" x1 = %3d, y1 = %3d,x2 = %3d, y2 = %3d,   \n", x1, y1, x2, y2);
389	*/
390	if(finger == 0)
391		input_report_abs(tsc->idev, ABS_MT_TOUCH_MAJOR, 0);
392	else
393		input_report_abs(tsc->idev, ABS_MT_TOUCH_MAJOR, 3);
394	/*
395	input_report_abs(tsc->idev, ABS_MT_WIDTH_MAJOR, 0);
396	*/
397	input_report_abs(tsc->idev, ABS_MT_POSITION_X, x1);
398	input_report_abs(tsc->idev, ABS_MT_POSITION_Y, y1);
399	input_mt_sync(tsc->idev);
400	if (finger == 2) {
401		input_report_abs(tsc->idev, ABS_MT_TOUCH_MAJOR, 3);
402		/*
403		input_report_abs(tsc->idev, ABS_MT_WIDTH_MAJOR, 0);
404		*/
405		input_report_abs(tsc->idev, ABS_MT_POSITION_X, x2);
406		input_report_abs(tsc->idev, ABS_MT_POSITION_Y, y2);
407		input_mt_sync(tsc->idev);
408	}     
409	input_report_abs(tsc->idev, ABS_PRESSURE, 0);   // 0 touch_pressure
410	input_report_abs(tsc->idev, ABS_TOOL_WIDTH, 0); // 0 touch_width,File system do judge this register
411	input_report_key(tsc->idev, BTN_TOUCH,finger);  // finger  num   0, 1, 2
412        input_report_key(tsc->idev, BTN_2, finger > 1); // finger2 state 0, 0, 1
413        input_sync(tsc->idev);   // up load data                           
414
415}
416
417
418static enum hrtimer_restart rohm_ts_timer_func(struct hrtimer *timer)
419{
420	struct bu21020 *tsc = container_of(timer, struct bu21020, timer);
421	queue_work(rohm_wq, &tsc->work);
422	hrtimer_start(&tsc->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);/*report rate 1/12500000=80Hz*/
423	return HRTIMER_NORESTART;
424}
425
426static int __devinit bu21020_ts_init(struct bu21020 *ts,
427				     struct bu21020_platform_data *pdata)
428{
429	struct input_dev *idev;
430
431	int r;
432	idev = input_allocate_device();
433	if (idev == NULL) {
434		r = -ENOMEM;
435		goto err;
436	}
437
438	idev->name = "BU21020 touchscreen";
439	/*Dean-
440	snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts",
441		 ts->spi->dev.bus_id);
442	*/
443	/*Dean+*/
444	snprintf(ts->phys, sizeof(ts->phys), "input-ts");
445	idev->phys = ts->phys;
446
447	idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
448	idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
449	ts->idev = idev;
450
451	////////////////////////////////////////////////////////////////////////////
452	input_set_abs_params(idev, ABS_MT_POSITION_X, ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
453	input_set_abs_params(idev, ABS_MT_POSITION_Y, ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
454	input_set_abs_params(idev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
455	//input_set_abs_params(idev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
456	////////////////////////////////////////////////////////////////////////////
457	//input_set_abs_params(idev, ABS_X, ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
458	//input_set_abs_params(idev, ABS_Y, ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
459	input_set_abs_params(idev, ABS_PRESSURE, 0, 1550, 0 , 0);  //1550  two point
460	input_set_abs_params(idev, ABS_TOOL_WIDTH, 0, 15, 0 , 0); 	//15   two point
461	//input_set_abs_params(idev, ABS_HAT0X, ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
462	//input_set_abs_params(idev, ABS_HAT0Y, ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
463
464	//bu21020_start_scan(ts);
465	r = input_register_device(idev);
466	if (r < 0) {
467		dev_err(&ts->spi->dev, "can't register touchscreen device\n");
468		goto err;
469	}
470
471	return 0;
472err:
473	return r;
474}
475
476static int private_wmt_ts_ioctl(
477	struct inode *inode,    /*!<; //[IN] a pointer point to struct inode */
478	struct file *filp,      /*!<; //[IN] a pointer point to struct file  */
479	unsigned int cmd,       /*!<; // please add parameters description her*/
480	unsigned long arg       /*!<; // please add parameters description her*/
481)
482{
483	int nBuff[7];
484	int retval = 0;
485	switch (cmd) {
486	case TS_IOCTL_CAL_START:
487		/*
488		printk("TS_IOCTL_CAL_START\n");
489		*/
490		break;
491	case TS_IOCTL_CAL_DONE:
492		/*
493		printk("TS_IOCTL_CAL_DONE\n");
494		*/
495		copy_from_user(nBuff, (unsigned int*)arg, 7*sizeof(int));
496		g_CalcParam.a1 = nBuff[0];
497		g_CalcParam.b1 = nBuff[1];
498		g_CalcParam.c1 = nBuff[2];
499		g_CalcParam.a2 = nBuff[3];
500		g_CalcParam.b2 = nBuff[4];
501		g_CalcParam.c2 = nBuff[5];
502		g_CalcParam.delta = nBuff[6];
503		/*
504		printk("g_CalcParam = %d, %d, %d, %d, %d, %d, %d\n",
505			g_CalcParam.a1, g_CalcParam.b1, g_CalcParam.c1,
506			g_CalcParam.a2, g_CalcParam.b2, g_CalcParam.c2, g_CalcParam.delta);
507		*/
508		set_twoD_calibration_info();
509		break;
510
511	case TS_IOCTL_GET_RAWDATA:
512		/*
513		printk("TS_IOCTL_GET_RAWDATA\n");
514		*/
515		nBuff[0] = cal_data[0];
516		nBuff[1] = cal_data[1];
517		copy_to_user((unsigned int*)arg, nBuff, 2*sizeof(int));
518		/*
519		printk("x = %d, y = %d\n", nBuff[0], nBuff[1]);
520		*/
521		break;
522	default:
523		retval = -EINVAL;
524		break;
525	}
526	return retval;
527}
528
529
530static int private_wmt_ts_open(
531        struct inode *inode,    /*!<; //[IN] a pointer point to struct inode */
532        struct file *filp       /*!<; //[IN] a pointer point to struct file  */
533)
534{
535	struct private_wmt_ts_s *dev;
536	/*
537	printk("wmt_ts_open\n");
538	*/
539	dev = container_of(inode->i_cdev, struct private_wmt_ts_s, cdev);
540	filp->private_data = dev;
541	return 0;
542}
543static int private_wmt_ts_release(
544        struct inode *inode,    /*!<; //[IN] a pointer point to struct inode */
545        struct file *filp       /*!<; //[IN] a pointer point to struct file  */
546)
547{
548	/*
549	printk("wmt_ts_release\n");
550	*/
551	return 0;
552}
553
554
555struct file_operations wmt_ts_fops = {
556	.owner = THIS_MODULE,
557	.open = private_wmt_ts_open,
558	.ioctl = private_wmt_ts_ioctl,
559	.release = private_wmt_ts_release,
560};
561
562// Firmware Download
563static int init_bu21020_firm(struct spi_device *spi)
564{
565	////////////////////////////////////////////////////////////////////////
566	// Download BU21020 Firmware by HOST
567	////////////////////////////////////////////////////////////////////////
568	// Wait 200usec for Reset
569	int i = 0;
570	SPI_ByteWrite(spi, 0x40, 0x00);
571	udelay(200);
572
573	SPI_ByteWrite(spi, 0x30, 0x02);
574	SPI_ByteWrite(spi, 0x40, 0x01);
575	// Wait 100usec for POWER-ON
576	udelay(100);
577	// Beginning address setting of program memory for host download
578	SPI_ByteWrite(spi, 0x70, 0x00);
579	SPI_ByteWrite(spi, 0x71, 0x00);
580
581	// Download firmware to BU21020
582	printk("BU21020 firmware download starts!\n");
583
584	for(i = 0; i < CODESIZE; i++)
585		SPI_ByteWrite(spi, 0x72, program[i]); 
586	printk("BU21020 firmware download is completed!\n");
587	// Clear all Interrupt
588	SPI_ByteWrite(spi, 0x3E, 0xFF);
589	return 0;
590}
591
592// Initial Setting (For Register Setting)
593static int init_bu21020_reg(struct spi_device *spi)
594{
595	////////////////////////////////////////////////////////////////////////
596	// Init BU21020
597	////////////////////////////////////////////////////////////////////////
598
599	SPI_ByteWrite(spi, 0x40, 0x00);
600
601	SPI_ByteWrite(spi, 0x30, 0x46);
602	SPI_ByteWrite(spi, 0x40, 0x01);
603	// Wait 100usec for Power-on
604	udelay(100);
605	SPI_ByteWrite(spi, 0x31, 0xE6);
606	SPI_ByteWrite(spi, 0x32, 0x62);	
607	
608	
609	SPI_ByteWrite(spi, 0x35, 0xB0);	
610	SPI_ByteWrite(spi, 0x34, 0x78);	
611	
612	/*
613	SPI_ByteWrite(spi, 0x35, 0xB0);	
614	SPI_ByteWrite(spi, 0x34, 0x78);	
615	*/
616
617	SPI_ByteWrite(spi, 0x36, 0x08);
618	SPI_ByteWrite(spi, 0x37, 0x08);
619
620	SPI_ByteWrite(spi, 0x3A, 0x0F);
621	
622	//Change AD timing
623	SPI_ByteWrite(spi, 0x50, 0x00);
624	SPI_ByteWrite(spi, 0x52, 0x08);
625	SPI_ByteWrite(spi, 0x56, 0xFF);
626	//SPI_ByteWrite(spi, 0x60, 0x04);
627	SPI_ByteWrite(spi, 0x61, 0x0A);
628	SPI_ByteWrite(spi, 0x62, 0x0F);
629	printk("Dean revised1111\n");
630
631	SPI_ByteWrite(spi, 0x64, 0x5C);
632	SPI_ByteWrite(spi, 0x63, 0xD6);
633
634	SPI_ByteWrite(spi, 0x65, 0x01);
635	// CPU power on
636	SPI_ByteWrite(spi, 0x40, 0x03);
637	// Clear all Interrupt
638	SPI_ByteWrite(spi, 0x3E, 0xFF);
639	return 0;
640}
641
642static int __devinit bu21020_probe(struct spi_device *spi)
643{
644	struct bu21020  *tsc;
645	struct bu21020_platform_data    *pdata = spi->dev.platform_data;
646	int r;
647#if 1
648	unsigned char version = 0;
649#endif
650#if 0
651	int i;
652#endif
653        dev_t dev_no;
654        struct cdev *cdev;
655        dev_no = MKDEV(private_wmt_dev_major, private_wmt_dev_minor);
656        cdev = &private_ts.cdev;
657        cdev_init(cdev,&wmt_ts_fops);
658        cdev_add(cdev, dev_no, 8);
659        class_wmt_ts = class_create(THIS_MODULE, "wmtts");
660        device_create(class_wmt_ts, NULL ,MKDEV(private_wmt_dev_major,private_wmt_dev_minor),
661                        NULL, "wmtts");
662	printk(KERN_ERR "ROHM BU21020 rohm_ts_probe!\n");
663
664	if (!pdata) {
665		dev_dbg(&spi->dev, "no platform data?\n");
666		return -ENODEV;
667	}
668
669	tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
670	if (tsc == NULL)
671		return -ENOMEM;
672
673	dev_set_drvdata(&spi->dev, tsc);
674	tsc->spi = spi;
675	spi->dev.power.power_state = PMSG_ON;
676
677	spi->mode = SPI_MODE_3;
678	spi->bits_per_word = 8;
679	/* The max speed might've been defined by the board-specific
680	 * struct */
681	if (!spi->max_speed_hz)
682		spi->max_speed_hz = BU21020_HZ;
683	spi_setup(spi);
684	INIT_WORK(&tsc->work, rohm_ts_work_func);
685
686#if 1
687	init_bu21020_firm(spi);
688	init_bu21020_reg(spi);
689#endif
690
691#if 0
692	////////////////////////////////////////////////////////////////////////
693	// Init BU21020
694	////////////////////////////////////////////////////////////////////////
695	// Wait 200usec for Reset
696	/*
697	SPI_ByteWrite(spi, 0x40, 0x00);
698	udelay(200);
699	*/
700	SPI_ByteWrite(spi, 0x40, 0x01);
701	udelay(200);
702	SPI_ByteWrite(spi, 0x30, 0x46);
703	SPI_ByteWrite(spi, 0x31, 0xE6);
704	SPI_ByteWrite(spi, 0x32, 0x62);	
705	
706	/*
707	SPI_ByteWrite(spi, 0x35, 0x78);	
708	SPI_ByteWrite(spi, 0x34, 0xB0);	
709	*/
710	SPI_ByteWrite(spi, 0x34, 0x78);	
711	SPI_ByteWrite(spi, 0x35, 0xB0);	
712
713	SPI_ByteWrite(spi, 0x36, 0x08);
714	SPI_ByteWrite(spi, 0x37, 0x08);
715
716	SPI_ByteWrite(spi, 0x3A, 0x0F);
717
718	SPI_ByteWrite(spi, 0x56, 0xFF);
719	SPI_ByteWrite(spi, 0x61, 0x0A);
720	SPI_ByteWrite(spi, 0x62, 0x0F);
721
722	SPI_ByteWrite(spi, 0x63, 0x5C);
723	SPI_ByteWrite(spi, 0x64, 0xD6);
724
725	/*
726	SPI_ByteWrite(spi, 0x63, 0xE0);
727	SPI_ByteWrite(spi, 0x64, 0xE4);
728	*/
729
730	SPI_ByteWrite(spi, 0x65, 0x01);
731
732	SPI_ByteWrite(spi, 0x40, 0x01);
733
734	// Wait 100usec for Power-on
735	udelay(100);
736
737	// Beginning address setting of program memory for host download
738	SPI_ByteWrite(spi, 0x70, 0x00);
739	SPI_ByteWrite(spi, 0x71, 0x00);
740
741	// Download firmware to BU21020
742	printk("BU21020 firmware download starts!\n");
743
744	for(i = 0; i < CODESIZE; i++)
745		SPI_ByteWrite(spi, 0x72, program[i]); 
746	printk("BU21020 firmware download is completed!\n");
747	// Download path setting
748
749	SPI_ByteWrite(spi, 0x3E, 0xFF);
750	
751	//Change AD timing
752	//SPI_ByteWrite(spi, 0x50, 0x00);
753	SPI_ByteWrite(spi, 0x52, 0x08);
754	// CPU power on
755	SPI_ByteWrite(spi, 0x40, 0x03);
756	// Clear all Interrupt
757	SPI_ByteWrite(spi, 0x3E, 0xFF);
758#endif
759
760#if 1 /*for debug*/
761	mdelay(10);
762	version = SPI_ByteRead(spi, 0x5f);
763	printk("BU21020 firmware version = %x\n", version);
764#endif
765
766	// Init end
767	////////////////////////////////////////////////////////////////////////
768
769	r = bu21020_ts_init(tsc, pdata);
770
771	/* Timer init*/
772	hrtimer_init(&tsc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
773	tsc->timer.function = rohm_ts_timer_func;
774	hrtimer_start(&tsc->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
775
776	get_twoD_calibration_info();
777
778	if (r)
779		goto err1;
780
781	return 0;
782
783err1:
784	kfree(tsc);
785	return r;
786}
787
788static int __devexit bu21020_remove(struct spi_device *spi)
789{
790	struct bu21020 *ts = dev_get_drvdata(&spi->dev);
791
792	hrtimer_cancel(&ts->timer);
793	input_unregister_device(ts->idev);
794
795	kfree(ts);
796
797	return 0;
798}
799static int bu21020_suspend(struct spi_device *spi, pm_message_t message)
800{
801	struct bu21020 *ts = dev_get_drvdata(&spi->dev);
802	ts_pm_state.event = message.event;
803	hrtimer_cancel(&ts->timer);
804	return 0;
805}
806
807static int bu21020_resume(struct spi_device *spi)
808{
809	struct bu21020 *ts = dev_get_drvdata(&spi->dev);
810	ts_pm_state.event = PM_EVENT_RESUME;
811	init_bu21020_firm(spi);
812	init_bu21020_reg(spi);
813	hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
814	return 0;
815}
816
817static struct spi_driver bu21020_driver = {
818	.driver = {
819		.name = "bu21020",
820		.owner = THIS_MODULE,
821	},
822	.probe = bu21020_probe,
823	.remove = __devexit_p(bu21020_remove),
824	.suspend = bu21020_suspend,
825	.resume = bu21020_resume
826};
827
828static int __init bu21020_init(void)
829{
830	printk(KERN_INFO "BU21020 driver initializing\n");
831	rohm_wq = create_singlethread_workqueue("rohm_wq");
832	if (!rohm_wq) {
833		printk(KERN_ERR "create_singlethread_workqueue ERROR!! \n");
834		return -ENOMEM;
835	}	
836	return spi_register_driver(&bu21020_driver);
837}
838module_init(bu21020_init);
839
840static void __exit bu21020_exit(void)
841{
842	spi_unregister_driver(&bu21020_driver);
843	if (rohm_wq)
844		destroy_workqueue(rohm_wq);
845}
846module_exit(bu21020_exit);
847
848MODULE_AUTHOR("CT Cheng <ct.cheng@rohm.com.tw>");
849MODULE_LICENSE("GPL");
850MODULE_ALIAS("platform:bu21020");