void forced_release(struct wacom_i2c *wac_i2c) { #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] %s\n", __func__); #endif input_report_abs(wac_i2c->input_dev, ABS_X, wac_i2c->last_x); input_report_abs(wac_i2c->input_dev, ABS_Y, wac_i2c->last_y); input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0); input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0); input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0); #if defined(WACOM_IRQ_WORK_AROUND) || defined(WACOM_PDCT_WORK_AROUND) input_report_key(wac_i2c->input_dev, BTN_TOOL_RUBBER, 0); input_report_key(wac_i2c->input_dev, BTN_TOOL_PEN, 0); input_report_key(wac_i2c->input_dev, KEY_PEN_PDCT, 0); #else input_report_key(wac_i2c->input_dev, wac_i2c->tool, 0); #endif input_sync(wac_i2c->input_dev); wac_i2c->last_x = 0; wac_i2c->last_y = 0; wac_i2c->pen_prox = 0; wac_i2c->pen_pressed = 0; wac_i2c->side_pressed = 0; wac_i2c->pen_pdct = PDCT_NOSIGNAL; #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(wac_i2c, false); #endif }
static void cyttsp4_mt_close(struct input_dev *input) { struct device *dev = input->dev.parent; struct cyttsp4_core_data *cd = dev_get_drvdata(dev); struct cyttsp4_mt_data *md = &cd->md; dev_info(dev, "%s\n", __func__); #if defined(TSP_BOOSTER) dev_err(md->dev, "%s force dvfs off\n", __func__); set_dvfs_lock(md, 2, false); #endif _cyttsp4_unsubscribe_attention(dev, CY_ATTEN_IRQ, CY_MODULE_MT, cyttsp4_mt_attention, CY_MODE_OPERATIONAL); _cyttsp4_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CY_MODULE_MT, cyttsp4_startup_attention, 0); _cyttsp4_unsubscribe_attention(dev, CY_ATTEN_WAKE, CY_MODULE_MT, cyttsp4_mt_wake_attention, 0); if (cd->pm_runtime_usage_count > 0) { pm_runtime_put(dev); cd->pm_runtime_usage_count--; } cd->number_of_open_input_device--; cyttsp4_core_suspend(dev); }
void forced_hover(struct wacom_i2c *wac_i2c) { #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] %s\n", __func__); #endif input_report_abs(wac_i2c->input_dev, ABS_X, 0); input_report_abs(wac_i2c->input_dev, ABS_Y, 0); input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0); input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0); input_report_key(wac_i2c->input_dev, BTN_TOUCH, 1); input_report_key(wac_i2c->input_dev, BTN_TOOL_PEN, 1); input_sync(wac_i2c->input_dev); #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(wac_i2c, true); #endif }
void forced_hover(struct wacom_i2c *wac_i2c) { /* To distinguish hover and pdct area, release */ if (wac_i2c->last_x != 0 || wac_i2c->last_y != 0) { printk(KERN_DEBUG "[E-PEN] release hover\n"); forced_release(wac_i2c); } wac_i2c->rdy_pdct = true; #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] %s\n", __func__); #endif input_report_key(wac_i2c->input_dev, KEY_PEN_PDCT, 1); input_sync(wac_i2c->input_dev); #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(wac_i2c, true); #endif }
static void cyttsp4_lift_all(struct cyttsp4_mt_data *md) { if (!md->si) return; if (md->num_prv_rec != 0) { if (md->mt_function.report_slot_liftoff) md->mt_function.report_slot_liftoff(md, md->si->si_ofs.tch_abs[CY_TCH_T].max); input_sync(md->input); md->num_prv_rec = 0; } #if defined(TSP_BOOSTER) if (md->touch_pressed_num != 0) { dev_err(md->dev, "%s force dvfs off\n", __func__); md->touch_pressed_num = 0; set_dvfs_lock(md, 0, false); } #endif }
void forced_release(struct wacom_i2c *wac_i2c) { #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] %s\n", __func__); #endif input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0); input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0); input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0); input_report_key(wac_i2c->input_dev, wac_i2c->tool, 0); input_sync(wac_i2c->input_dev); wac_i2c->pen_prox = 0; wac_i2c->pen_pressed = 0; wac_i2c->side_pressed = 0; #ifdef SEC_DVFS_LOCK set_dvfs_lock(wac_i2c, false); #endif }
int wacom_i2c_coord(struct wacom_i2c *wac_i2c) { bool prox = false; int ret = 0; u8 *data; int rubber, stylus; static u16 x, y, pressure; static u16 tmp; int rdy = 0; data = wac_i2c->wac_feature->data; ret = i2c_master_recv(wac_i2c->client, data, COM_COORD_NUM); if (ret >= 0) { #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) pr_debug("[E-PEN] %x, %x, %x, %x, %x, %x, %x\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6]); #endif if (data[0] & 0x80) { /* enable emr device */ if (!wac_i2c->pen_prox) { wac_i2c->pen_prox = 1; if (data[0] & 0x40) wac_i2c->tool = BTN_TOOL_RUBBER; else wac_i2c->tool = BTN_TOOL_PEN; #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) pr_debug("[E-PEN] is in(%d)\n", wac_i2c->tool); #endif } prox = !!(data[0] & 0x10); stylus = !!(data[0] & 0x20); rubber = !!(data[0] & 0x40); rdy = !!(data[0] & 0x80); x = ((u16) data[1] << 8) + (u16) data[2]; y = ((u16) data[3] << 8) + (u16) data[4]; pressure = ((u16) data[5] << 8) + (u16) data[6]; #ifdef WACOM_IMPORT_FW_ALGO /* Change Position to Active Area */ if (x <= origin_offset[0]) x = 0; else x = x - origin_offset[0]; if (y <= origin_offset[1]) y = 0; else y = y - origin_offset[1]; #ifdef COOR_WORK_AROUND wacom_i2c_coord_offset(&x, &y); wacom_i2c_coord_average(&x, &y, rdy); #endif #endif if (wac_i2c->wac_pdata->x_invert) x = wac_i2c->wac_feature->x_max - x; if (wac_i2c->wac_pdata->y_invert) y = wac_i2c->wac_feature->y_max - y; if (wac_i2c->wac_pdata->xy_switch) { tmp = x; x = y; y = tmp; } #ifdef COOR_WORK_AROUND /* Add offset */ x = x + tilt_offsetX[user_hand][screen_rotate]; y = y + tilt_offsetY[user_hand][screen_rotate]; #endif if (wacom_i2c_coord_range(&x, &y)) { input_report_abs(wac_i2c->input_dev, ABS_X, x); input_report_abs(wac_i2c->input_dev, ABS_Y, y); input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, pressure); input_report_key(wac_i2c->input_dev, BTN_STYLUS, stylus); input_report_key(wac_i2c->input_dev, BTN_TOUCH, prox); input_report_key(wac_i2c->input_dev, wac_i2c->tool, 1); input_sync(wac_i2c->input_dev); if (prox && !wac_i2c->pen_pressed) { #ifdef SEC_DVFS_LOCK set_dvfs_lock(wac_i2c, true); #endif #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] is pressed(%d,%d,%d)(%d)\n", x, y, pressure, wac_i2c->tool); #else printk(KERN_DEBUG "[E-PEN] pressed\n"); #endif } else if (!prox && wac_i2c->pen_pressed) { #ifdef SEC_DVFS_LOCK set_dvfs_lock(wac_i2c, false); #endif #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] is released(%d,%d,%d)(%d)\n", x, y, pressure, wac_i2c->tool); #else printk(KERN_DEBUG "[E-PEN] released\n"); #endif } wac_i2c->pen_pressed = prox; #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) if (stylus && !wac_i2c->side_pressed) printk(KERN_DEBUG "[E-PEN] side on"); else if (!stylus && wac_i2c->side_pressed) printk(KERN_DEBUG "[E-PEN] side off"); #endif wac_i2c->side_pressed = stylus; } #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) else printk("[E-PEN] raw data x=0x%x, y=0x%x\n", x, y); #endif } else { #ifdef COOR_WORK_AROUND /* enable emr device */ wacom_i2c_coord_average(0, 0, 0); #endif if (wac_i2c->pen_prox) { /* input_report_abs(wac->input_dev, ABS_X, x); */ /* input_report_abs(wac->input_dev, ABS_Y, y); */ input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0); input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0); input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0); input_report_key(wac_i2c->input_dev, wac_i2c->tool, 0); input_sync(wac_i2c->input_dev); #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) if (wac_i2c->pen_pressed || wac_i2c->side_pressed) printk(KERN_DEBUG "[E-PEN] is out"); else printk(KERN_DEBUG "[E-PEN] is out"); #endif } wac_i2c->pen_prox = 0; wac_i2c->pen_pressed = 0; wac_i2c->side_pressed = 0; #ifdef SEC_DVFS_LOCK set_dvfs_lock(wac_i2c, false); #endif } } else { printk(KERN_ERR "[E-PEN]: failed to read i2c\n"); return -1; } return 0; }
static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_rec) { struct device *dev = md->dev; struct cyttsp4_sysinfo *si = md->si; struct cyttsp4_touch tch; int sig; int i, j, t = 0; int mt_sync_count = 0; DECLARE_BITMAP(ids, max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)); bitmap_zero(ids, si->si_ofs.tch_abs[CY_TCH_T].max); for (i = 0; i < num_cur_rec; i++) { cyttsp4_get_touch_record(md->dev, i, tch.abs); /* Discard proximity event */ if (tch.abs[CY_TCH_O] == CY_OBJ_PROXIMITY) { dev_dbg(dev, "%s: Discarding proximity event\n", __func__); continue; } if ((tch.abs[CY_TCH_T] < md->pdata->frmwrk->abs [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]) || (tch.abs[CY_TCH_T] > md->pdata->frmwrk->abs [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST])) { dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n", __func__, i, tch.abs[CY_TCH_T], md->pdata->frmwrk->abs[(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST]); if (md->mt_function.input_sync) md->mt_function.input_sync(md->input); mt_sync_count++; continue; } /* Process touch */ cyttsp4_mt_process_touch(md, &tch); /* use 0 based track id's */ sig = md->pdata->frmwrk->abs [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + 0]; if (sig != CY_IGNORE_VALUE) { t = tch.abs[CY_TCH_T] - md->pdata->frmwrk->abs [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]; if (tch.abs[CY_TCH_E] == CY_EV_LIFTOFF) { dev_dbg(dev, "%s: t=%d e=%d lift-off\n", __func__, t, tch.abs[CY_TCH_E]); #if defined(TSP_BOOSTER) if(num_cur_rec==1){ set_dvfs_lock(md, 0, false); } #endif printk("TSP is released \n"); printk("%s: tcn=[%d] e=%d RELEASE x=%d, y=%d \n",__func__, num_cur_rec, tch.abs[CY_TCH_E], tch.abs[CY_TCH_X], tch.abs[CY_TCH_Y]); goto cyttsp4_get_mt_touches_pr_tch; } if (tch.abs[CY_TCH_E] == CY_EV_TOUCHDOWN){ printk("TSP is pressed \n"); printk("%s: tcn=[%d] e=%d PRESS x=%d, y=%d \n",__func__, num_cur_rec, tch.abs[CY_TCH_E], tch.abs[CY_TCH_X], tch.abs[CY_TCH_Y]); #if defined(TSP_BOOSTER) set_dvfs_lock(md, 1,true); #endif } if (md->mt_function.input_report) md->mt_function.input_report(md->input, sig, t, tch.abs[CY_TCH_O]); __set_bit(t, ids); } /* all devices: position and pressure fields */ for (j = 0; j <= CY_ABS_W_OST ; j++) { sig = md->pdata->frmwrk->abs[((CY_ABS_X_OST + j) * CY_NUM_ABS_SET) + 0]; if (sig != CY_IGNORE_VALUE) input_report_abs(md->input, sig, tch.abs[CY_TCH_X + j]); } if (IS_TTSP_VER_GE(si, 2, 3)) { /* * TMA400 size and orientation fields: * if pressure is non-zero and major touch * signal is zero, then set major and minor touch * signals to minimum non-zero value */ if (tch.abs[CY_TCH_P] > 0 && tch.abs[CY_TCH_MAJ] == 0) tch.abs[CY_TCH_MAJ] = tch.abs[CY_TCH_MIN] = 1; /* Get the extended touch fields */ for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) { sig = md->pdata->frmwrk->abs [((CY_ABS_MAJ_OST + j) * CY_NUM_ABS_SET) + 0]; if (sig != CY_IGNORE_VALUE) input_report_abs(md->input, sig, tch.abs[CY_TCH_MAJ + j]); } } if (md->mt_function.input_sync) md->mt_function.input_sync(md->input); mt_sync_count++; cyttsp4_get_mt_touches_pr_tch: if (IS_TTSP_VER_GE(si, 2, 3)) dev_info(dev, "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d\n", __func__, t, tch.abs[CY_TCH_X], tch.abs[CY_TCH_Y], tch.abs[CY_TCH_P], tch.abs[CY_TCH_MAJ], tch.abs[CY_TCH_MIN], tch.abs[CY_TCH_OR], tch.abs[CY_TCH_E]); else dev_info(dev, "%s: t=%d x=%d y=%d z=%d e=%d\n", __func__, t, tch.abs[CY_TCH_X], tch.abs[CY_TCH_Y], tch.abs[CY_TCH_P], tch.abs[CY_TCH_E]); } if (md->mt_function.final_sync) md->mt_function.final_sync(md->input, si->si_ofs.tch_abs[CY_TCH_T].max, mt_sync_count, ids); md->num_prv_rec = num_cur_rec; md->prv_tch_type = tch.abs[CY_TCH_O]; return; }
int wacom_i2c_coord(struct wacom_i2c *wac_i2c) { bool prox = false; int ret = 0; u8 *data; int rubber, stylus; static u16 x, y, pressure; static u16 tmp; int rdy = 0; #ifdef WACOM_IRQ_WORK_AROUND cancel_delayed_work(&wac_i2c->pendct_dwork); #endif data = wac_i2c->wac_feature->data; ret = i2c_master_recv(wac_i2c->client, data, COM_COORD_NUM); if (ret < 0) { printk(KERN_ERR "[E-PEN] %s failed to read i2c.L%d\n", __func__, __LINE__); return -1; } #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) pr_debug("[E-PEN] %x, %x, %x, %x, %x, %x, %x\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6]); #endif if (data[0] & 0x80) { /* enable emr device */ if (!wac_i2c->pen_prox) { wac_i2c->pen_prox = 1; if (data[0] & 0x40) wac_i2c->tool = BTN_TOOL_RUBBER; else wac_i2c->tool = BTN_TOOL_PEN; #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) pr_debug("[E-PEN] is in(%d)\n", wac_i2c->tool); #endif } prox = !!(data[0] & 0x10); stylus = !!(data[0] & 0x20); rubber = !!(data[0] & 0x40); rdy = !!(data[0] & 0x80); x = ((u16) data[1] << 8) + (u16) data[2]; y = ((u16) data[3] << 8) + (u16) data[4]; pressure = ((u16) data[5] << 8) + (u16) data[6]; #if defined(CONFIG_MACH_P4NOTE) if (!wac_i2c->pen_type) { pressure = (12 * pressure) / 10; if (pressure > wac_i2c->wac_feature->pressure_max) pressure = wac_i2c->wac_feature->pressure_max; } #endif #ifdef WACOM_IMPORT_FW_ALGO /* Change Position to Active Area */ if (x <= origin_offset[0]) x = 0; else x = x - origin_offset[0]; if (y <= origin_offset[1]) y = 0; else y = y - origin_offset[1]; #ifdef COOR_WORK_AROUND wacom_i2c_coord_offset(&x, &y); wacom_i2c_coord_average(&x, &y, rdy); #endif #endif if (wac_i2c->wac_pdata->x_invert) x = wac_i2c->wac_feature->x_max - x; if (wac_i2c->wac_pdata->y_invert) y = wac_i2c->wac_feature->y_max - y; if (wac_i2c->wac_pdata->xy_switch) { tmp = x; x = y; y = tmp; } #ifdef COOR_WORK_AROUND /* Add offset */ x = x + tilt_offsetX[user_hand][screen_rotate]; y = y + tilt_offsetY[user_hand][screen_rotate]; #endif if (wacom_i2c_coord_range(&x, &y)) { input_report_abs(wac_i2c->input_dev, ABS_X, x); input_report_abs(wac_i2c->input_dev, ABS_Y, y); input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, pressure); input_report_key(wac_i2c->input_dev, BTN_STYLUS, stylus); input_report_key(wac_i2c->input_dev, BTN_TOUCH, prox); input_report_key(wac_i2c->input_dev, wac_i2c->tool, 1); input_sync(wac_i2c->input_dev); if (prox && !wac_i2c->pen_pressed) { #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(wac_i2c, true); #endif #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] is pressed(%d,%d,%d)(%d)\n", x, y, pressure, wac_i2c->tool); #else printk(KERN_DEBUG "[E-PEN] pressed\n"); #endif } else if (!prox && wac_i2c->pen_pressed) { #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(wac_i2c, false); #endif #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) printk(KERN_DEBUG "[E-PEN] is released(%d,%d,%d)(%d)\n", x, y, pressure, wac_i2c->tool); #else printk(KERN_DEBUG "[E-PEN] released\n"); #endif } wac_i2c->pen_pressed = prox; if (stylus && !wac_i2c->side_pressed) printk(KERN_DEBUG "[E-PEN] side on\n"); else if (!stylus && wac_i2c->side_pressed) printk(KERN_DEBUG "[E-PEN] side off\n"); wac_i2c->side_pressed = stylus; } #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER) else printk(KERN_DEBUG "[E-PEN] raw data x=0x%x, y=0x%x\n", x, y); #endif } else { #ifdef WACOM_IRQ_WORK_AROUND if (!gpio_get_value(wac_i2c->wac_pdata->gpio_pendct)) { x = ((u16) data[1] << 8) + (u16) data[2]; y = ((u16) data[3] << 8) + (u16) data[4]; if (data[0] & 0x40) wac_i2c->tool = BTN_TOOL_RUBBER; else wac_i2c->tool = BTN_TOOL_PEN; input_report_abs(wac_i2c->input_dev, ABS_X, x); input_report_abs(wac_i2c->input_dev, ABS_Y, y); input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0); input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0); input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0); input_report_key(wac_i2c->input_dev, wac_i2c->tool, 1); input_sync(wac_i2c->input_dev); } schedule_delayed_work(&wac_i2c->pendct_dwork, HZ / 10); return 0; #else /* WACOM_IRQ_WORK_AROUND */ #ifdef COOR_WORK_AROUND /* enable emr device */ wacom_i2c_coord_average(0, 0, 0); #endif #ifdef WACOM_PDCT_WORK_AROUND if (wac_i2c->pen_pdct == PDCT_DETECT_PEN) forced_hover(wac_i2c); else #endif if (wac_i2c->pen_prox) { /* input_report_abs(wac->input_dev, ABS_X, x); */ /* input_report_abs(wac->input_dev, ABS_Y, y); */ input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0); input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0); input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0); #if defined(WACOM_PDCT_WORK_AROUND) input_report_key(wac_i2c->input_dev, BTN_TOOL_RUBBER, 0); input_report_key(wac_i2c->input_dev, BTN_TOOL_PEN, 0); #else input_report_key(wac_i2c->input_dev, wac_i2c->tool, 0); #endif input_sync(wac_i2c->input_dev); printk(KERN_DEBUG "[E-PEN] is out"); } wac_i2c->pen_prox = 0; wac_i2c->pen_pressed = 0; wac_i2c->side_pressed = 0; #ifdef CONFIG_SEC_TOUCHSCREEN_DVFS_LOCK set_dvfs_lock(wac_i2c, false); #endif #endif } return 0; }