diff --git a/arch/arm/mach-msm/board-htcleo-bl-led.c b/arch/arm/mach-msm/board-htcleo-bl-led.c index 54dbf099..3a492260 100644 --- a/arch/arm/mach-msm/board-htcleo-bl-led.c +++ b/arch/arm/mach-msm/board-htcleo-bl-led.c @@ -37,10 +37,13 @@ #define LCMDBG(fmt, arg...) {} #endif +#define HTCLEO_DEFAULT_BACKLIGHT_BRIGHTNESS 255 + static struct led_trigger *htcleo_lcd_backlight; static int auto_bl_state=0; +static DEFINE_MUTEX(htcleo_backlight_lock); -int htcleo_brightness_autobacklight(uint8_t value) +static int htcleo_brightness_autobacklight(uint8_t value) { int ret; uint8_t data[2]; @@ -73,16 +76,18 @@ static ssize_t htcleo_auto_bl_set(struct device *dev, const char *buf, size_t count) { int set_state; + mutex_lock(&htcleo_backlight_lock); sscanf(buf, "%d", &set_state); if(set_state!=0 && set_state!=1) return -EINVAL; htcleo_brightness_autobacklight(set_state); + mutex_unlock(&htcleo_backlight_lock); return count; } static DEVICE_ATTR(auto_bl, 0644, htcleo_auto_bl_get, htcleo_auto_bl_set); -int htcleo_brightness_onoff_bkl(int enable) +static int htcleo_brightness_onoff_bkl(int enable) { int ret; uint8_t data[1]; @@ -94,7 +99,7 @@ int htcleo_brightness_onoff_bkl(int enable) return 0; } -int htcleo_brightness_set_bkl(uint8_t value) +static int htcleo_brightness_set_bkl(uint8_t value) { int ret; uint8_t cmd[2]; @@ -118,13 +123,14 @@ int htcleo_brightness_set_bkl(uint8_t value) return 0; } -void htcleo_brightness_set(struct led_classdev *led_cdev, enum led_brightness val) +static void htcleo_brightness_set(struct led_classdev *led_cdev, enum led_brightness val) { - led_cdev->brightness = val; + mutex_lock(&htcleo_backlight_lock); // set brigtness level via MicroP LCMDBG("htcleo_brightness_set: %d\n", val); if (val > 255) val = 255; + led_cdev->brightness = val; if (val < 30) { htcleo_brightness_onoff_bkl(0); @@ -134,13 +140,20 @@ void htcleo_brightness_set(struct led_classdev *led_cdev, enum led_brightness va htcleo_brightness_onoff_bkl(1); htcleo_brightness_set_bkl((val - 30) / 23); } + mutex_unlock(&htcleo_backlight_lock); +} + +static enum led_brightness htcleo_brightness_get(struct led_classdev *led_cdev) +{ + return led_cdev->brightness; } static struct led_classdev htcleo_backlight_led = { .name = "lcd-backlight", - .brightness = LED_FULL, + .brightness = HTCLEO_DEFAULT_BACKLIGHT_BRIGHTNESS, .brightness_set = htcleo_brightness_set, + .brightness_get = htcleo_brightness_get, }; static int htcleo_backlight_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-msm/board-htcleo-bl.c b/arch/arm/mach-msm/board-htcleo-bl.c index edb44b04..7d7525f3 100644 --- a/arch/arm/mach-msm/board-htcleo-bl.c +++ b/arch/arm/mach-msm/board-htcleo-bl.c @@ -41,24 +41,6 @@ #define HTCLEO_MAX_BRIGHTNESS 255 -int htcleo_brightness_autobacklight(uint8_t value) -{ - int ret; - uint8_t data[2]; - - LCMDBG("%s:(%d)\n", __func__, value); - - data[0] = 1; - data[1] = value; - ret = microp_i2c_write(MICROP_I2C_WCMD_AUTO_BL_CTL, data, 2); - if (ret != 0) - pr_err("%s: set auto light sensor fail\n", __func__); - - - return ret; -} -EXPORT_SYMBOL(htcleo_brightness_autobacklight); - int htcleo_brightness_onoff_bkl(int enable) { int ret; @@ -74,7 +56,7 @@ int htcleo_brightness_onoff_bkl(int enable) int htcleo_brightness_set_bkl(uint8_t value) { int ret; - uint8_t cmd[2]; + uint8_t cmd[2], data[2]; LCMDBG("microp_set_bkl(%d)\n", value); @@ -82,9 +64,18 @@ int htcleo_brightness_set_bkl(uint8_t value) { value = 9; } + // disable autobrigtness +// CotullaTEST: Lsensor test, add 0x100 +// data[0] = 0; + data[0] = 1; + data[1] = 0; + ret = microp_i2c_write(MICROP_I2C_WCMD_AUTO_BL_CTL, data, 2); // 23 + if (ret != 0) + pr_err("%s: set auto light sensor fail\n", __func__); // setvalue cmd[0] = value << 4; +// printk("22LEVEL %02X\n", cmd[0]); ret = microp_i2c_write(MICROP_I2C_WCMD_LCM_BL_MANU_CTL, cmd, 1); // 22 if (ret < 0) { @@ -136,8 +127,6 @@ static struct backlight_ops htcleo_backlight_ops = static int htcleo_backlight_probe(struct platform_device *pdev) { struct backlight_device *bd; - ret = device_create_file(&client->dev, &dev_attr_reset); - bd = backlight_device_register("htcleo-backlight", &pdev->dev, NULL, &htcleo_backlight_ops); bd->props.max_brightness = HTCLEO_MAX_BRIGHTNESS; bd->props.brightness = HTCLEO_MAX_BRIGHTNESS; diff --git a/arch/arm/mach-msm/board-htcleo-keypad.c b/arch/arm/mach-msm/board-htcleo-keypad.c index b28ac502..3117a245 100644 --- a/arch/arm/mach-msm/board-htcleo-keypad.c +++ b/arch/arm/mach-msm/board-htcleo-keypad.c @@ -26,8 +26,10 @@ #include "board-htcleo.h" +#define HTCLEO_DEFAULT_KEYPAD_BRIGHTNESS 0 +static DEFINE_MUTEX(htcleo_keypad_brightness_lock); + struct led_data { - struct led_classdev ldev; struct mutex led_data_mutex; struct work_struct brightness_work; spinlock_t brightness_lock; @@ -169,6 +171,7 @@ static void keypad_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { unsigned long flags; + mutex_lock(&htcleo_keypad_brightness_lock); pr_debug("Setting %s brightness current %d new %d\n", led_cdev->name, led_cdev->brightness, brightness); @@ -182,8 +185,21 @@ static void keypad_led_brightness_set(struct led_classdev *led_cdev, spin_unlock_irqrestore(&keypad_led_data.brightness_lock, flags); schedule_work(&keypad_led_data.brightness_work); + mutex_unlock(&htcleo_keypad_brightness_lock); } +static enum led_brightness keypad_led_brightness_get(struct led_classdev *led_cdev) +{ + return led_cdev->brightness; +} + +static struct led_classdev htcleo_backlight_led = +{ + .name = "button-backlight", + .brightness = HTCLEO_DEFAULT_KEYPAD_BRIGHTNESS, + .brightness_set = keypad_led_brightness_set, + .brightness_get = keypad_led_brightness_get, +}; static int __init htcleo_init_keypad(void) { @@ -214,15 +230,12 @@ static int __init htcleo_init_keypad(void) goto err_gpio_kpl; } - keypad_led_data.ldev.name = "button-backlight"; - keypad_led_data.ldev.brightness_set = keypad_led_brightness_set; keypad_led_data.oldval = 0; mutex_init(&keypad_led_data.led_data_mutex); INIT_WORK(&keypad_led_data.brightness_work, keypad_led_brightness_set_work); spin_lock_init(&keypad_led_data.brightness_lock); - ret = led_classdev_register(&htcleo_input_device.dev, &keypad_led_data.ldev); + ret = led_classdev_register(&htcleo_input_device.dev, &htcleo_backlight_led); if (ret) { - keypad_led_data.ldev.name = NULL; goto exit; } diff --git a/arch/arm/mach-msm/board-htcleo-ts.c b/arch/arm/mach-msm/board-htcleo-ts.c index 7bbda383..465709df 100644 --- a/arch/arm/mach-msm/board-htcleo-ts.c +++ b/arch/arm/mach-msm/board-htcleo-ts.c @@ -39,649 +39,668 @@ #define TOUCH_TYPE_68 2 #define TOUCH_TYPE_2A 3 - #define LEO_TYPE_1 1 #define LEO_TYPE_2 2 #define LEO_TYPE_3 3 - - #define TYPE_68_DEVID (0x68 >> 1) #define TYPE_B8_DEVID (0xB8 >> 1) #define TYPE_2A_DEVID (0x2A >> 1) - +#define TS_USE_IRQ 1 #define MAKEWORD(a, b) ((uint16_t)(((uint8_t)(a)) | ((uint16_t)((uint8_t)(b))) << 8)) -struct leo_ts_data +struct htcleo_ts_data { - struct i2c_client *client; - struct input_dev *input_dev; - uint32_t prev_ptcount; - int ts_type; - int intr_type; // 0 - FAILING, 1- RISING - int pressed1; - int pressed2; - struct work_struct work; - uint16_t version; - struct early_suspend early_suspend; + struct i2c_client *client; + struct input_dev *input_dev; + uint32_t prev_ptcount; + int ts_type; + int intr_type; // 0 - FAILING, 1- RISING + int pressed1; + int pressed2; + struct work_struct work; +#ifndef TS_USE_IRQ + struct hrtimer timer; +#endif + uint16_t version; + struct early_suspend early_suspend; }; -struct workqueue_struct *leo_touch_wq; +struct workqueue_struct *htcleo_touch_wq; #ifdef CONFIG_HAS_EARLYSUSPEND -static void leo_ts_early_suspend(struct early_suspend *h); -static void leo_ts_late_resume(struct early_suspend *h); +static void htcleo_ts_early_suspend(struct early_suspend *h); +static void htcleo_ts_late_resume(struct early_suspend *h); #endif -static int I2C_Read(struct leo_ts_data *ts, uint8_t dev, uint8_t addr, uint32_t sz, uint8_t* bf) +static int I2C_Read(struct htcleo_ts_data *ts, uint8_t dev, uint8_t addr, uint32_t sz, uint8_t* bf) { - struct i2c_msg msg[2]; - int ret = 0; + struct i2c_msg msg[2]; + int ret = 0; - msg[0].addr = dev; - msg[0].flags = 0; - msg[0].len = 1; - msg[0].buf = &addr; + msg[0].addr = dev; + msg[0].flags = 0; + msg[0].len = 1; + msg[0].buf = &addr; - msg[1].addr = dev; - msg[1].flags = I2C_M_RD; - msg[1].len = sz; - msg[1].buf = bf; + msg[1].addr = dev; + msg[1].flags = I2C_M_RD; + msg[1].len = sz; + msg[1].buf = bf; - ret = i2c_transfer(ts->client->adapter, msg, 2); - if (ret < 0) - { - dev_dbg(&ts->client->dev, "TS: I2C_Read(%x %x) failed!\n", dev, addr); - return 0; - } - return 1; + ret = i2c_transfer(ts->client->adapter, msg, 2); + if (ret < 0) + { + dev_dbg(&ts->client->dev, "TS: I2C_Read(%x %x) failed!\n", dev, addr); + return 0; + } + return 1; } -static int I2C_ReadNo(struct leo_ts_data *ts, uint8_t dev, uint32_t sz, uint8_t* bf) +static int I2C_ReadNo(struct htcleo_ts_data *ts, uint8_t dev, uint32_t sz, uint8_t* bf) { - struct i2c_msg msg[1]; - int ret = 0; + struct i2c_msg msg[1]; + int ret = 0; - msg[0].addr = dev; - msg[0].flags = I2C_M_RD; - msg[0].len = sz; - msg[0].buf = bf; + msg[0].addr = dev; + msg[0].flags = I2C_M_RD; + msg[0].len = sz; + msg[0].buf = bf; - ret = i2c_transfer(ts->client->adapter, msg, 1); - if (ret < 0) - { - dev_dbg(&ts->client->dev, "TS: I2C_ReadNo(%x) failed!\n", dev); - return 0; - } - return 1; + ret = i2c_transfer(ts->client->adapter, msg, 1); + if (ret < 0) + { + dev_dbg(&ts->client->dev, "TS: I2C_ReadNo(%x) failed!\n", dev); + return 0; + } + return 1; } -static int leo_detect_ts_type(struct leo_ts_data *ts) +static int htcleo_detect_ts_type(struct htcleo_ts_data *ts) { - uint8_t bt[4]; + uint8_t bt[4]; - ts->ts_type = TOUCH_TYPE_UNKNOWN; - if (I2C_Read(ts, TYPE_B8_DEVID, 0x00, 1, bt)) - { - dev_dbg(&ts->client->dev, "TS: DETECTED TYPE B8\n"); - ts->ts_type = TOUCH_TYPE_B8; - return 1; - } + ts->ts_type = TOUCH_TYPE_UNKNOWN; + if (I2C_Read(ts, TYPE_B8_DEVID, 0x00, 1, bt)) + { + dev_dbg(&ts->client->dev, "TS: DETECTED TYPE B8\n"); + ts->ts_type = TOUCH_TYPE_B8; + return 1; + } - if (I2C_Read(ts, TYPE_68_DEVID, 0x00, 1, bt)) - { - dev_dbg(&ts->client->dev, "TS: DETECTED TYPE 68\n"); - ts->ts_type = TOUCH_TYPE_68; - return 1; - } + if (I2C_Read(ts, TYPE_68_DEVID, 0x00, 1, bt)) + { + dev_dbg(&ts->client->dev, "TS: DETECTED TYPE 68\n"); + ts->ts_type = TOUCH_TYPE_68; + return 1; + } - if (I2C_ReadNo(ts, TYPE_2A_DEVID, 4, bt) && bt[0] == 0x55) - { - dev_dbg(&ts->client->dev, "TS: DETECTED TYPE 2A\n"); - ts->ts_type = TOUCH_TYPE_2A; - return 1; - } - dev_dbg(&ts->client->dev, "TS: NOT DETECTED\n"); - return -1; + if (I2C_ReadNo(ts, TYPE_2A_DEVID, 4, bt) && bt[0] == 0x55) + { + dev_dbg(&ts->client->dev, "TS: DETECTED TYPE 2A\n"); + ts->ts_type = TOUCH_TYPE_2A; + return 1; + } + dev_dbg(&ts->client->dev, "TS: NOT DETECTED\n"); + return -1; } -static uint32_t touch_on_gpio_table[] = +static int htcleo_reset_ts(struct htcleo_ts_data *ts) { - PCOM_GPIO_CFG(HTCLEO_GPIO_TS_SEL, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_TS_POWER, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), - PCOM_GPIO_CFG(HTCLEO_GPIO_TS_IRQ, 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA), -}; + while (gpio_get_value(HTCLEO_GPIO_TS_POWER)) + { + gpio_set_value(HTCLEO_GPIO_TS_SEL, 1); + gpio_set_value(HTCLEO_GPIO_TS_POWER, 0); + gpio_set_value(HTCLEO_GPIO_TS_MULT, 0); + gpio_set_value(HTCLEO_GPIO_H2W_CLK, 0); + msleep(10); + } + gpio_set_value(HTCLEO_GPIO_TS_MULT, 1); + gpio_set_value(HTCLEO_GPIO_H2W_CLK, 1); -static int leo_reset_ts(struct leo_ts_data *ts) -{ -// only for XC - config_gpio_table(touch_on_gpio_table, ARRAY_SIZE(touch_on_gpio_table)); + while (!gpio_get_value(HTCLEO_GPIO_TS_POWER)) + { + gpio_set_value(HTCLEO_GPIO_TS_POWER, 1); + } + msleep(20); + while (gpio_get_value(HTCLEO_GPIO_TS_IRQ)) + { + msleep(10); + } - gpio_direction_output(HTCLEO_GPIO_TS_SEL, 1); - gpio_direction_output(HTCLEO_GPIO_TS_POWER, 0); -// gpio_direction_input(HTCLEO_GPIO_TS_IRQ); - msleep(100); -// gpio_configure(92, GPIOF_INPUT | IRQF_TRIGGER_FALLING); - -/* - while (gpio_get_value(HTCLEO_GPIO_TS_POWER)) - { - gpio_set_value(HTCLEO_GPIO_TS_SEL, 1); - gpio_set_value(HTCLEO_GPIO_TS_POWER, 0); - gpio_set_value(82, 0); - gpio_set_value(27, 0); - msleep(10); - } -*/ - gpio_set_value(82, 1); - gpio_set_value(27, 1); - - while (!gpio_get_value(HTCLEO_GPIO_TS_POWER)) - { - gpio_set_value(HTCLEO_GPIO_TS_POWER, 1); - } - msleep(20); - while (gpio_get_value(HTCLEO_GPIO_TS_IRQ)) - { - msleep(10); - } - - while (gpio_get_value(HTCLEO_GPIO_TS_SEL)) - { - gpio_set_value(HTCLEO_GPIO_TS_SEL, 0); - } - msleep(300); - dev_dbg(&ts->client->dev, "TS: reset done\n"); - return 1; + while (gpio_get_value(HTCLEO_GPIO_TS_SEL)) + { + gpio_set_value(HTCLEO_GPIO_TS_SEL, 0); + } + msleep(300); + dev_dbg(&ts->client->dev, "TS: reset done\n"); + return 1; } -static int leo_init_ts(struct leo_ts_data *ts) +static int htcleo_init_ts(struct htcleo_ts_data *ts) { - uint8_t bt[6]; - struct i2c_msg msg; - int ret; + uint8_t bt[6]; + struct i2c_msg msg; + int ret; - switch (ts->ts_type) - { - case TOUCH_TYPE_2A: - bt[0] = 0xD0; - bt[1] = 0x00; - bt[2] = 0x01; + switch (ts->ts_type) + { + case TOUCH_TYPE_2A: + bt[0] = 0xD0; + bt[1] = 0x00; + bt[2] = 0x01; - msg.addr = 0x2A >> 1; - msg.flags = 0; - msg.len = 3; - msg.buf = bt; + msg.addr = 0x2A >> 1; + msg.flags = 0; + msg.len = 3; + msg.buf = bt; - ret = i2c_transfer(ts->client->adapter, &msg, 1); - if (ret < 0) - { - goto error; - } - break; - default: - dev_dbg(&ts->client->dev, "TS: wrong type %x\n", ts->ts_type); - goto error; - } - dev_dbg(&ts->client->dev, "TS: init done\n"); - return 1; + ret = i2c_transfer(ts->client->adapter, &msg, 1); + if (ret < 0) + { + goto error; + } + break; + default: + dev_dbg(&ts->client->dev, "TS: wrong type %x\n", ts->ts_type); + goto error; + } + dev_dbg(&ts->client->dev, "TS: init done\n"); + return 1; error: - return -1; + return -1; } -static void leo_deinit_ts(void) +static void htcleo_deinit_ts(void) { gpio_set_value(HTCLEO_GPIO_TS_POWER, 0); } -static int leo_init_intr(struct leo_ts_data *ts) +static int htcleo_init_intr(struct htcleo_ts_data *ts) { - switch (ts->ts_type) - { - case TOUCH_TYPE_B8: - ts->intr_type = 1; - break; - case TOUCH_TYPE_68: - case TOUCH_TYPE_2A: - ts->intr_type = 0; - break; - default: - dev_dbg(&ts->client->dev, "TS: wrong type %x\n", ts->ts_type); - ts->intr_type = 0; - goto error; - } - return 1; -error: - return -1; -} - - -static void leo_ts_work_func(struct work_struct *work) -{ - uint8_t buf[9]; - uint32_t ptcount; - uint32_t ptx[2]; - uint32_t pty[2]; - struct leo_ts_data *ts = container_of(work, struct leo_ts_data, work); - int pressed1, pressed2; - - ptcount = 0; - switch (ts->ts_type) - { - case TOUCH_TYPE_2A: - if (!I2C_ReadNo(ts, TYPE_2A_DEVID, 9, buf)) + switch (ts->ts_type) { - dev_dbg(&ts->client->dev, "TS: ReadPos failed\n"); - goto error; + case TOUCH_TYPE_B8: + ts->intr_type = 1; + break; + case TOUCH_TYPE_68: + case TOUCH_TYPE_2A: + ts->intr_type = 0; + break; + default: + dev_dbg(&ts->client->dev, "TS: wrong type %x\n", ts->ts_type); + ts->intr_type = 0; + goto error; } - if (buf[0] != 0x5A) - { - dev_dbg(&ts->client->dev, "TS: ReadPos wrmark\n"); - goto error; - } - - ptcount = (buf[8] >> 1) & 3; - if (ptcount > 2) - { - ptcount = 2; - } - - if (ptcount >= 1) - { - ptx[0] = MAKEWORD(buf[2], (buf[1] & 0xF0) >> 4); - pty[0] = MAKEWORD(buf[3], (buf[1] & 0x0F) >> 0); - } - if (ptcount == 2) - { - ptx[1] = MAKEWORD(buf[5], (buf[4] & 0xF0) >> 4); - pty[1] = MAKEWORD(buf[6], (buf[4] & 0x0F) >> 0); - } - break; - default: - dev_dbg(&ts->client->dev, "TS: wrong type %x\n", ts->ts_type); - goto error; - } - - - if (ptcount == 0) - dev_dbg(&ts->client->dev, "TS: not pressed\n"); - else if (ptcount == 1) - dev_dbg(&ts->client->dev, "TS: pressed1 (%d, %d)\n", ptx[0], pty[0]); - else if (ptcount == 2) - dev_dbg(&ts->client->dev, "TS: pressed2 (%d, %d) (%d, %d)\n", ptx[0], pty[0], ptx[1], pty[1]); - else - dev_dbg(&ts->client->dev, "TS: BUGGY!\n"); - - - if (ptcount == 0) - { - pressed1 = 0; - pressed2 = 0; - } - else if (ptcount == 1) - { - pressed1 = 1; - pressed2 = 0; - } - else if (ptcount == 2) - { - pressed1 = 1; - pressed2 = 1; - } - else - { - pressed1 = 0; - pressed2 = 0; - } - - if (pressed1) - { - dev_dbg(&ts->client->dev, "pressed1\n"); - input_report_abs(ts->input_dev, ABS_X, ptx[0]); - input_report_abs(ts->input_dev, ABS_Y, pty[0]); - input_report_abs(ts->input_dev, ABS_PRESSURE, 100); - input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, 1); - input_report_key(ts->input_dev, BTN_TOUCH, 1); -#ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, ptx[0]); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pty[0]); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); -#endif - } - else if (ts->pressed1) - { - dev_dbg(&ts->client->dev, "unpressed1\n"); - input_report_abs(ts->input_dev, ABS_X, ptx[0]); - input_report_abs(ts->input_dev, ABS_Y, pty[0]); - input_report_abs(ts->input_dev, ABS_PRESSURE, 0); - input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, 0); - input_report_key(ts->input_dev, BTN_TOUCH, 0); -#ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, ptx[0]); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pty[0]); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); -#endif - } -#ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH - input_mt_sync(ts->input_dev); - - - if (pressed2) - { - dev_dbg(&ts->client->dev, "pressed2\n"); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, ptx[1]); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pty[1]); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); - } - else if (ts->pressed2) - { - dev_dbg(&ts->client->dev, "unpressed2\n"); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); - } - input_mt_sync(ts->input_dev); -#endif - input_sync(ts->input_dev); - - ts->pressed1 = pressed1; - ts->pressed2 = pressed2; - -error: - ts->prev_ptcount = ptcount; - - /* prepare for next intr */ - msleep(1); - enable_irq(ts->client->irq); + return 1; + error: + return -1; } -static irqreturn_t leo_ts_irq_handler(int irq, void *dev_id) + +static void htcleo_ts_work_func(struct work_struct *work) { - struct leo_ts_data *ts = dev_id; - disable_irq_nosync(ts->client->irq); - queue_work(leo_touch_wq, &ts->work); - return IRQ_HANDLED; + uint8_t buf[9]; + uint32_t ptcount; + uint32_t ptx[2]; + uint32_t pty[2]; + struct htcleo_ts_data *ts = container_of(work, struct htcleo_ts_data, work); + int pressed1, pressed2; + + ptcount = 0; + switch (ts->ts_type) + { + case TOUCH_TYPE_2A: + if (!I2C_ReadNo(ts, TYPE_2A_DEVID, 9, buf)) + { + dev_dbg(&ts->client->dev, "TS: ReadPos failed\n"); + goto error; + } + if (buf[0] != 0x5A) + { + dev_dbg(&ts->client->dev, "TS: ReadPos wrmark\n"); + goto error; + } + + ptcount = (buf[8] >> 1) & 3; + if (ptcount > 2) + { + ptcount = 2; + } + + if (ptcount >= 1) + { + ptx[0] = MAKEWORD(buf[2], (buf[1] & 0xF0) >> 4); + pty[0] = MAKEWORD(buf[3], (buf[1] & 0x0F) >> 0); + } + if (ptcount == 2) + { + ptx[1] = MAKEWORD(buf[5], (buf[4] & 0xF0) >> 4); + pty[1] = MAKEWORD(buf[6], (buf[4] & 0x0F) >> 0); + } + break; + default: + dev_dbg(&ts->client->dev, "TS: wrong type %x\n", ts->ts_type); + goto error; + } + + + if (ptcount == 0) + dev_dbg(&ts->client->dev, "TS: not pressed\n"); + else if (ptcount == 1) + dev_dbg(&ts->client->dev, "TS: pressed1 (%d, %d)\n", ptx[0], pty[0]); + else if (ptcount == 2) + dev_dbg(&ts->client->dev, "TS: pressed2 (%d, %d) (%d, %d)\n", ptx[0], pty[0], ptx[1], pty[1]); + else + dev_dbg(&ts->client->dev, "TS: BUGGY!\n"); + + + if (ptcount == 0) + { + pressed1 = 0; + pressed2 = 0; + } + else if (ptcount == 1) + { + pressed1 = 1; + pressed2 = 0; + } + else if (ptcount == 2) + { + pressed1 = 1; + pressed2 = 1; + } + else + { + pressed1 = 0; + pressed2 = 0; + } + + if (pressed1) + { + dev_dbg(&ts->client->dev, "pressed1\n"); + input_report_abs(ts->input_dev, ABS_X, ptx[0]); + input_report_abs(ts->input_dev, ABS_Y, pty[0]); + input_report_abs(ts->input_dev, ABS_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, 1); + input_report_key(ts->input_dev, BTN_TOUCH, 1); +#ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, ptx[0]); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pty[0]); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); +#endif + } + else if (ts->pressed1) + { + dev_dbg(&ts->client->dev, "unpressed1\n"); + input_report_abs(ts->input_dev, ABS_X, ptx[0]); + input_report_abs(ts->input_dev, ABS_Y, pty[0]); + input_report_abs(ts->input_dev, ABS_PRESSURE, 0); + input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, 0); + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, ptx[0]); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pty[0]); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); +#endif + } + #ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH + input_mt_sync(ts->input_dev); + + + if (pressed2) + { + dev_dbg(&ts->client->dev, "pressed2\n"); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, ptx[1]); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, pty[1]); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); + } + else if (ts->pressed2) + { + dev_dbg(&ts->client->dev, "unpressed2\n"); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + } + input_mt_sync(ts->input_dev); + #endif + input_sync(ts->input_dev); + + ts->pressed1 = pressed1; + ts->pressed2 = pressed2; + + error: + ts->prev_ptcount = ptcount; + + /* prepare for next intr */ + enable_irq(ts->client->irq); } +#ifndef TS_USE_IRQ +static enum hrtimer_restart htcleo_ts_timer_func(struct hrtimer *timer) +{ + struct htcleo_ts_data *ts = container_of(timer, struct htcleo_ts_data, timer); + queue_work(htcleo_touch_wq, &ts->work); + hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} +#else +static irqreturn_t htcleo_ts_irq_handler(int irq, void *dev_id) +{ + struct htcleo_ts_data *ts = dev_id; + disable_irq_nosync(ts->client->irq); + queue_work(htcleo_touch_wq, &ts->work); + return IRQ_HANDLED; +} +#endif //////////////////////////////////////////////////////////////////////////// -static int leo_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +static uint32_t touch_on_gpio_table[] = { - struct leo_ts_data *ts; - int ret = 0; - int x_start, y_start, x_end, y_end; + PCOM_GPIO_CFG(HTCLEO_GPIO_TS_IRQ, 0, GPIO_INPUT, GPIO_PULL_UP, GPIO_2MA), +}; + +static int htcleo_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct htcleo_ts_data *ts; + int ret = 0; + int x_start, y_start, x_end, y_end; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - { - dev_err(&client->dev, "need I2C_FUNC_I2C\n"); - ret = -ENODEV; - goto err_check_functionality_failed; - } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + { + dev_err(&client->dev, "need I2C_FUNC_I2C\n"); + ret = -ENODEV; + goto err_check_functionality_failed; + } - ts = kzalloc(sizeof(struct leo_ts_data), GFP_KERNEL); - if (ts == NULL) - { - dev_err(&client->dev, "allocate leo_ts_data failed\n"); - ret = -ENOMEM; - goto err_alloc_data_failed; - } + ts = kzalloc(sizeof(struct htcleo_ts_data), GFP_KERNEL); + if (ts == NULL) + { + dev_err(&client->dev, "allocate htcleo_ts_data failed\n"); + ret = -ENOMEM; + goto err_alloc_data_failed; + } - INIT_WORK(&ts->work, leo_ts_work_func); - ts->client = client; - i2c_set_clientdata(client, ts); - ts->prev_ptcount = 0; + INIT_WORK(&ts->work, htcleo_ts_work_func); + ts->client = client; + i2c_set_clientdata(client, ts); + ts->prev_ptcount = 0; - gpio_request(HTCLEO_GPIO_TS_POWER, "htcleo_ts"); - gpio_request(HTCLEO_GPIO_TS_SEL, "htcleo_ts"); - gpio_request(HTCLEO_GPIO_TS_IRQ, "htcleo_ts"); - gpio_request(82, "htcleo_ts"); - gpio_request(27, "htcleo_ts"); + config_gpio_table(touch_on_gpio_table, ARRAY_SIZE(touch_on_gpio_table)); + + gpio_request(HTCLEO_GPIO_TS_POWER, "htcleo_ts"); + gpio_request(HTCLEO_GPIO_TS_SEL, "htcleo_ts"); + gpio_request(HTCLEO_GPIO_TS_IRQ, "htcleo_ts"); + gpio_request(HTCLEO_GPIO_TS_MULT, "htcleo_ts"); + gpio_request(HTCLEO_GPIO_H2W_CLK, "htcleo_ts"); + + gpio_direction_output(HTCLEO_GPIO_TS_SEL, 1); + gpio_direction_output(HTCLEO_GPIO_TS_POWER, 0); + gpio_direction_output(HTCLEO_GPIO_TS_MULT, 0); + gpio_direction_output(HTCLEO_GPIO_H2W_CLK, 0); + gpio_direction_input(HTCLEO_GPIO_TS_IRQ); + msleep(100); + + ret = htcleo_reset_ts(ts); + if (ret < 0) + { + dev_err(&client->dev, "TS: htcleo_reset_ts() failed\n"); + goto err_detect_failed; + } + + ret = htcleo_detect_ts_type(ts); + if (ret < 0) + { + dev_err(&client->dev, "TS: htcleo_detect_ts_type() failed\n"); + goto err_detect_failed; + } + + // !!!other types are not supported yet!!! + if (ts->ts_type == TOUCH_TYPE_68 || ts->ts_type == TOUCH_TYPE_B8) + { + dev_err(&ts->client->dev, "TS: NOT SUPPORTED\n"); + BUG(); + } + + ret = htcleo_init_ts(ts); + if (ret < 0) + { + dev_err(&client->dev, "TS: htcleo_init_ts() failed\n"); + goto err_detect_failed; + } + + ret = htcleo_init_intr(ts); + if (ret < 0) + { + dev_err(&client->dev, "TS: htcleo_init_intr() failed\n"); + goto err_detect_failed; + } + + ts->input_dev = input_allocate_device(); + if (ts->input_dev == NULL) + { + ret = -ENOMEM; + dev_err(&client->dev, "Failed to allocate input device\n"); + goto err_input_dev_alloc_failed; + } + + ts->input_dev->name = "htcleo-touchscreen"; - ret = leo_reset_ts(ts); - if (ret < 0) - { - dev_err(&client->dev, "TS: leo_reset_ts() failed\n"); - goto err_detect_failed; - } + // inital touch calibraion + switch (ts->ts_type) + { + case TOUCH_TYPE_2A: + x_start = 6; + y_start = 6; + x_end = 576; + y_end = 952; + break; + } - ret = leo_detect_ts_type(ts); - if (ret < 0) - { - dev_err(&client->dev, "TS: leo_detect_ts_type() failed\n"); - goto err_detect_failed; - } + set_bit(EV_SYN, ts->input_dev->evbit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(EV_KEY, ts->input_dev->evbit); -// !!!other types are not supported yet!!! - if (ts->ts_type == TOUCH_TYPE_68 || ts->ts_type == TOUCH_TYPE_B8) - { - dev_err(&ts->client->dev, "TS: NOT SUPPORTED\n"); - BUG(); - } - - ret = leo_init_ts(ts); - if (ret < 0) - { - dev_err(&client->dev, "TS: leo_init_ts() failed\n"); - goto err_detect_failed; - } - - ret = leo_init_intr(ts); - if (ret < 0) - { - dev_err(&client->dev, "TS: leo_init_intr() failed\n"); - goto err_detect_failed; - } - - ts->input_dev = input_allocate_device(); - if (ts->input_dev == NULL) - { - ret = -ENOMEM; - dev_err(&client->dev, "Failed to allocate input device\n"); - goto err_input_dev_alloc_failed; - } - - ts->input_dev->name = "leo-touchscreen"; - - -// inital touch calibraion - switch (ts->ts_type) - { - case TOUCH_TYPE_2A: - x_start = 6; - y_start = 6; - x_end = 576; - y_end = 952; - break; - } - - set_bit(EV_SYN, ts->input_dev->evbit); - set_bit(EV_ABS, ts->input_dev->evbit); - set_bit(EV_KEY, ts->input_dev->evbit); - - input_set_capability(ts->input_dev, EV_KEY, BTN_TOUCH); + input_set_capability(ts->input_dev, EV_KEY, BTN_TOUCH); #ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH - input_set_capability(ts->input_dev, EV_KEY, BTN_2); + input_set_capability(ts->input_dev, EV_KEY, BTN_2); #endif - input_set_abs_params(ts->input_dev, ABS_X, x_start, x_end, 5, 0); - input_set_abs_params(ts->input_dev, ABS_Y, y_start, y_end, 5, 0); - input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, 5, 0, 0); + input_set_abs_params(ts->input_dev, ABS_X, x_start, x_end, 5, 0); + input_set_abs_params(ts->input_dev, ABS_Y, y_start, y_end, 5, 0); + input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, 0, 5, 0, 0); #ifdef CONFIG_HTCLEO_ENABLE_MULTI_TOUCH - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, x_start, x_end, 5, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, y_start, y_end, 5, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 1, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, x_start, x_end, 5, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, y_start, y_end, 5, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 1, 0, 0); #endif -// input_set_abs_params(ts->input_dev, ABS_HAT0X, x_start, x_end, 0, 0); -// input_set_abs_params(ts->input_dev, ABS_HAT0Y, y_start, y_end, 0, 0); -// input_set_abs_params(ts->input_dev, ABS_PRESSURE, pdata->abs_pressure_min, pdata->abs_pressure_max, 0, 0); -// input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, pdata->abs_width_min, pdata->abs_width_max, 0, 0); + // input_set_abs_params(ts->input_dev, ABS_HAT0X, x_start, x_end, 0, 0); + // input_set_abs_params(ts->input_dev, ABS_HAT0Y, y_start, y_end, 0, 0); + // input_set_abs_params(ts->input_dev, ABS_PRESSURE, pdata->abs_pressure_min, pdata->abs_pressure_max, 0, 0); + // input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH, pdata->abs_width_min, pdata->abs_width_max, 0, 0); - ret = input_register_device(ts->input_dev); - if (ret) - { - dev_err(&client->dev, - "leo_ts_probe: Unable to register %s input device\n", - ts->input_dev->name); - goto err_input_register_device_failed; - } + ret = input_register_device(ts->input_dev); + if (ret) + { + dev_err(&client->dev, + "htcleo_ts_probe: Unable to register %s input device\n", + ts->input_dev->name); + goto err_input_register_device_failed; + } + +#ifdef TS_USE_IRQ + ts->client->irq = gpio_to_irq(HTCLEO_GPIO_TS_IRQ); + ret = request_irq(ts->client->irq, htcleo_ts_irq_handler, + ts->intr_type ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW, + LEO_TOUCH_DRV_NAME, ts); +#else + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = htcleo_ts_timer_func; + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); +#endif - ts->client->irq = gpio_to_irq(HTCLEO_GPIO_TS_IRQ); - ret = request_irq(ts->client->irq, leo_ts_irq_handler, - ts->intr_type ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW, - LEO_TOUCH_DRV_NAME, ts); #ifdef CONFIG_HAS_EARLYSUSPEND - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - ts->early_suspend.suspend = leo_ts_early_suspend; - ts->early_suspend.resume = leo_ts_late_resume; - register_early_suspend(&ts->early_suspend); + ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + ts->early_suspend.suspend = htcleo_ts_early_suspend; + ts->early_suspend.resume = htcleo_ts_late_resume; + register_early_suspend(&ts->early_suspend); #endif - dev_info(&client->dev, "Start touchscreen %s\n", ts->input_dev->name); + dev_info(&client->dev, "Start touchscreen %s\n", ts->input_dev->name); - return 0; + return 0; err_input_register_device_failed: - input_free_device(ts->input_dev); + input_free_device(ts->input_dev); err_input_dev_alloc_failed: - // POWER OFF - leo_deinit_ts(); + // POWER OFF + htcleo_deinit_ts(); err_detect_failed: - kfree(ts); + kfree(ts); err_alloc_data_failed: err_check_functionality_failed: - return ret; + return ret; } -static int leo_ts_remove(struct i2c_client *client) +static int htcleo_ts_remove(struct i2c_client *client) { - struct leo_ts_data *ts = i2c_get_clientdata(client); + struct htcleo_ts_data *ts = i2c_get_clientdata(client); - unregister_early_suspend(&ts->early_suspend); + unregister_early_suspend(&ts->early_suspend); - free_irq(client->irq, ts); +#ifdef TS_USE_IRQ + free_irq(client->irq, ts); +#else + hrtimer_cancel(&ts->timer); +#endif + input_unregister_device(ts->input_dev); + kfree(ts); - input_unregister_device(ts->input_dev); - kfree(ts); - - return 0; + return 0; } -static int leo_ts_suspend(struct i2c_client *client, pm_message_t mesg) +static int htcleo_ts_suspend(struct i2c_client *client, pm_message_t mesg) { - struct leo_ts_data *ts = i2c_get_clientdata(client); - int ret; + struct htcleo_ts_data *ts = i2c_get_clientdata(client); + int ret; - disable_irq_nosync(client->irq); +#ifdef TS_USE_IRQ + disable_irq_nosync(client->irq); +#else + hrtimer_cancel(&ts->timer); +#endif + ret = cancel_work_sync(&ts->work); + if (ret) + { + enable_irq(client->irq); + } - ret = cancel_work_sync(&ts->work); - if (ret) - { - enable_irq(client->irq); - } + // POWER OFF + htcleo_deinit_ts(); - // POWER OFF - leo_deinit_ts(); - - return 0; + return 0; } -static int leo_ts_resume(struct i2c_client *client) +static int htcleo_ts_resume(struct i2c_client *client) { - struct leo_ts_data *ts = i2c_get_clientdata(client); + struct htcleo_ts_data *ts = i2c_get_clientdata(client); - // POWER ON - leo_reset_ts(ts); - leo_detect_ts_type(ts); - leo_init_ts(ts); - leo_init_intr(ts); + // POWER ON + htcleo_reset_ts(ts); + htcleo_detect_ts_type(ts); + htcleo_init_ts(ts); + htcleo_init_intr(ts); - enable_irq(client->irq); - - return 0; +#ifdef TS_USE_IRQ + enable_irq(client->irq); +#else + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); +#endif + return 0; } #ifdef CONFIG_HAS_EARLYSUSPEND -static void leo_ts_early_suspend(struct early_suspend *h) +static void htcleo_ts_early_suspend(struct early_suspend *h) { - struct leo_ts_data *ts; - ts = container_of(h, struct leo_ts_data, early_suspend); - leo_ts_suspend(ts->client, PMSG_SUSPEND); + struct htcleo_ts_data *ts; + ts = container_of(h, struct htcleo_ts_data, early_suspend); + htcleo_ts_suspend(ts->client, PMSG_SUSPEND); } -static void leo_ts_late_resume(struct early_suspend *h) +static void htcleo_ts_late_resume(struct early_suspend *h) { - struct leo_ts_data *ts; - ts = container_of(h, struct leo_ts_data, early_suspend); - leo_ts_resume(ts->client); + struct htcleo_ts_data *ts; + ts = container_of(h, struct htcleo_ts_data, early_suspend); + htcleo_ts_resume(ts->client); } #endif -static const struct i2c_device_id leo_ts_id[] = +static const struct i2c_device_id htcleo_ts_id[] = { - { LEO_TOUCH_DRV_NAME, 0 }, - { } + { LEO_TOUCH_DRV_NAME, 0 }, + { } }; -static struct i2c_driver leo_ts_driver = +static struct i2c_driver htcleo_ts_driver = { - .driver = - { - .name = LEO_TOUCH_DRV_NAME, - .owner = THIS_MODULE, - }, - .id_table = leo_ts_id, - .probe = leo_ts_probe, - .remove = leo_ts_remove, + .driver = + { + .name = LEO_TOUCH_DRV_NAME, + .owner = THIS_MODULE, + }, + .id_table = htcleo_ts_id, + .probe = htcleo_ts_probe, + .remove = htcleo_ts_remove, #ifndef CONFIG_HAS_EARLYSUSPEND - .suspend = leo_ts_suspend, - .resume = leo_ts_resume, + .suspend = htcleo_ts_suspend, + .resume = htcleo_ts_resume, #endif }; -static int __devinit leo_ts_init(void) +static int __devinit htcleo_ts_init(void) { - leo_touch_wq = create_singlethread_workqueue("leo_touch_wq"); - if (!leo_touch_wq) - { - return -ENOMEM; - } - return i2c_add_driver(&leo_ts_driver); + htcleo_touch_wq = create_singlethread_workqueue("htcleo_touch_wq"); + if (!htcleo_touch_wq) + { + return -ENOMEM; + } + return i2c_add_driver(&htcleo_ts_driver); } -static void __exit leo_ts_exit(void) +static void __exit htcleo_ts_exit(void) { - if (leo_touch_wq) - { - destroy_workqueue(leo_touch_wq); - leo_touch_wq = NULL; - } - i2c_del_driver(&leo_ts_driver); + if (htcleo_touch_wq) + { + destroy_workqueue(htcleo_touch_wq); + htcleo_touch_wq = NULL; + } + i2c_del_driver(&htcleo_ts_driver); } -module_init(leo_ts_init); -module_exit(leo_ts_exit); +module_init(htcleo_ts_init); +module_exit(htcleo_ts_exit); MODULE_DESCRIPTION("HTC LEO Touchscreen Support Driver"); diff --git a/arch/arm/mach-msm/board-htcleo.h b/arch/arm/mach-msm/board-htcleo.h index ab9064f7..61816de0 100644 --- a/arch/arm/mach-msm/board-htcleo.h +++ b/arch/arm/mach-msm/board-htcleo.h @@ -62,65 +62,81 @@ /* End EBI region */ -#define HTCLEO_GPIO_PS_HOLD 25 +#define HTCLEO_GPIO_PS_HOLD 25 -//#define HTCLEO_GPIO_UP_INT_N 35 // We have to find the right one -#define HTCLEO_GPIO_UP_INT_N 90 -#define HTCLEO_GPIO_UP_RESET_N 91 -#define HTCLEO_GPIO_LS_EN_N 119 +#define HTCLEO_GPIO_UP_INT_N 90 +#define HTCLEO_GPIO_UP_RESET_N 91 +#define HTCLEO_GPIO_LS_EN_N 119 -#define HTCLEO_GPIO_TP_INT_N 92 -#define HTCLEO_GPIO_TP_LS_EN 93 -#define HTCLEO_GPIO_TP_EN 160 +#define HTCLEO_GPIO_TP_INT_N 92 +#define HTCLEO_GPIO_TP_LS_EN 93 +#define HTCLEO_GPIO_TP_EN 160 -#define HTCLEO_GPIO_POWER_KEY 94 -#define HTCLEO_GPIO_SD_STATUS 153 +#define HTCLEO_GPIO_POWER_KEY 94 +#define HTCLEO_GPIO_SD_STATUS 153 -#define HTCLEO_GPIO_WIFI_SHUTDOWN_N 129 -#define HTCLEO_GPIO_WIFI_IRQ 152 +#define HTCLEO_GPIO_WIFI_SHUTDOWN_N 129 +#define HTCLEO_GPIO_WIFI_IRQ 152 -#define HTCLEO_GPIO_VIBRATOR_ON 100 +#define HTCLEO_GPIO_VIBRATOR_ON 100 /* Flashlight */ -#define HTCLEO_GPIO_FLASHLIGHT_TORCH 159 -#define HTCLEO_GPIO_FLASHLIGHT_FLASH 143 +#define HTCLEO_GPIO_FLASHLIGHT_TORCH 159 +#define HTCLEO_GPIO_FLASHLIGHT_FLASH 143 -#define HTCLEO_AUD_JACKHP_EN 157 -#define HTCLEO_AUD_2V5_EN 158 -#define HTCLEO_BT_PCM_OUT 68 -#define HTCLEO_BT_PCM_IN 69 -#define HTCLEO_BT_PCM_SYNC 70 -#define HTCLEO_BT_PCM_CLK 71 +#define HTCLEO_AUD_JACKHP_EN 157 +#define HTCLEO_AUD_2V5_EN 158 +#define HTCLEO_BT_PCM_OUT 68 +#define HTCLEO_BT_PCM_IN 69 +#define HTCLEO_BT_PCM_SYNC 70 +#define HTCLEO_BT_PCM_CLK 71 /* Headset */ -#define HTCLEO_GPIO_HDS_MIC 35 -#define HTCLEO_GPIO_HDS_DET 145 +#define HTCLEO_GPIO_HDS_MIC 35 +#define HTCLEO_GPIO_HDS_DET 145 /* Keypad */ -#define HTCLEO_GPIO_KP_MKOUT0 33 -#define HTCLEO_GPIO_KP_MKOUT1 32 -#define HTCLEO_GPIO_KP_MKOUT2 31 -#define HTCLEO_GPIO_KP_MPIN0 42 -#define HTCLEO_GPIO_KP_MPIN1 41 -#define HTCLEO_GPIO_KP_MPIN2 40 -#define HTCLEO_GPIO_KP_LED 48 +#define HTCLEO_GPIO_KP_MKOUT0 33 +#define HTCLEO_GPIO_KP_MKOUT1 32 +#define HTCLEO_GPIO_KP_MKOUT2 31 +#define HTCLEO_GPIO_KP_MPIN0 42 +#define HTCLEO_GPIO_KP_MPIN1 41 +#define HTCLEO_GPIO_KP_MPIN2 40 +#define HTCLEO_GPIO_KP_LED 48 /* Bluetooth */ -#define HTCLEO_GPIO_BT_UART1_RTS 43 -#define HTCLEO_GPIO_BT_UART1_CTS 44 -#define HTCLEO_GPIO_BT_UART1_RX 45 -#define HTCLEO_GPIO_BT_UART1_TX 46 -#define HTCLEO_GPIO_BT_RESET_N 146 -#define HTCLEO_GPIO_BT_SHUTDOWN_N 128 -#define HTCLEO_GPIO_BT_HOST_WAKE 37 -#define HTCLEO_GPIO_BT_CHIP_WAKE 57 +#define HTCLEO_GPIO_BT_UART1_RTS 43 +#define HTCLEO_GPIO_BT_UART1_CTS 44 +#define HTCLEO_GPIO_BT_UART1_RX 45 +#define HTCLEO_GPIO_BT_UART1_TX 46 +#define HTCLEO_GPIO_BT_RESET_N 146 +#define HTCLEO_GPIO_BT_SHUTDOWN_N 128 +#define HTCLEO_GPIO_BT_HOST_WAKE 37 +#define HTCLEO_GPIO_BT_CHIP_WAKE 57 + +/* Battery */ +#define HTCLEO_GPIO_BATTERY_CHARGER_ENABLE 22 +#define HTCLEO_GPIO_BATTERY_CHARGER_CURRENT 16 +#define HTCLEO_GPIO_BATTERY_OVER_CHG 147 +#define HTCLEO_GPIO_POWER_USB 109 +#define HTCLEO_GPIO_USBPHY_3V3_ENABLE 104 + +/* Touchscreen */ +#define HTCLEO_GPIO_TS_POWER 160 +#define HTCLEO_GPIO_TS_IRQ 92 +#define HTCLEO_GPIO_TS_SEL 108 +#define HTCLEO_GPIO_TS_MULT 82 +#define HTCLEO_GPIO_H2W_CLK 27 + +#define HTCLEO_GPIO_LED_3V3_EN 85 + /* Compass */ -#define HTCLEO_GPIO_COMPASS_INT_N 39 -#define HTCLEO_GPIO_COMPASS_RST_N 107 -#define HTCLEO_PROJECT_NAME "htcleo" +#define HTCLEO_GPIO_COMPASS_INT_N 39 +#define HTCLEO_GPIO_COMPASS_RST_N 107 +#define HTCLEO_PROJECT_NAME "htcleo" #define HTCLEO_LAYOUTS { \ { { 0, 1, 0}, { -1, 0, 0}, { 0, 0, 1} }, \ { { 0, -1, 0}, { 1, 0, 0}, { 0, 0, -1} }, \ @@ -131,40 +147,28 @@ /* Display */ #define HTCLEO_GPIO_LCM_POWER 88 #define HTCLEO_GPIO_LCM_RESET 29 -#define HTCLEO_LCD_R1 (114) -#define HTCLEO_LCD_R2 (115) -#define HTCLEO_LCD_R3 (116) -#define HTCLEO_LCD_R4 (117) -#define HTCLEO_LCD_R5 (118) -#define HTCLEO_LCD_G0 (121) -#define HTCLEO_LCD_G1 (122) -#define HTCLEO_LCD_G2 (123) -#define HTCLEO_LCD_G3 (124) -#define HTCLEO_LCD_G4 (125) -#define HTCLEO_LCD_G5 (126) -#define HTCLEO_LCD_B1 (130) -#define HTCLEO_LCD_B2 (131) -#define HTCLEO_LCD_B3 (132) -#define HTCLEO_LCD_B4 (133) -#define HTCLEO_LCD_B5 (134) -#define HTCLEO_LCD_PCLK (135) -#define HTCLEO_LCD_VSYNC (136) -#define HTCLEO_LCD_HSYNC (137) -#define HTCLEO_LCD_DE (138) +#define HTCLEO_LCD_R1 (114) +#define HTCLEO_LCD_R2 (115) +#define HTCLEO_LCD_R3 (116) +#define HTCLEO_LCD_R4 (117) +#define HTCLEO_LCD_R5 (118) +#define HTCLEO_LCD_G0 (121) +#define HTCLEO_LCD_G1 (122) +#define HTCLEO_LCD_G2 (123) +#define HTCLEO_LCD_G3 (124) +#define HTCLEO_LCD_G4 (125) +#define HTCLEO_LCD_G5 (126) +#define HTCLEO_LCD_B1 (130) +#define HTCLEO_LCD_B2 (131) +#define HTCLEO_LCD_B3 (132) +#define HTCLEO_LCD_B4 (133) +#define HTCLEO_LCD_B5 (134) +#define HTCLEO_LCD_PCLK (135) +#define HTCLEO_LCD_VSYNC (136) +#define HTCLEO_LCD_HSYNC (137) +#define HTCLEO_LCD_DE (138) + -/* Battery */ -#define HTCLEO_GPIO_BATTERY_CHARGER_ENABLE 22 -#define HTCLEO_GPIO_BATTERY_CHARGER_CURRENT 16 -#define HTCLEO_GPIO_BATTERY_OVER_CHG 147 -#define HTCLEO_GPIO_POWER_USB 109 -#define HTCLEO_GPIO_USBPHY_3V3_ENABLE 104 - -/* Touchscreen */ -#define HTCLEO_GPIO_TS_POWER 160 -#define HTCLEO_GPIO_TS_IRQ 92 -#define HTCLEO_GPIO_TS_SEL 108 - -#define HTCLEO_GPIO_LED_3V3_EN 85 int htcleo_pm_set_vreg(int enable, unsigned id); int __init htcleo_init_panel(void); diff --git a/drivers/media/video/msm/s5k3e2fx.c b/drivers/media/video/msm/s5k3e2fx.c index a2ab9ba1..f77b503d 100644 --- a/drivers/media/video/msm/s5k3e2fx.c +++ b/drivers/media/video/msm/s5k3e2fx.c @@ -14,6 +14,7 @@ #include #include #include +#include static uint16_t g_usModuleVersion; /*0: rev.4, 1: rev.5 */ @@ -1689,8 +1690,16 @@ struct s5k3e2fx_ctrl { enum msm_s_test_mode set_test; }; +struct s5k3e2fx_waitevent{ + uint32_t waked_up; + wait_queue_head_t event_wait; +}; +static struct s5k3e2fx_waitevent s5k3e2fx_event; +static struct platform_device *s5k3e2fx_pdev; + static struct s5k3e2fx_ctrl *s5k3e2fx_ctrl; static DECLARE_WAIT_QUEUE_HEAD(s5k3e2fx_wait_queue); +DECLARE_MUTEX(s5k3e2fx_sem); #define MAX_I2C_RETRIES 20 static int i2c_transfer_retry(struct i2c_adapter *adap, @@ -2319,8 +2328,26 @@ static int s5k3e2fx_setting(enum msm_s_reg_update rupdate, static int s5k3e2fx_sensor_open_init(const struct msm_camera_sensor_info *data) { - int rc; + int rc=0; + int timeout; + + down(&s5k3e2fx_sem); + + /*check whether resume done*/ + timeout = wait_event_interruptible_timeout( + s5k3e2fx_event.event_wait, + s5k3e2fx_event.waked_up, + 30*HZ); + + pr_info("wait event : %d timeout:%d\n", + s5k3e2fx_event.waked_up, timeout); + if (timeout == 0) { + up(&s5k3e2fx_sem); + return rc; + } + + msm_camio_probe_on(s5k3e2fx_pdev); CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__); s5k3e2fx_ctrl = kzalloc(sizeof(struct s5k3e2fx_ctrl), GFP_KERNEL); if (!s5k3e2fx_ctrl) { @@ -2369,6 +2396,7 @@ static int s5k3e2fx_sensor_open_init(const struct msm_camera_sensor_info *data) init_fail1: kfree(s5k3e2fx_ctrl); init_done: + up(&s5k3e2fx_sem); return rc; } @@ -2406,6 +2434,8 @@ static int s5k3e2fx_sensor_release(void) s5k3e2fx_suspend_sensor(); + msm_camio_probe_off(s5k3e2fx_pdev); + kfree(s5k3e2fx_ctrl); s5k3e2fx_ctrl = NULL; @@ -2901,39 +2931,6 @@ static int s5k3e2fx_sensor_config(void __user *argp) return rc; } -static int s5k3e2fx_sensor_probe(const struct msm_camera_sensor_info *info, - struct msm_sensor_ctrl *s) -{ - int rc = 0; - pr_info("%s\n", __func__); - - rc = i2c_add_driver(&s5k3e2fx_i2c_driver); - if (rc < 0 || s5k3e2fx_client == NULL) { - rc = -ENOTSUPP; - goto probe_fail; - } - - msm_camio_clk_rate_set(S5K3E2FX_DEF_MCLK); - msleep(20); - - rc = s5k3e2fx_probe_init_sensor(info); - if (rc < 0) - goto probe_fail; - - /* lens correction */ - s5k3e2fx_probe_init_lens_correction(info); - init_suspend(); - - s->s_init = s5k3e2fx_sensor_open_init; - s->s_release = s5k3e2fx_sensor_release; - s->s_config = s5k3e2fx_sensor_config; - - return rc; - -probe_fail: - pr_err("SENSOR PROBE FAILS!\n"); - return rc; -} static int s5k3e2fx_suspend(struct platform_device *pdev, pm_message_t state) { @@ -2943,6 +2940,8 @@ static int s5k3e2fx_suspend(struct platform_device *pdev, pm_message_t state) if (!sinfo->need_suspend) return 0; + s5k3e2fx_event.waked_up = 0; + CDBG("s5k3e2fx: camera suspend\n"); rc = gpio_request(sinfo->sensor_reset, "s5k3e2fx"); if (!rc) @@ -3035,17 +3034,22 @@ static void s5k3e2fx_sensor_resume_setting(void) s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x0202, 0x03); s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x0200, 0x02); } -static int s5k3e2fx_resume(struct platform_device *pdev) +static void s5k3e2fx_resume(struct early_suspend *handler) { - int rc = 0; - struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data; + struct msm_camera_sensor_info *sinfo = s5k3e2fx_pdev->dev.platform_data; if (!sinfo->need_suspend) - return 0; + return; + + /*check whether already suspend*/ + if (s5k3e2fx_event.waked_up == 1) { + pr_info("S5k3e2fx: No nesesary to do Resume\n"); + return; + } CDBG("s5k3e2fx_resume\n"); /*init msm,clk ,GPIO,enable */ - msm_camio_probe_on(pdev); + msm_camio_probe_on(s5k3e2fx_pdev); msm_camio_clk_enable(CAMIO_MDC_CLK); CDBG("msm_camio_probe_on\n"); @@ -3075,14 +3079,106 @@ static int s5k3e2fx_resume(struct platform_device *pdev) s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x3150, 0x51); msleep(240); /*set RST to low */ - msm_camio_probe_off(pdev); + msm_camio_probe_off(s5k3e2fx_pdev); msm_camio_clk_disable(CAMIO_MDC_CLK); + s5k3e2fx_event.waked_up = 1; + wake_up(&s5k3e2fx_event.event_wait); CDBG("s5k3e2fx:resume done\n"); + return; +} + +static struct early_suspend early_suspend_s5k3e2fx = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN+1, + .resume = s5k3e2fx_resume, + .suspend = NULL, +}; + +static const char *s5k3e2fxVendor = "Samsung"; +static const char *s5k3e2fxNAME = "s5k3e2fx"; +static const char *s5k3e2fxSize = "5M"; + +static ssize_t sensor_vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t ret = 0; + + sprintf(buf, "%s %s %s\n", s5k3e2fxVendor, s5k3e2fxNAME, s5k3e2fxSize); + ret = strlen(buf) + 1; + + return ret; +} + +static DEVICE_ATTR(sensor, 0444, sensor_vendor_show, NULL); + +static struct kobject *android_s5k3e2fx; + +static int s5k3e2fx_sysfs_init(void) +{ + int ret ; + pr_info("s5k3e2fx:kobject creat and add\n"); + android_s5k3e2fx = kobject_create_and_add("android_camera", NULL); + if (android_s5k3e2fx == NULL) { + pr_info("s5k3e2fx_sysfs_init: subsystem_register " \ + "failed\n"); + ret = -ENOMEM; + return ret ; + } + pr_info("s5k3e2fx:sysfs_create_file\n"); + ret = sysfs_create_file(android_s5k3e2fx, &dev_attr_sensor.attr); + if (ret) { + pr_info("s5k3e2fx_sysfs_init: sysfs_create_file " \ + "failed\n"); + kobject_del(android_s5k3e2fx); + } + return 0 ; +} + +static int s5k3e2fx_sensor_probe(const struct msm_camera_sensor_info *info, + struct msm_sensor_ctrl *s) +{ + int rc = 0; + pr_info("%s\n", __func__); + + rc = i2c_add_driver(&s5k3e2fx_i2c_driver); + if (rc < 0 || s5k3e2fx_client == NULL) { + rc = -ENOTSUPP; + goto probe_fail; + } + + msm_camio_clk_rate_set(S5K3E2FX_DEF_MCLK); + msleep(20); + + rc = s5k3e2fx_probe_init_sensor(info); + if (rc < 0) + goto probe_fail; + + /* lens correction */ + s5k3e2fx_probe_init_lens_correction(info); + init_suspend(); + + s->s_init = s5k3e2fx_sensor_open_init; + s->s_release = s5k3e2fx_sensor_release; + s->s_config = s5k3e2fx_sensor_config; + + /*register late resuem*/ + register_early_suspend(&early_suspend_s5k3e2fx); + /*init wait event*/ + init_waitqueue_head(&s5k3e2fx_event.event_wait); + /*init waked_up value*/ + s5k3e2fx_event.waked_up = 1; + /*write sysfs*/ + s5k3e2fx_sysfs_init(); + + return rc; + +probe_fail: + pr_err("SENSOR PROBE FAILS!\n"); return rc; } static int __s5k3e2fx_probe(struct platform_device *pdev) { + s5k3e2fx_pdev = pdev; return msm_camera_drv_start(pdev, s5k3e2fx_sensor_probe); } @@ -3093,7 +3189,6 @@ static struct platform_driver msm_camera_driver = { .owner = THIS_MODULE, }, .suspend = s5k3e2fx_suspend, - .resume = s5k3e2fx_resume, }; static int __init s5k3e2fx_init(void) diff --git a/drivers/mtd/devices/htcleo_nand.c b/drivers/mtd/devices/htcleo_nand.c index 689f086a..07dc26c3 100755 --- a/drivers/mtd/devices/htcleo_nand.c +++ b/drivers/mtd/devices/htcleo_nand.c @@ -554,7 +554,12 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_o } } - if (oob_count > 0 && ops->ooboffs != 0) + if (!readdata && !readoob) + { + pr_err("%s: nothing to do\n", __func__); + return -EINVAL; + } + if (readoob && ops->ooboffs != 0) { pr_err("%s: unsupported ops->ooboffs, %d\n", __func__, ops->ooboffs); return -EINVAL; @@ -1106,7 +1111,12 @@ msm_nand_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) } } - if (oob_count != 0 && ops->ooboffs != 0) + if (!writedata && !writeoob) + { + pr_err("%s: nothing to do\n", __func__); + return -EINVAL; + } + if (writeoob && ops->ooboffs != 0) { pr_err("%s: unsupported ops->ooboffs, %d\n", __func__, ops->ooboffs); return -EINVAL;