/ANDROID_2.6.32-DS/ANDROID_2.6.32/drivers/input/touchscreen/rohm/rohm_bu21020.c
C | 850 lines | 589 code | 124 blank | 137 comment | 82 complexity | 8a421147599f2d56bc18c430a8ca3651 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /* drivers/input/touchscreen/rohm_bu21020.c
- * BU21020 touchscreen driver
- *
- * Copyright (C) 2010 ROHM SEMICONDUCTOR Co. Ltd.
- *
- * Author: CT Cheng <ct.cheng@rohm.com.tw>
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/input.h>
- #include <linux/interrupt.h>
- #include <linux/delay.h>
- #include <linux/gpio.h>
- #include <linux/spi/spi.h>
- #include <linux/hrtimer.h>
- #include <linux/spi/rohm_bu21020.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- #include <linux/poll.h>
- //#include "BU21020_firmware.h" /* BU21020 internal firmware */
- #include "bu21020.h"
- #define ROHM_TS_ABS_X_MIN 0
- #define ROHM_TS_ABS_X_MAX 799
- #define ROHM_TS_ABS_Y_MIN 0
- #define ROHM_TS_ABS_Y_MAX 479
- #define BU21020_HZ (10000000)
- // Register map
- #define BU21020_REG_X1H (0x20)
- #define BU21020_REG_X1L (0x21)
- #define BU21020_REG_Y1H (0x22)
- #define BU21020_REG_Y1L (0x23)
- #define BU21020_REG_X2H (0x24)
- #define BU21020_REG_X2L (0x25)
- #define BU21020_REG_Y2H (0x26)
- #define BU21020_REG_Y2L (0x27)
- // Command
- #define BU21020_CMD_W(addr) (addr) /* single write */
- #define BU21020_CMD_R(addr) (addr | 0x80) /* single read */
- #undef SW_AVG
- /********************************************/
- #ifdef SW_AVG
- #define BUFF_ARRAY 16
- #define DISTANCE_X 6
- #define DISTANCE_Y 6
- #define AVG_BOUND_X 4
- #define AVG_BOUND_Y 4
- #define S_DISTANCE_X 6
- #define S_DISTANCE_Y 6
- #define S_AVG_BOUND_X 4
- #define S_AVG_BOUND_Y 4
- #define MULTI_SKIP_TIMES 15
- #define SKIP_AVG_1 1
- #define SKIP_AVG_2 1
- struct touch_point
- {
- unsigned int x;
- unsigned int y;
- unsigned int buff_x[BUFF_ARRAY];
- unsigned int buff_y[BUFF_ARRAY];
- unsigned char buff_cnt;
- /* Previous coordinate of touch point after moving average calculating */
- unsigned int old_avg_x;
- unsigned int old_avg_y;
- };
- struct touch_point tp1, tp2;
- #endif
- extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
- extern int wmt_setsyspara(char *varname, char *varval);
- #define UBOOT_PARA_USED
- #define IOCTL_GET_CAL 0x1601
- #define IOCTL_SET_CAL 0x1602
- #define IOCTL_GET_RAW 0x1603
- #define IOCTL_SET_RAW 0x1604
- #define IOCTL_SET_RESOLUTION 0x1605
- #define IOCTL_DO_FILTER 0x1606
- #define IOCTL_SET_FILTER_DISTANCE 0x1607
- #define IOCTL_SET_SPI_FREQ 0x1608
- #define IOCTL_GET_SPI_FREQ 0x1609
- #define IOCTL_SET_DELAY_TIME 0x160A
- #define IOCTL_GET_DELAY_TIME 0x160B
- #define TS_IOC_MAGIC 't'
- #define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
- #define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
- #define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
- struct private_wmt_ts_s {
- /* module parameters */
- char *buf;
- /* char dev struct */
- struct cdev cdev;
- };
- static struct workqueue_struct *rohm_wq;
- static struct private_wmt_ts_s private_ts;
- static int private_wmt_dev_major = 160;
- static int private_wmt_dev_minor = 0 ;
- struct class *class_wmt_ts;
- static pm_message_t ts_pm_state = {
- .event = PM_EVENT_ON,
- };
- struct calibration_parameter g_CalcParam = {
- .a1 = 32602,
- .b1 = 339,
- .c1 = -1973856,
- .a2 = -99,
- .b2 = 23003,
- .c2 = -3520935,
- .delta = 37654,
- };
- struct bu21020
- {
- struct spi_device *spi;
- struct input_dev *idev;
- char phys[32];
- struct hrtimer timer;
- struct work_struct work;
- };
- /*
- * brief : set calibration information from BOOT ROM
- */
- int set_twoD_calibration_info(void) {
- int retval;
- char buf[160];
- sprintf(buf, "%d %d %d %d %d %d %d",
- g_CalcParam.a1,
- g_CalcParam.b1,
- g_CalcParam.c1,
- g_CalcParam.a2,
- g_CalcParam.b2,
- g_CalcParam.c2,
- g_CalcParam.delta
- );
- #ifdef UBOOT_PARA_USED
- retval = wmt_setsyspara("wmt.io.ts.2dcal", buf);
- #endif
- retval = 0;
- return retval;
- }
- int get_twoD_calibration_info(void) {
- int retval;
- char *varname = "wmt.io.ts.2dcal";
- #ifdef UBOOT_PARA_USED
- int varlen = 160;
- #endif
- unsigned char buf[160];
- #ifdef UBOOT_PARA_USED
- retval = wmt_getsyspara(varname, buf, &varlen);
- #else
- retval = 1;
- #endif
- if (retval != 0) {
- printk("Use default Calibration points\n");
- return retval;
- } else
- printk("%s = %s\n",varname, buf);
- sscanf(buf, "%d %d %d %d %d %d %d",
- &g_CalcParam.a1,
- &g_CalcParam.b1,
- &g_CalcParam.c1,
- &g_CalcParam.a2,
- &g_CalcParam.b2,
- &g_CalcParam.c2,
- &g_CalcParam.delta);
- return retval;
- }
- static inline void SPI_ByteWrite(struct spi_device *spi, u8 address, u8 data)
- {
- char tx_buf[2];
- int ret;
- tx_buf[0] = address;
- tx_buf[1] = data;
- ret = spi_write(spi, tx_buf, 2);
- if (ret != 0)
- printk("spi write err\n");
- /*
- else
- printk("<1> Write reg(0x%x): 0x%x\n", address, data);
- */
- }
- static inline u8 SPI_ByteRead(struct spi_device *spi, u8 address)
- {
- u8 result;
- result = spi_w8r8(spi, BU21020_CMD_R(address));
- return result;
- }
- #ifdef SW_AVG
- //-----------------------------------------------------------------------------
- //
- //Coord_Avg
- //
- //-----------------------------------------------------------------------------
- static void Coord_Avg (struct touch_point *tp)
- {
- unsigned long temp_x = 0, temp_y = 0, temp_n = 0;
- unsigned int i;
- ////////////////////////////////////////
- // X1,Y1 Moving Avg
- ////////////////////////////////////////
- if ((tp->x != 0) && (tp->y != 0)) {
- if(tp->buff_cnt >= SKIP_AVG_1) {
- if(((abs(tp->buff_x[0] - tp->x) > DISTANCE_X) && (abs(tp->buff_y[0] - tp->y) > DISTANCE_Y)) ||
- ((abs(tp->buff_x[0] - tp->x) > S_DISTANCE_X) && (abs(tp->buff_y[0] - tp->y) < S_DISTANCE_Y)) ||
- ((abs(tp->buff_x[0] - tp->x) < S_DISTANCE_X) && (abs(tp->buff_y[0] - tp->y) > S_DISTANCE_Y)) ||
- (((tp->old_avg_x != 0) && (abs(tp->old_avg_x - tp->x) > AVG_BOUND_X)) &&
- ( (tp->old_avg_y != 0) && (abs(tp->old_avg_y - tp->y) > AVG_BOUND_Y))) ||
- (((tp->old_avg_x != 0) && (abs(tp->old_avg_x - tp->x) > S_AVG_BOUND_X)) &&
- ( (tp->old_avg_y != 0) && (abs(tp->old_avg_y - tp->y) < S_AVG_BOUND_Y)))||
- (((tp->old_avg_x != 0) && (abs(tp->old_avg_x - tp->x) < S_AVG_BOUND_X)) &&
- ( (tp->old_avg_y != 0) && (abs(tp->old_avg_y - tp->y) > S_AVG_BOUND_Y)))) {
- for (i = 0; i < tp->buff_cnt; i++) {
- tp->buff_x[tp->buff_cnt - i] = tp->buff_x[tp->buff_cnt - i - 1];
- tp->buff_y[tp->buff_cnt - i] = tp->buff_y[tp->buff_cnt - i - 1];
- }
- tp->buff_x[0] = tp->x;
- tp->buff_y[0] = tp->y;
-
- temp_x = 0; temp_y = 0; temp_n = 0;
-
- for (i = 0; i <= tp->buff_cnt; i++) {
- temp_x += ((unsigned long) (tp->buff_x[i] * (tp->buff_cnt - i + 1)));
- temp_y += ((unsigned long) (tp->buff_y[i] * (tp->buff_cnt - i + 1)));
- temp_n += (unsigned long) (tp->buff_cnt - i + 1);
- }
- tp->x = temp_x / temp_n;
- tp->y = temp_y / temp_n;
-
- tp->old_avg_x = tp->x;
- tp->old_avg_y = tp->y;
- if (tp->buff_cnt < (BUFF_ARRAY-1))
- tp->buff_cnt++;
- } else {
- tp->x = tp->old_avg_x;
- tp->y = tp->old_avg_y;
- }
- } else {
- for (i = 0; i < tp->buff_cnt; i++) {
- tp->buff_x[tp->buff_cnt - i] = tp->buff_x[tp->buff_cnt - i - 1];
- tp->buff_y[tp->buff_cnt - i] = tp->buff_y[tp->buff_cnt - i - 1];
- }
- tp->buff_x[0] = tp->x;
- tp->buff_y[0] = tp->y;
- if(tp->buff_cnt < (BUFF_ARRAY-1))
- tp->buff_cnt++;
- tp->old_avg_x = tp->x;
- tp->old_avg_y = tp->y;
- tp->x = 0;
- tp->y = 0;
- }
- } else {//End/ of "if((x1 != 0) && (y1 != 0))"
- tp->buff_cnt = 0;
- if((tp->buff_x[0] != 0) && (tp->buff_y[0] != 0)) {
- tp->x = tp->buff_x[0];
- tp->y = tp->buff_y[0];
- } else {
- tp->x = 0;
- tp->y = 0;
- }
- tp->buff_x[0] = 0;
- tp->buff_y[0] = 0;
- tp->old_avg_x = 0;
- tp->old_avg_y = 0;
- }
- }
- #endif
- static u16 cal_data[2];
- static void twoDconvert(u32 *cal_x, u32 *cal_y )
- {
- int UncalX;
- int UncalY;
- int x,y;
- UncalX = (int) *cal_x;
- UncalY = (int) *cal_y;
- x = (g_CalcParam.a1 * UncalX + g_CalcParam.b1 * UncalY +
- g_CalcParam.c1) / g_CalcParam.delta;
- y = (g_CalcParam.a2 * UncalX + g_CalcParam.b2 * UncalY +
- g_CalcParam.c2) / g_CalcParam.delta;
- if (x < 0)
- x = 0;
- if (y < 0)
- y = 0;
- *cal_x = (u32)x;
- *cal_y = (u32)y;
- }
- static void rohm_ts_work_func(struct work_struct *work)
- {
- //define ouput data start
- unsigned int finger;
- unsigned int x1, y1, x2, y2;
- struct bu21020 *tsc = container_of(work, struct bu21020, work);
- //Get the coordinate of point 1 and point 2
- /*
- x1 = (SPI_ByteRead(tsc->spi, BU21020_REG_X1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X1L);
- y1 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y1L);
- x2 = (SPI_ByteRead(tsc->spi, BU21020_REG_X2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X2L);
- y2 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y2L);
- */
- y1 = (SPI_ByteRead(tsc->spi, BU21020_REG_X1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X1L);
- x1 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y1H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y1L);
- y2 = (SPI_ByteRead(tsc->spi, BU21020_REG_X2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_X2L);
- x2 = (SPI_ByteRead(tsc->spi, BU21020_REG_Y2H) << 2) | SPI_ByteRead(tsc->spi, BU21020_REG_Y2L);
- //printk(" x1 = %3d, y1 = %3d,x2 = %3d, y2 = %3d, \n", x1, y1, x2, y2);
- cal_data[0] = x1;
- cal_data[1] = y1;
-
- if (x1 != 0 && y1 != 0)
- twoDconvert(&x1, &y1);
- if (x2 != 0 && y2 != 0)
- twoDconvert(&x2, &y2);
- /*
- printk(" x1 = %3d, y1 = %3d,x2 = %3d, y2 = %3d, \n", x1, y1, x2, y2);
- */
- SPI_ByteWrite(tsc->spi, 0x3E, 0xFF);
- #ifdef SW_AVG
- tp1.x = x1;
- tp1.y = y1;
- Coord_Avg(&tp1);
- x1 = tp1.x;
- y1 = tp1.y;
- tp2.x = x2;
- tp2.y = y2;
- Coord_Avg(&tp2);
- x2 = tp2.x;
- y2 = tp2.y;
- #endif
-
- if (((y1 > 0) && (x1 > 0)) && ((y2 > 0) && (x2 > 0))) {
- finger = 2;
- } else if (((y1 > 0) && (x1 > 0)) || ((y2 > 0) && (x2 > 0))) {
- finger = 1;
- if ((x2 != 0) && (y2 != 0)) {
- x1 = x2;
- y1 = y2;
- x2 = 0;
- y2 = 0;
- }
- } else {
- finger = 0;
- }
- /*
- printk(" x1 = %3d, y1 = %3d,x2 = %3d, y2 = %3d, \n", x1, y1, x2, y2);
- */
- if(finger == 0)
- input_report_abs(tsc->idev, ABS_MT_TOUCH_MAJOR, 0);
- else
- input_report_abs(tsc->idev, ABS_MT_TOUCH_MAJOR, 3);
- /*
- input_report_abs(tsc->idev, ABS_MT_WIDTH_MAJOR, 0);
- */
- input_report_abs(tsc->idev, ABS_MT_POSITION_X, x1);
- input_report_abs(tsc->idev, ABS_MT_POSITION_Y, y1);
- input_mt_sync(tsc->idev);
- if (finger == 2) {
- input_report_abs(tsc->idev, ABS_MT_TOUCH_MAJOR, 3);
- /*
- input_report_abs(tsc->idev, ABS_MT_WIDTH_MAJOR, 0);
- */
- input_report_abs(tsc->idev, ABS_MT_POSITION_X, x2);
- input_report_abs(tsc->idev, ABS_MT_POSITION_Y, y2);
- input_mt_sync(tsc->idev);
- }
- input_report_abs(tsc->idev, ABS_PRESSURE, 0); // 0 touch_pressure
- input_report_abs(tsc->idev, ABS_TOOL_WIDTH, 0); // 0 touch_width,File system do judge this register
- input_report_key(tsc->idev, BTN_TOUCH,finger); // finger num 0, 1, 2
- input_report_key(tsc->idev, BTN_2, finger > 1); // finger2 state 0, 0, 1
- input_sync(tsc->idev); // up load data
- }
- static enum hrtimer_restart rohm_ts_timer_func(struct hrtimer *timer)
- {
- struct bu21020 *tsc = container_of(timer, struct bu21020, timer);
- queue_work(rohm_wq, &tsc->work);
- hrtimer_start(&tsc->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);/*report rate 1/12500000=80Hz*/
- return HRTIMER_NORESTART;
- }
- static int __devinit bu21020_ts_init(struct bu21020 *ts,
- struct bu21020_platform_data *pdata)
- {
- struct input_dev *idev;
- int r;
- idev = input_allocate_device();
- if (idev == NULL) {
- r = -ENOMEM;
- goto err;
- }
- idev->name = "BU21020 touchscreen";
- /*Dean-
- snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts",
- ts->spi->dev.bus_id);
- */
- /*Dean+*/
- snprintf(ts->phys, sizeof(ts->phys), "input-ts");
- idev->phys = ts->phys;
- idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
- idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- ts->idev = idev;
- ////////////////////////////////////////////////////////////////////////////
- input_set_abs_params(idev, ABS_MT_POSITION_X, ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
- input_set_abs_params(idev, ABS_MT_POSITION_Y, ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
- input_set_abs_params(idev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
- //input_set_abs_params(idev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
- ////////////////////////////////////////////////////////////////////////////
- //input_set_abs_params(idev, ABS_X, ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
- //input_set_abs_params(idev, ABS_Y, ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
- input_set_abs_params(idev, ABS_PRESSURE, 0, 1550, 0 , 0); //1550 two point
- input_set_abs_params(idev, ABS_TOOL_WIDTH, 0, 15, 0 , 0); //15 two point
- //input_set_abs_params(idev, ABS_HAT0X, ROHM_TS_ABS_X_MIN, ROHM_TS_ABS_X_MAX, 0, 0);
- //input_set_abs_params(idev, ABS_HAT0Y, ROHM_TS_ABS_Y_MIN, ROHM_TS_ABS_Y_MAX, 0, 0);
- //bu21020_start_scan(ts);
- r = input_register_device(idev);
- if (r < 0) {
- dev_err(&ts->spi->dev, "can't register touchscreen device\n");
- goto err;
- }
- return 0;
- err:
- return r;
- }
- static int private_wmt_ts_ioctl(
- struct inode *inode, /*!<; //[IN] a pointer point to struct inode */
- struct file *filp, /*!<; //[IN] a pointer point to struct file */
- unsigned int cmd, /*!<; // please add parameters description her*/
- unsigned long arg /*!<; // please add parameters description her*/
- )
- {
- int nBuff[7];
- int retval = 0;
- switch (cmd) {
- case TS_IOCTL_CAL_START:
- /*
- printk("TS_IOCTL_CAL_START\n");
- */
- break;
- case TS_IOCTL_CAL_DONE:
- /*
- printk("TS_IOCTL_CAL_DONE\n");
- */
- copy_from_user(nBuff, (unsigned int*)arg, 7*sizeof(int));
- g_CalcParam.a1 = nBuff[0];
- g_CalcParam.b1 = nBuff[1];
- g_CalcParam.c1 = nBuff[2];
- g_CalcParam.a2 = nBuff[3];
- g_CalcParam.b2 = nBuff[4];
- g_CalcParam.c2 = nBuff[5];
- g_CalcParam.delta = nBuff[6];
- /*
- printk("g_CalcParam = %d, %d, %d, %d, %d, %d, %d\n",
- g_CalcParam.a1, g_CalcParam.b1, g_CalcParam.c1,
- g_CalcParam.a2, g_CalcParam.b2, g_CalcParam.c2, g_CalcParam.delta);
- */
- set_twoD_calibration_info();
- break;
- case TS_IOCTL_GET_RAWDATA:
- /*
- printk("TS_IOCTL_GET_RAWDATA\n");
- */
- nBuff[0] = cal_data[0];
- nBuff[1] = cal_data[1];
- copy_to_user((unsigned int*)arg, nBuff, 2*sizeof(int));
- /*
- printk("x = %d, y = %d\n", nBuff[0], nBuff[1]);
- */
- break;
- default:
- retval = -EINVAL;
- break;
- }
- return retval;
- }
- static int private_wmt_ts_open(
- struct inode *inode, /*!<; //[IN] a pointer point to struct inode */
- struct file *filp /*!<; //[IN] a pointer point to struct file */
- )
- {
- struct private_wmt_ts_s *dev;
- /*
- printk("wmt_ts_open\n");
- */
- dev = container_of(inode->i_cdev, struct private_wmt_ts_s, cdev);
- filp->private_data = dev;
- return 0;
- }
- static int private_wmt_ts_release(
- struct inode *inode, /*!<; //[IN] a pointer point to struct inode */
- struct file *filp /*!<; //[IN] a pointer point to struct file */
- )
- {
- /*
- printk("wmt_ts_release\n");
- */
- return 0;
- }
- struct file_operations wmt_ts_fops = {
- .owner = THIS_MODULE,
- .open = private_wmt_ts_open,
- .ioctl = private_wmt_ts_ioctl,
- .release = private_wmt_ts_release,
- };
- // Firmware Download
- static int init_bu21020_firm(struct spi_device *spi)
- {
- ////////////////////////////////////////////////////////////////////////
- // Download BU21020 Firmware by HOST
- ////////////////////////////////////////////////////////////////////////
- // Wait 200usec for Reset
- int i = 0;
- SPI_ByteWrite(spi, 0x40, 0x00);
- udelay(200);
- SPI_ByteWrite(spi, 0x30, 0x02);
- SPI_ByteWrite(spi, 0x40, 0x01);
- // Wait 100usec for POWER-ON
- udelay(100);
- // Beginning address setting of program memory for host download
- SPI_ByteWrite(spi, 0x70, 0x00);
- SPI_ByteWrite(spi, 0x71, 0x00);
- // Download firmware to BU21020
- printk("BU21020 firmware download starts!\n");
- for(i = 0; i < CODESIZE; i++)
- SPI_ByteWrite(spi, 0x72, program[i]);
- printk("BU21020 firmware download is completed!\n");
- // Clear all Interrupt
- SPI_ByteWrite(spi, 0x3E, 0xFF);
- return 0;
- }
- // Initial Setting (For Register Setting)
- static int init_bu21020_reg(struct spi_device *spi)
- {
- ////////////////////////////////////////////////////////////////////////
- // Init BU21020
- ////////////////////////////////////////////////////////////////////////
- SPI_ByteWrite(spi, 0x40, 0x00);
- SPI_ByteWrite(spi, 0x30, 0x46);
- SPI_ByteWrite(spi, 0x40, 0x01);
- // Wait 100usec for Power-on
- udelay(100);
- SPI_ByteWrite(spi, 0x31, 0xE6);
- SPI_ByteWrite(spi, 0x32, 0x62);
-
-
- SPI_ByteWrite(spi, 0x35, 0xB0);
- SPI_ByteWrite(spi, 0x34, 0x78);
-
- /*
- SPI_ByteWrite(spi, 0x35, 0xB0);
- SPI_ByteWrite(spi, 0x34, 0x78);
- */
- SPI_ByteWrite(spi, 0x36, 0x08);
- SPI_ByteWrite(spi, 0x37, 0x08);
- SPI_ByteWrite(spi, 0x3A, 0x0F);
-
- //Change AD timing
- SPI_ByteWrite(spi, 0x50, 0x00);
- SPI_ByteWrite(spi, 0x52, 0x08);
- SPI_ByteWrite(spi, 0x56, 0xFF);
- //SPI_ByteWrite(spi, 0x60, 0x04);
- SPI_ByteWrite(spi, 0x61, 0x0A);
- SPI_ByteWrite(spi, 0x62, 0x0F);
- printk("Dean revised1111\n");
- SPI_ByteWrite(spi, 0x64, 0x5C);
- SPI_ByteWrite(spi, 0x63, 0xD6);
- SPI_ByteWrite(spi, 0x65, 0x01);
- // CPU power on
- SPI_ByteWrite(spi, 0x40, 0x03);
- // Clear all Interrupt
- SPI_ByteWrite(spi, 0x3E, 0xFF);
- return 0;
- }
- static int __devinit bu21020_probe(struct spi_device *spi)
- {
- struct bu21020 *tsc;
- struct bu21020_platform_data *pdata = spi->dev.platform_data;
- int r;
- #if 1
- unsigned char version = 0;
- #endif
- #if 0
- int i;
- #endif
- dev_t dev_no;
- struct cdev *cdev;
- dev_no = MKDEV(private_wmt_dev_major, private_wmt_dev_minor);
- cdev = &private_ts.cdev;
- cdev_init(cdev,&wmt_ts_fops);
- cdev_add(cdev, dev_no, 8);
- class_wmt_ts = class_create(THIS_MODULE, "wmtts");
- device_create(class_wmt_ts, NULL ,MKDEV(private_wmt_dev_major,private_wmt_dev_minor),
- NULL, "wmtts");
- printk(KERN_ERR "ROHM BU21020 rohm_ts_probe!\n");
- if (!pdata) {
- dev_dbg(&spi->dev, "no platform data?\n");
- return -ENODEV;
- }
- tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
- if (tsc == NULL)
- return -ENOMEM;
- dev_set_drvdata(&spi->dev, tsc);
- tsc->spi = spi;
- spi->dev.power.power_state = PMSG_ON;
- spi->mode = SPI_MODE_3;
- spi->bits_per_word = 8;
- /* The max speed might've been defined by the board-specific
- * struct */
- if (!spi->max_speed_hz)
- spi->max_speed_hz = BU21020_HZ;
- spi_setup(spi);
- INIT_WORK(&tsc->work, rohm_ts_work_func);
- #if 1
- init_bu21020_firm(spi);
- init_bu21020_reg(spi);
- #endif
- #if 0
- ////////////////////////////////////////////////////////////////////////
- // Init BU21020
- ////////////////////////////////////////////////////////////////////////
- // Wait 200usec for Reset
- /*
- SPI_ByteWrite(spi, 0x40, 0x00);
- udelay(200);
- */
- SPI_ByteWrite(spi, 0x40, 0x01);
- udelay(200);
- SPI_ByteWrite(spi, 0x30, 0x46);
- SPI_ByteWrite(spi, 0x31, 0xE6);
- SPI_ByteWrite(spi, 0x32, 0x62);
-
- /*
- SPI_ByteWrite(spi, 0x35, 0x78);
- SPI_ByteWrite(spi, 0x34, 0xB0);
- */
- SPI_ByteWrite(spi, 0x34, 0x78);
- SPI_ByteWrite(spi, 0x35, 0xB0);
- SPI_ByteWrite(spi, 0x36, 0x08);
- SPI_ByteWrite(spi, 0x37, 0x08);
- SPI_ByteWrite(spi, 0x3A, 0x0F);
- SPI_ByteWrite(spi, 0x56, 0xFF);
- SPI_ByteWrite(spi, 0x61, 0x0A);
- SPI_ByteWrite(spi, 0x62, 0x0F);
- SPI_ByteWrite(spi, 0x63, 0x5C);
- SPI_ByteWrite(spi, 0x64, 0xD6);
- /*
- SPI_ByteWrite(spi, 0x63, 0xE0);
- SPI_ByteWrite(spi, 0x64, 0xE4);
- */
- SPI_ByteWrite(spi, 0x65, 0x01);
- SPI_ByteWrite(spi, 0x40, 0x01);
- // Wait 100usec for Power-on
- udelay(100);
- // Beginning address setting of program memory for host download
- SPI_ByteWrite(spi, 0x70, 0x00);
- SPI_ByteWrite(spi, 0x71, 0x00);
- // Download firmware to BU21020
- printk("BU21020 firmware download starts!\n");
- for(i = 0; i < CODESIZE; i++)
- SPI_ByteWrite(spi, 0x72, program[i]);
- printk("BU21020 firmware download is completed!\n");
- // Download path setting
- SPI_ByteWrite(spi, 0x3E, 0xFF);
-
- //Change AD timing
- //SPI_ByteWrite(spi, 0x50, 0x00);
- SPI_ByteWrite(spi, 0x52, 0x08);
- // CPU power on
- SPI_ByteWrite(spi, 0x40, 0x03);
- // Clear all Interrupt
- SPI_ByteWrite(spi, 0x3E, 0xFF);
- #endif
- #if 1 /*for debug*/
- mdelay(10);
- version = SPI_ByteRead(spi, 0x5f);
- printk("BU21020 firmware version = %x\n", version);
- #endif
- // Init end
- ////////////////////////////////////////////////////////////////////////
- r = bu21020_ts_init(tsc, pdata);
- /* Timer init*/
- hrtimer_init(&tsc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- tsc->timer.function = rohm_ts_timer_func;
- hrtimer_start(&tsc->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
- get_twoD_calibration_info();
- if (r)
- goto err1;
- return 0;
- err1:
- kfree(tsc);
- return r;
- }
- static int __devexit bu21020_remove(struct spi_device *spi)
- {
- struct bu21020 *ts = dev_get_drvdata(&spi->dev);
- hrtimer_cancel(&ts->timer);
- input_unregister_device(ts->idev);
- kfree(ts);
- return 0;
- }
- static int bu21020_suspend(struct spi_device *spi, pm_message_t message)
- {
- struct bu21020 *ts = dev_get_drvdata(&spi->dev);
- ts_pm_state.event = message.event;
- hrtimer_cancel(&ts->timer);
- return 0;
- }
- static int bu21020_resume(struct spi_device *spi)
- {
- struct bu21020 *ts = dev_get_drvdata(&spi->dev);
- ts_pm_state.event = PM_EVENT_RESUME;
- init_bu21020_firm(spi);
- init_bu21020_reg(spi);
- hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
- return 0;
- }
- static struct spi_driver bu21020_driver = {
- .driver = {
- .name = "bu21020",
- .owner = THIS_MODULE,
- },
- .probe = bu21020_probe,
- .remove = __devexit_p(bu21020_remove),
- .suspend = bu21020_suspend,
- .resume = bu21020_resume
- };
- static int __init bu21020_init(void)
- {
- printk(KERN_INFO "BU21020 driver initializing\n");
- rohm_wq = create_singlethread_workqueue("rohm_wq");
- if (!rohm_wq) {
- printk(KERN_ERR "create_singlethread_workqueue ERROR!! \n");
- return -ENOMEM;
- }
- return spi_register_driver(&bu21020_driver);
- }
- module_init(bu21020_init);
- static void __exit bu21020_exit(void)
- {
- spi_unregister_driver(&bu21020_driver);
- if (rohm_wq)
- destroy_workqueue(rohm_wq);
- }
- module_exit(bu21020_exit);
- MODULE_AUTHOR("CT Cheng <ct.cheng@rohm.com.tw>");
- MODULE_LICENSE("GPL");
- MODULE_ALIAS("platform:bu21020");