示例#1
0
static int goodix_ts_power(struct gt818_ts_data * ts, int on)
{
	int ret = -1;
	struct gt818_platform_data	*pdata = ts->client->dev.platform_data;
	unsigned char i2c_control_buf[3] = {0x06,0x92,0x01};		//suspend cmd
	if(ts != NULL && !ts->use_irq)
		return -2;
	switch(on)
	{
		case 0:
			i2c_pre_cmd(ts);
			// set the io port high level to avoid level change which might stop gt818 from sleeping
			gpio_direction_output(pdata->gpio_reset, 1);
			gpio_direction_output(pdata->gpio_pendown, 1);
			msleep(5);
			ret = i2c_write_bytes(ts->client, i2c_control_buf, 3);
			if(ret < 0)
			{
				printk(KERN_INFO"**gt818 suspend fail**\n");
			}
			else
			{
				//printk(KERN_INFO"**gt818 suspend**\n");
				ret = 0;
			}
//			i2c_end_cmd(ts);
			return ret;
			
		case 1:

			gpio_pull_updown(pdata->gpio_pendown, 1);
			gpio_direction_output(pdata->gpio_pendown, 0);
			msleep(1);
			gpio_direction_output(pdata->gpio_pendown, 1);
			msleep(1);
			gpio_direction_input(pdata->gpio_pendown);
			gpio_pull_updown(pdata->gpio_pendown, 0);

/*
			msleep(2);
			gpio_pull_updown(pdata->gpio_reset, 1);
			gpio_direction_output(pdata->gpio_reset, 0);
			msleep(2);
			gpio_direction_input(pdata->gpio_reset);
			gpio_pull_updown(pdata->gpio_reset, 0);
			msleep(30);
*/
			msleep(1);
			ret = i2c_pre_cmd(ts);
			//printk(KERN_INFO"**gt818 reusme**\n");
			ret = i2c_end_cmd(ts);

			return ret;
				
		default:
			printk(KERN_DEBUG "%s: Cant't support this command.", gt818_ts_name);
			return -EINVAL;
	}

}
static u8 clear_mix_flag(struct goodix_ts_data *ts)
{
    s32 i = 0;
    u8 buf[3];
    
    buf[0] = 0x14;
    buf[1] = 0x00;
    buf[2] = 0x80;
    
    for (i = 0; i < 5; i++)
    {
        if (i2c_write_bytes(ts->client, buf, 3) > 0)
        {
            break;
        }
    }
    i2c_end_cmd(ts);

    if (i >= 5)
    {
        DEBUG_UPDATE("Clear mix flag failed!\n");
        return fail;
    }

    return success;
}
static u8 get_ic_msg(struct goodix_ts_data *ts, u16 addr, u8* msg, s32 len)
{
    s32 i = 0;

    msg[0] = addr >> 8 & 0xff;
    msg[1] = addr & 0xff;

    for (i = 0; i < 5; i++)
    {
        if (i2c_read_bytes(ts->client, msg, ADDR_LENGTH + len) > 0)
        {
            break;
        }
    }
    i2c_end_cmd(ts);

    if (i >= 5)
    {
        DEBUG_UPDATE("Read data from 0x%02x%02x failed!\n", msg[0], msg[1]);
        return fail;
    }

    return success;
}
示例#4
0
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int ret = 0;
	int retry=0;
	struct gt818_ts_data *ts;

	struct gt818_platform_data *pdata;
	dev_info(&client->dev,"Install touch driver.\n");
	printk("gt818: Install touch driver.\n");
	//Check I2C function
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
	{
		dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
		ret = -ENODEV;
		goto err_check_functionality_failed;
	}

	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
	if (ts == NULL) {
		ret = -ENOMEM;
		goto err_alloc_data_failed;
	}

	i2c_connect_client = client;	//used by Guitar_Update
	pdata = client->dev.platform_data;
	ts->client = client;
	i2c_set_clientdata(client, ts);

	//init int and reset ports
	ret = gpio_request(pdata->gpio_pendown, "TS_INT");	//Request IO
	if (ret){
		dev_err(&client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(int)pdata->gpio_pendown, ret);
		goto err_gpio_request_failed;
	}
	rk29_mux_api_set(pdata->pendown_iomux_name, pdata->pendown_iomux_mode);
	gpio_direction_input(pdata->gpio_pendown);
	gpio_pull_updown(pdata->gpio_pendown, 0);

	ret = gpio_request(pdata->gpio_reset, "gt818_resetPin");
	if(ret){
		dev_err(&client->dev, "failed to request resetPin GPIO%d\n", pdata->gpio_reset);
		goto err_gpio_request_failed;
	}
	rk29_mux_api_set(pdata->resetpin_iomux_name, pdata->resetpin_iomux_mode);

#if 1
	for(retry = 0; retry < 4; retry++)
	{
		gpio_pull_updown(pdata->gpio_reset, 1);
		gpio_direction_output(pdata->gpio_reset, 0);
		msleep(1);     //delay at least 1ms
		gpio_direction_input(pdata->gpio_reset);
		gpio_pull_updown(pdata->gpio_reset, 0);
		msleep(25);   //delay at least 20ms
		ret = i2c_pre_cmd(ts);
		if (ret > 0)
			break;
		msleep(50);
	}

	if(ret <= 0)
	{
		dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n");
		goto err_i2c_failed;
	}	

#endif

	for(retry = 0; retry < 3; retry++)
	{
		ret = goodix_init_panel(ts);

		dev_info(&client->dev,"the config ret is :%d\n", ret);
		msleep(20);
		if(ret < 0)	//Initiall failed
			continue;
		else
			break;
	}

	if(ret < 0) {
		ts->bad_data = 1;
		goto err_init_godix_ts;
	}

	goodix_read_version(ts);


	INIT_WORK(&ts->work, goodix_ts_work_func);		//init work_struct
	ts->input_dev = input_allocate_device();
	if (ts->input_dev == NULL) {
		ret = -ENOMEM;
		dev_dbg(&client->dev,"goodix_ts_probe: Failed to allocate input device\n");
		goto err_input_dev_alloc_failed;
	}

	//ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
	//ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
	//ts->input_dev->absbit[0] = BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y) |
	//		BIT_MASK(ABS_MT_TOUCH_MAJOR) | BIT_MASK(ABS_MT_WIDTH_MAJOR);  // for android


#ifdef HAVE_TOUCH_KEY
	for(retry = 0; retry < MAX_KEY_NUM; retry++)
	{
		input_set_capability(ts->input_dev, EV_KEY, gt818_key_array[retry]);
	}
#endif

	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev));
	snprintf(ts->name, sizeof(ts->name), "gt818-touchscreen");

	ts->input_dev->name = "gt818_ts";//ts->name;
	ts->input_dev->phys = ts->phys;
	ts->input_dev->dev.parent = &client->dev;
	ts->input_dev->id.bustype = BUS_I2C;
	ts->input_dev->id.vendor = 0xDEAD;
	ts->input_dev->id.product = 0xBEEF;
	ts->input_dev->id.version = 10427;	//screen firmware version

	__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
	__set_bit(EV_ABS, ts->input_dev->evbit);
#ifdef GOODIX_MULTI_TOUCH
	input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM);
	//input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 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_POSITION_X, 0, SCREEN_MAX_WIDTH, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_HEIGHT, 0, 0);
	//input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, MAX_FINGER_NUM, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
#else
	input_set_abs_params(ts->input_dev, ABS_X, 0, SCREEN_MAX_HEIGHT, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_Y, 0, SCREEN_MAX_WIDTH, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
#endif	
	
	ret = input_register_device(ts->input_dev);
	if (ret) {
		dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);
		goto err_input_register_device_failed;
	}
	ts->bad_data = 0;
//	16finger_list.length = 0;

	client->irq = gpio_to_irq(pdata->gpio_pendown);		//If not defined in client
	if (client->irq)
	{

	#if INT_TRIGGER==0
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_RISING
	#elif INT_TRIGGER==1
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_FALLING
	#elif INT_TRIGGER==2
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_LOW
	#elif INT_TRIGGER==3
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_HIGH
	#endif

		ret = request_irq(client->irq, goodix_ts_irq_handler, GT801_PLUS_IRQ_TYPE,
			client->name, ts);
		if (ret != 0) {
			dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret);
			gpio_direction_input(pdata->gpio_pendown);
			gpio_free(pdata->gpio_pendown);
			goto err_gpio_request_failed;
		}
		else 
		{	
			disable_irq(client->irq);
			ts->use_irq = 1;
			dev_dbg(&client->dev,"Reques EIRQ %d succesd on GPIO:%d\n", client->irq, pdata->gpio_pendown);
		}	
	}

err_gpio_request_failed:
	ts->power = goodix_ts_power;
#ifdef CONFIG_HAS_EARLYSUSPEND
	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	ts->early_suspend.suspend = goodix_ts_early_suspend;
	ts->early_suspend.resume = goodix_ts_late_resume;
	register_early_suspend(&ts->early_suspend);
#endif
	dev_info(&client->dev,"Start %s in %s mode\n",
		ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");

	if (ts->use_irq)
	{
		enable_irq(client->irq);
	}
	else
	{
		hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		ts->timer.function = goodix_ts_timer_func;
		hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
	}

	i2c_end_cmd(ts);
	return 0;

err_init_godix_ts:
	i2c_end_cmd(ts);
	if(ts->use_irq)
	{
		ts->use_irq = 0;
		free_irq(client->irq,ts);
		gpio_direction_input(pdata->gpio_pendown);
		gpio_free(pdata->gpio_pendown);
	}
	else 
		hrtimer_cancel(&ts->timer);

err_input_register_device_failed:
	input_free_device(ts->input_dev);

err_input_dev_alloc_failed:
	i2c_set_clientdata(client, NULL);
err_i2c_failed:	
	kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
	return ret;
}
示例#5
0
static void goodix_ts_work_func(struct work_struct *work)
{	
	u8  touch_status[8*MAX_FINGER_NUM + 18] = {READ_TOUCH_ADDR_H, READ_TOUCH_ADDR_L, 0};
	u8  *key_value = NULL;
	u8  *point_data = NULL;
	static u8 finger_last[MAX_FINGER_NUM + 1]={0};
	u8  finger_current[MAX_FINGER_NUM + 1] = {0};
	u8  coor_data[6*MAX_FINGER_NUM] = {0};
	static u8  last_key = 0;

	u8  finger = 0;
	u8  key = 0;
	unsigned int  count = 0;
	unsigned int position = 0;	
	int temp = 0;
	int x = 0, y = 0 , pressure;

	u16 *coor_point;

	int syn_flag = 0;

	struct gt818_ts_data *ts = container_of(work, struct gt818_ts_data, work);

	i2c_pre_cmd(ts);
	i2c_read_bytes(ts->client, touch_status, sizeof(touch_status)/sizeof(touch_status[0]));
	i2c_end_cmd(ts);

	//judge whether the data is ready
	if((touch_status[2] & 0x30) != 0x20)
	{
		printk("%s:DATA_NO_READY\n", __func__);
		goto DATA_NO_READY;
	}
	//judge whether it is large area touch
	if(touch_status[13] & 0x0f)
	{
		goto DATA_NO_READY;
	}

	ts->bad_data = 0;
	finger = touch_status[2] & 0x07;
	key_value = touch_status + 15;
	key = key_value[2] & 0x0f;

	if(finger > 0)
	{
		point_data = key_value + 3;

		for(position = 0; position < (finger*8); position += 8)
		{
			temp = point_data[position];
			//printk("track:%d\n", temp);
			if(temp < (MAX_FINGER_NUM + 1))
			{
				finger_current[temp] = 1;
				for(count = 0; count < 6; count++)
				{
					coor_data[(temp - 1) * 6 + count] = point_data[position+1+count];
				}
			}
			else
			{
				//dev_err(&(ts->client->dev),"Track Id error:%d\n ",);
				ts->bad_data = 1;
				ts->retry++;
				goto XFER_ERROR;
			}		
		}
	
	}
	
	else
	{
		for(position = 1; position < MAX_FINGER_NUM+1; position++)
		{
			finger_current[position] = 0;
		}
	}

	coor_point = (u16 *)coor_data;

	for(position = 1; position < MAX_FINGER_NUM + 1; position++)
	{
		if((finger_current[position] == 0) && (finger_last[position] != 0))
		{
			//printk("<<<<<<<<<<<<<<<<<<<%s:positon:%d (%d,%d)\n", __func__, position,last_x,last_y);
			//printk("<<<%d , %d ",finger_current[position],finger_last[position]);
			//input_mt_slot(ts->input_dev, position);
			//input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
			//input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
			//input_report_abs(ts->input_dev, ABS_MT_POSITION_X, last_x[position]);
			//input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, last_y[position]);
			//input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100);
			//input_mt_sync(ts->input_dev);
			input_mt_slot(ts->input_dev, position);
			input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
			syn_flag = 1;
		}
		else if(finger_current[position])
		{
			x = (*(coor_point+3*(position-1)))*SCREEN_MAX_WIDTH/(TOUCH_MAX_WIDTH);
			y = (*(coor_point+3*(position-1)+1))*SCREEN_MAX_HEIGHT/(TOUCH_MAX_HEIGHT);
			pressure = (*(coor_point+3*(position-1)+2));
			if(x < SCREEN_MAX_WIDTH){
				x = SCREEN_MAX_WIDTH - x;
			}

			if(y < SCREEN_MAX_HEIGHT){
			//	y = SCREEN_MAX_HEIGHT-y;
			}

			//printk(">>>>>>>>>>>>>>>>>%s:positon:%d (%d,%d)\n", __func__, position,x,y);
			input_mt_slot(ts->input_dev, position);
			input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
			input_report_abs(ts->input_dev, ABS_MT_PRESSURE, pressure);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);

			last_x[position] = x;
			last_y[position] = y;
			//input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, pressure);
			//input_mt_sync(ts->input_dev);
			syn_flag = 1;
		}

}
input_sync(ts->input_dev);



#ifdef HAVE_TOUCH_KEY
	if((last_key == 0) && (key == 0)){
		goto NO_KEY_PRESS;
	}
	else{
		syn_flag = 1;
		switch(key){
			case 1:
				key = 4;
				break;
			case 2:
				key = 3;
				break;
			case 4:
				key = 2;
				break;
			case 8:
				key = 1;
				break;
			default:
				key = 0;
				break;
		}
		if(key != 0){
			input_report_key(ts->input_dev, gt818_key_array[key - 1], 1);
		}
		else{
			input_report_key(ts->input_dev, gt818_key_array[last_key - 1], 0);
		}
		last_key = key;
	}		

#endif


NO_KEY_PRESS:
	if(syn_flag){
		input_sync(ts->input_dev);
	}

	for(position = 1; position < MAX_FINGER_NUM + 1; position++)
	{
		finger_last[position] = finger_current[position];
	}

DATA_NO_READY:
XFER_ERROR:
//	i2c_end_cmd(ts);
	if(ts->use_irq)
		enable_irq(ts->client->irq);

}
static u8 get_ic_fw_msg(struct goodix_ts_data *ts)
{
    s32 ret = 0;
    s32 i = 0;
    u8 buf[32];
    
    if (fail == clear_mix_flag(ts))
    {
        return fail;
    }
    
    //Get the mask version in rom of IC
    if (fail == get_ic_msg(ts, READ_MSK_VER_ADDR_H << 8 | READ_MSK_VER_ADDR_L, buf, 4))
    {
        DEBUG_UPDATE("Read mask version failed!\n");
        return fail;
    }
    
    memcpy(update_msg.ic_fw_msg.msk_ver, &buf[ADDR_LENGTH], 4);
    DEBUG_UPDATE("IC The mask version in rom is %c%c%c%c.\n",
                 update_msg.ic_fw_msg.msk_ver[0],update_msg.ic_fw_msg.msk_ver[1],
                 update_msg.ic_fw_msg.msk_ver[2],update_msg.ic_fw_msg.msk_ver[3]);

#if 1
    //Get the firmware msg in IC, include firmware version and checksum flag
    for (i = 0; i < 2; i++)
    {
        if (fail == get_ic_msg(ts, READ_FW_MSG_ADDR_H<< 8 | READ_FW_MSG_ADDR_L, buf, 4))
        {
            DEBUG_UPDATE("Get firmware msg in IC error.\n");
            return fail;
        }
        update_msg.force_update = buf[ADDR_LENGTH];
        if (i == 0 && update_msg.force_update == 0xAA)
        {
            DEBUG_UPDATE("The check sum in ic is error.\n");
            DEBUG_UPDATE("IC will be reset.\n");
            DEBUG_UPDATE("If the check sum is still error,\n ");
            DEBUG_UPDATE("The IC will be updated by force.\n");

            guitar_reset(10);
            continue;
            //msleep(100);
        }
        break;
    }
    //ic_fw_msg.type = buf[ADDR_LENGTH + 1];
    update_msg.ic_fw_msg.version = buf[ADDR_LENGTH + 2] << 8 | buf[ADDR_LENGTH + 3];
    DEBUG_UPDATE("IC VID:0x%x\n", (int)update_msg.ic_fw_msg.version);
    DEBUG_UPDATE("IC force update:%x\n", update_msg.force_update);
#endif

    //Cuts the frequency
    buf[0] = 0x15;
    buf[1] = 0x22;
    buf[2] = 0x18;
    ret =  i2c_write_bytes(ts->client, buf, 3);
    if (ret <= 0)
    {
        return fail;
    }
    i2c_end_cmd(ts);
    
    //Get the pid at 0x4011 in nvram
    if (fail == get_ic_msg(ts, 0x4011, buf, 1))
    {
        DEBUG_UPDATE("Read pid failed!\n");
        return fail;
    }
    update_msg.ic_fw_msg.type = buf[ADDR_LENGTH];
    
    DEBUG_UPDATE("IC PID:%x\n", update_msg.ic_fw_msg.type);

//    guitar_reset(10);
    return success;
}