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; }
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; }