Ejemplo n.º 1
0
static void melfas_ts_work_func(struct work_struct *work)
{
	int i,k;
	int ret;
	int bad_data = 0;	
	struct i2c_msg msg[2];
	uint8_t start_reg;
	/* varible z is press value*/
	uint8_t z = 0;
    uint8_t read_len;
	uint8_t touch_num = 0;
	uint8_t buf[11];
	uint8_t key_info = 0;
    uint8_t lifted_event = 0;
    uint8_t touch1_z = 0;
	uint8_t key_index = 0;
	uint8_t key_pressed = 0;
	uint16_t position[2][2];
	uint8_t w = 0;

	struct melfas_ts_data *ts = container_of(work, struct melfas_ts_data, work);
	if(machine_is_msm7x25_u8500() || machine_is_msm7x25_um840() || machine_is_msm7x25_u8350())
	{
		start_reg = 0x02;
        read_len = sizeof(buf);
	}
	else
	{
		start_reg = 0x10;
       /* for non-multi_touch*/
        read_len = sizeof(buf) - 2;
	}
	msg[0].addr = ts->client->addr;
	msg[0].flags = 0;
	msg[0].len = 1;
	msg[0].buf = &start_reg;
	
	msg[1].addr = ts->client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = read_len;
	msg[1].buf = buf;

	for (i = 0; i < ((ts->use_irq && !bad_data)? 1 : 5 ); i++)
	{
		ret = i2c_transfer(ts->client->adapter, msg, 2);
		if (ret < 0) 
		{
			MELFAS_DEBUG("%d times i2c_transfer failed\n",i);
			bad_data = 1;
			continue;
		}
		else
		{
		    bad_data = 0;
		}
    	if (i == 5) 
		{
			pr_err("five times i2c_transfer error\n");
			break;
		}

#ifdef TS_DEBUG
        /*printf debug info*/
        for(k=0; k < read_len; k++)
        {
            MELFAS_DEBUG("%s:register[0x%x]= 0x%x \n",__FUNCTION__, start_reg+k, buf[k]);
        }
#endif

		touch_num = buf[0] & 0x07;
		position[0][0] = buf[2] | (uint16_t)(buf[1] & 0x03) << 8;
		position[0][1] = buf[4] | (uint16_t)(buf[3] & 0x03) << 8;

        if (ts->support_multi_touch) { 		
			position[1][0] = buf[8] | (uint16_t)(buf[7] & 0x03) << 8;
			position[1][1] = buf[10] | (uint16_t)(buf[9] & 0x03) << 8;
			MELFAS_DEBUG("Touch_Area: X = %d Y = %d; X2 = %d Y2 = %d  \n",position[0][0],position[0][1],position[1][0],position[1][1] );
		}
		lifted_event = buf[6] & 0x03;//specifies which touch was lifted when two touches were present.
		touch1_z = buf[5];  //specifies the magnitude(width or pressure) of first touch
		/*reading pressure register */
		z = buf[5]; 
		
		/*the following four lines are not my code, I think it doesn't work,          
		cause buf[8] is not register 8, author: luojianhong */
		key_info = buf[8] & 0x3;
		key_index = (buf[8] & 0x0C) >> 2;
		key_pressed = (buf[0] & 0xC0) >> 6;
		w = buf[6];
		
		MELFAS_DEBUG("version 3.touch_num = %d, lifted_event = %d, touch1_z = %d \n",touch_num, lifted_event, touch1_z);
		if(ts->support_multi_touch)
		{
			if (!touch_num) 
                touch1_z = 0;
                
			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, touch1_z);
			input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, touch1_z>>5);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, position[0][0]);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, position[0][1]);
			input_mt_sync(ts->input_dev);
            
           /*
            2: two touches with ghosting
            3: two touches without ghosting.
           */
			if ((touch_num == 2) || (touch_num == 3))
			{
				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, touch1_z);
				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, touch1_z>>5);
				input_report_abs(ts->input_dev, ABS_MT_POSITION_X, position[1][0]);
				input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, position[1][1]);
				input_mt_sync(ts->input_dev);
			} 
			else if (ts->reported_finger_count > 1) 
			{
				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
				input_mt_sync(ts->input_dev);
			}
			ts->reported_finger_count = touch_num;
			
			input_sync(ts->input_dev);
				
			goto support_multi_touch_end;
		}
Ejemplo n.º 2
0
static int aps_12d_probe(
	struct i2c_client *client, const struct i2c_device_id *id)
{	
	int ret;
	struct aps_data *aps;
	int i;

	printk(KERN_INFO "aps_12d_probe enter\n ");
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		printk(KERN_ERR "aps_12d_probe: need I2C_FUNC_I2C\n");
		ret = -ENODEV;
		goto err_check_functionality_failed;
	}

	if(machine_is_msm7x25_u8150() || machine_is_msm7x25_c8150())
	{
		if((get_hw_sub_board_id() == HW_VER_SUB_VA) || ((get_hw_sub_board_id() == HW_VER_SUB_VB)))
		{
			printk(KERN_ERR "aps_12d_probe: aps is not supported in c8150 and u8150 T1 board!\n");
			ret = -ENODEV;
			goto err_check_functionality_failed; 
		}
	}
	
	aps = kzalloc(sizeof(*aps), GFP_KERNEL);
	if (aps == NULL) {
		ret = -ENOMEM;
		goto err_alloc_data_failed;
	}

	mutex_init(&aps->mlock);

	INIT_WORK(&aps->work, aps_12d_work_func);
	aps->client = client;
	i2c_set_clientdata(client, aps);

	printk(KERN_INFO "aps_12d_probe send command 2\n ");
	/* Command 2 register: 25mA,DC,12bit,Range1 */
	ret = aps_i2c_reg_write(aps, APS_12D_REG_CMD2, \
	                         (uint8_t)(APS_12D_IRDR_SEL_50MA << 6 | \
	                                   APS_12D_FREQ_SEL_DC << 4 | \
	                                   APS_12D_RES_SEL_12 << 2 | \
	                                   APS_12D_RANGE_SEL_ALS_1000));
	if (ret < 0) {
		goto err_detect_failed;
	}

	if( machine_is_msm7x25_u8150() || machine_is_msm7x25_c8150() || machine_is_msm7x25_u8159()\
		|| machine_is_msm7x25_u8160() || machine_is_msm7x25_u8130() || machine_is_msm7x25_c8510())
	{
		range_index = 0;
		high_threshold = high_threshold_value[range_index];
		low_threshold = low_threshold_value[range_index];


		for(i = 0; i < TOTAL_RANGE_NUM; i++)
		{
			/* NOTE: do NOT use the last one */
			up_range_value[i] = MAX_ADC_OUTPUT - high_threshold_value[i] - UP_RANGE_FIX;
#ifdef DEBUG_AUTO_RANGE_ADJUST
			printk("up_range_value[%d] = %d.\n",i, up_range_value[i]);
#endif
		}

		down_range_value[0] = 0;
		for(i = 1; i < TOTAL_RANGE_NUM; i++)
		{
			/* NOTE: do not use the first one */
			down_range_value[i] = (MAX_ADC_OUTPUT - high_threshold_value[i-1] - (MAX_ADC_OUTPUT / ADJUST_GATE)) / 4;
#ifdef DEBUG_AUTO_RANGE_ADJUST
			printk("down_range_value[%d] = %d\n",i, down_range_value[i]);
#endif
		}

	}
	else if( machine_is_msm7x25_u8500() || machine_is_msm7x25_um840())
	{
		high_threshold = 300;
		low_threshold = 280;
	}
	else if( machine_is_msm7x25_u8300() )
	{
/* set shutter value for u8300 */
		high_threshold = 710;
		low_threshold = 650;
	}
	else
	{
		high_threshold = 780;
		low_threshold = 730;
	}
	
	if (sensor_dev == NULL) {
		aps->input_dev = input_allocate_device();
		if (aps->input_dev == NULL) {
			ret = -ENOMEM;
			printk(KERN_ERR "aps_12d_probe: Failed to allocate input device\n");
			goto err_input_dev_alloc_failed;
		}
		aps->input_dev->name = "sensors";
		
		aps->input_dev->id.bustype = BUS_I2C;
		
		input_set_drvdata(aps->input_dev, aps);
		
		ret = input_register_device(aps->input_dev);
		if (ret) {
			printk(KERN_ERR "aps_probe: Unable to register %s input device\n", aps->input_dev->name);
			goto err_input_register_device_failed;
		}
		sensor_dev = aps->input_dev;
	} else {
		aps->input_dev = sensor_dev;
	}

	set_bit(EV_ABS, aps->input_dev->evbit);
	input_set_abs_params(aps->input_dev, ABS_LIGHT, 0, 10240, 0, 0);
	input_set_abs_params(aps->input_dev, ABS_DISTANCE, 0, 1, 0, 0);

	ret = misc_register(&light_device);
	if (ret) {
		printk(KERN_ERR "aps_12d_probe: light_device register failed\n");
		goto err_light_misc_device_register_failed;
	}

	ret = misc_register(&proximity_device);
	if (ret) {
		printk(KERN_ERR "aps_12d_probe: proximity_device register failed\n");
		goto err_proximity_misc_device_register_failed;
	}

	if( light_device.minor != MISC_DYNAMIC_MINOR ){
		light_device_minor = light_device.minor;
	}
	
	if( proximity_device.minor != MISC_DYNAMIC_MINOR ){
		proximity_device_minor = proximity_device.minor ;
	}

	wake_lock_init(&proximity_wake_lock, WAKE_LOCK_SUSPEND, "proximity");

	hrtimer_init(&aps->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	aps->timer.function = aps_timer_func;
	
	aps_wq = create_singlethread_workqueue("aps_wq");

	if (!aps_wq) {
		ret = -ENOMEM;
		goto err_create_workqueue_failed;
	}
	
	this_aps_data =aps;

#ifdef CONFIG_HAS_EARLYSUSPEND
	aps->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	aps->early_suspend.suspend = aps_12d_early_suspend;
	aps->early_suspend.resume = aps_12d_early_resume;
	register_early_suspend(&aps->early_suspend);
#endif

	#ifdef CONFIG_HUAWEI_HW_DEV_DCT
	/* detect current device successful, set the flag as present */
	set_hw_dev_flag(DEV_I2C_APS);
	#endif

	printk(KERN_INFO "aps_12d_probe: Start Proximity Sensor APS-12D\n");

#ifdef CONFIG_MELFAS_UPDATE_TS_FIRMWARE
	TS_updateFW_aps_data = this_aps_data;
	TS_updateFW_aps_wq = aps_wq;
#endif

	return 0;
	
err_create_workqueue_failed:
	misc_deregister(&proximity_device);
err_proximity_misc_device_register_failed:
	misc_deregister(&light_device);
err_light_misc_device_register_failed:
err_input_register_device_failed:
	input_free_device(aps->input_dev);
err_input_dev_alloc_failed:
err_detect_failed:
	kfree(aps);
err_alloc_data_failed:
err_check_functionality_failed:
	return ret;
  
}