1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006 |
- /*
- * pt_mt_common.c
- * Parade TrueTouch(TM) Standard Product Multi-Touch Reports Module.
- * For use with Parade touchscreen controllers.
- * Supported parts include:
- * TMA5XX
- * TMA448
- * TMA445A
- * TT21XXX
- * TT31XXX
- * TT4XXXX
- * TT7XXX
- * TC3XXX
- *
- * Copyright (C) 2015-2020 Parade Technologies
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2, and only version 2, as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * Contact Parade Technologies at www.paradetech.com <[email protected]>
- */
- #include "pt_regs.h"
- #define MT_PARAM_SIGNAL(md, sig_ost) PARAM_SIGNAL(md->pdata->frmwrk, sig_ost)
- #define MT_PARAM_MIN(md, sig_ost) PARAM_MIN(md->pdata->frmwrk, sig_ost)
- #define MT_PARAM_MAX(md, sig_ost) PARAM_MAX(md->pdata->frmwrk, sig_ost)
- #define MT_PARAM_FUZZ(md, sig_ost) PARAM_FUZZ(md->pdata->frmwrk, sig_ost)
- #define MT_PARAM_FLAT(md, sig_ost) PARAM_FLAT(md->pdata->frmwrk, sig_ost)
- /*******************************************************************************
- * FUNCTION: pt_mt_lift_all
- *
- * SUMMARY: Reports touch liftoff action
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- ******************************************************************************/
- static void pt_mt_lift_all(struct pt_mt_data *md)
- {
- int max = md->si->tch_abs[PT_TCH_T].max;
- if (md->num_prv_rec != 0) {
- if (md->mt_function.report_slot_liftoff)
- md->mt_function.report_slot_liftoff(md, max);
- input_sync(md->input);
- md->num_prv_rec = 0;
- }
- }
- /*******************************************************************************
- * FUNCTION: pt_get_touch_axis
- *
- * SUMMARY: Calculates touch axis
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- * *axis - pointer to axis calculation result
- * size - size in byte
- * max - max value of result
- * *xy_data - pointer to input data to be parsed
- * bofs - bit offset
- ******************************************************************************/
- static void pt_get_touch_axis(struct pt_mt_data *md,
- int *axis, int size, int max, u8 *xy_data, int bofs)
- {
- int nbyte;
- int next;
- for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
- pt_debug(md->dev, DL_DEBUG,
- "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
- __func__, *axis, *axis, size, max, xy_data, next,
- xy_data[next], xy_data[next], bofs);
- *axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
- next++;
- }
- *axis &= max - 1;
- pt_debug(md->dev, DL_DEBUG,
- "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
- __func__, *axis, *axis, size, max, xy_data, next,
- xy_data[next], xy_data[next]);
- }
- /*******************************************************************************
- * FUNCTION: pt_get_touch_hdr
- *
- * SUMMARY: Get the header of touch report
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- * *touch - pointer to pt_touch structure
- * *xy_mode - pointer to touch mode data
- ******************************************************************************/
- static void pt_get_touch_hdr(struct pt_mt_data *md,
- struct pt_touch *touch, u8 *xy_mode)
- {
- struct device *dev = md->dev;
- struct pt_sysinfo *si = md->si;
- enum pt_tch_hdr hdr;
- for (hdr = PT_TCH_TIME; hdr < PT_TCH_NUM_HDR; hdr++) {
- if (!si->tch_hdr[hdr].report)
- continue;
- pt_get_touch_axis(md, &touch->hdr[hdr],
- si->tch_hdr[hdr].size,
- si->tch_hdr[hdr].max,
- xy_mode + si->tch_hdr[hdr].ofs,
- si->tch_hdr[hdr].bofs);
- pt_debug(dev, DL_DEBUG, "%s: get %s=%04X(%d)\n",
- __func__, pt_tch_hdr_string[hdr],
- touch->hdr[hdr], touch->hdr[hdr]);
- }
- pt_debug(dev, DL_INFO,
- "%s: time=%X tch_num=%d lo=%d noise=%d counter=%d\n",
- __func__,
- touch->hdr[PT_TCH_TIME],
- touch->hdr[PT_TCH_NUM],
- touch->hdr[PT_TCH_LO],
- touch->hdr[PT_TCH_NOISE],
- touch->hdr[PT_TCH_COUNTER]);
- }
- /*******************************************************************************
- * FUNCTION: pt_get_touch_record
- *
- * SUMMARY: Gets axis of touch report
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- * *touch - pointer to pt_touch structure
- * *xy_data - pointer to touch data
- ******************************************************************************/
- static void pt_get_touch_record(struct pt_mt_data *md,
- struct pt_touch *touch, u8 *xy_data)
- {
- struct device *dev = md->dev;
- struct pt_sysinfo *si = md->si;
- enum pt_tch_abs abs;
- for (abs = PT_TCH_X; abs < PT_TCH_NUM_ABS; abs++) {
- if (!si->tch_abs[abs].report)
- continue;
- pt_get_touch_axis(md, &touch->abs[abs],
- si->tch_abs[abs].size,
- si->tch_abs[abs].max,
- xy_data + si->tch_abs[abs].ofs,
- si->tch_abs[abs].bofs);
- pt_debug(dev, DL_DEBUG, "%s: get %s=%04X(%d)\n",
- __func__, pt_tch_abs_string[abs],
- touch->abs[abs], touch->abs[abs]);
- }
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_process_touch
- *
- * SUMMARY: Process touch includes oritation,axis invert and
- * convert MAJOR/MINOR from mm to resolution
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- * *touch - pointer to pt_touch structure
- ******************************************************************************/
- static void pt_mt_process_touch(struct pt_mt_data *md,
- struct pt_touch *touch)
- {
- struct device *dev = md->dev;
- struct pt_sysinfo *si = md->si;
- int tmp;
- bool flipped;
- /* Orientation is signed */
- touch->abs[PT_TCH_OR] = (int8_t)touch->abs[PT_TCH_OR];
- if (md->pdata->flags & PT_MT_FLAG_FLIP) {
- tmp = touch->abs[PT_TCH_X];
- touch->abs[PT_TCH_X] = touch->abs[PT_TCH_Y];
- touch->abs[PT_TCH_Y] = tmp;
- if (touch->abs[PT_TCH_OR] > 0)
- touch->abs[PT_TCH_OR] =
- md->or_max - touch->abs[PT_TCH_OR];
- else
- touch->abs[PT_TCH_OR] =
- md->or_min - touch->abs[PT_TCH_OR];
- flipped = true;
- } else
- flipped = false;
- /*
- * 1 is subtracted from each touch location to make the location
- * 0 based. e.g. If the resolution of touch panel is 1200x1600,
- * the FW touch report must be (0~1199,0~1599). The driver
- * should register the (min,max) value to Linux input system as
- * (0~1199,0~1599). When the host needs to invert the
- * coordinates, the driver would incorrectly use the resolution
- * to subtract the reported point directly, such as
- * 1200-(0~1199). The input system will lose the 0 point report
- * and the 1200 point will be ignored.
- */
- if (md->pdata->flags & PT_MT_FLAG_INV_X) {
- if (flipped)
- touch->abs[PT_TCH_X] = si->sensing_conf_data.res_y -
- touch->abs[PT_TCH_X] - 1;
- else
- touch->abs[PT_TCH_X] = si->sensing_conf_data.res_x -
- touch->abs[PT_TCH_X] - 1;
- touch->abs[PT_TCH_OR] *= -1;
- }
- if (md->pdata->flags & PT_MT_FLAG_INV_Y) {
- if (flipped)
- touch->abs[PT_TCH_Y] = si->sensing_conf_data.res_x -
- touch->abs[PT_TCH_Y] - 1;
- else
- touch->abs[PT_TCH_Y] = si->sensing_conf_data.res_y -
- touch->abs[PT_TCH_Y] - 1;
- touch->abs[PT_TCH_OR] *= -1;
- }
- /* Convert MAJOR/MINOR from mm to resolution */
- tmp = touch->abs[PT_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
- touch->abs[PT_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
- tmp = touch->abs[PT_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
- touch->abs[PT_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
- pt_debug(dev, DL_INFO,
- "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n",
- __func__, flipped ? "true" : "false",
- md->pdata->flags & PT_MT_FLAG_INV_X ? "true" : "false",
- md->pdata->flags & PT_MT_FLAG_INV_Y ? "true" : "false",
- touch->abs[PT_TCH_X], touch->abs[PT_TCH_X],
- touch->abs[PT_TCH_Y], touch->abs[PT_TCH_Y]);
- }
- /*******************************************************************************
- * FUNCTION: pt_report_event
- *
- * SUMMARY: Reports touch event
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- * event - type of touch event
- * value - value of report event
- ******************************************************************************/
- static void pt_report_event(struct pt_mt_data *md, int event,
- int value)
- {
- int sig = MT_PARAM_SIGNAL(md, event);
- if (sig != PT_IGNORE_VALUE)
- input_report_abs(md->input, sig, value);
- }
- /*******************************************************************************
- * FUNCTION: pt_get_mt_touches
- *
- * SUMMARY: Parse and report touch event
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- * *tch - pointer to touch structure
- * num_cur_tch - number of current touch
- ******************************************************************************/
- static void pt_get_mt_touches(struct pt_mt_data *md,
- struct pt_touch *tch, int num_cur_tch)
- {
- struct device *dev = md->dev;
- struct pt_sysinfo *si = md->si;
- int sig;
- int i, j, t = 0;
- DECLARE_BITMAP(ids, PT_TOUCH_ID_MAX);
- int mt_sync_count = 0;
- u8 *tch_addr;
- if (PT_TOUCH_ID_MAX < si->tch_abs[PT_TCH_T].max) {
- pt_debug(dev, DL_ERROR,
- "%s: Touch ID num %d is allocated less than needed %d\n",
- __func__, PT_TOUCH_ID_MAX, si->tch_abs[PT_TCH_T].max);
- return;
- }
- bitmap_zero(ids, PT_TOUCH_ID_MAX);
- memset(tch->abs, 0, sizeof(tch->abs));
- for (i = 0; i < num_cur_tch; i++) {
- tch_addr = si->xy_data + (i * si->desc.tch_record_size);
- pt_get_touch_record(md, tch, tch_addr);
- /* Discard proximity event */
- if (tch->abs[PT_TCH_O] == PT_OBJ_PROXIMITY) {
- pt_debug(dev, DL_INFO,
- "%s: Discarding proximity event\n",
- __func__);
- continue;
- }
- /* Validate track_id */
- t = tch->abs[PT_TCH_T];
- if (t < md->t_min || t > md->t_max) {
- pt_debug(dev, DL_INFO,
- "%s: tch=%d -> bad trk_id=%d max_id=%d\n",
- __func__, i, t, md->t_max);
- if (md->mt_function.input_sync)
- md->mt_function.input_sync(md->input);
- mt_sync_count++;
- continue;
- }
- /* Lift-off */
- if (tch->abs[PT_TCH_E] == PT_EV_LIFTOFF) {
- pt_debug(dev, DL_INFO, "%s: t=%d e=%d lift-off\n",
- __func__, t, tch->abs[PT_TCH_E]);
- goto pt_get_mt_touches_pr_tch;
- }
- /* Process touch */
- pt_mt_process_touch(md, tch);
- /* use 0 based track id's */
- t -= md->t_min;
- sig = MT_PARAM_SIGNAL(md, PT_ABS_ID_OST);
- if (sig != PT_IGNORE_VALUE) {
- if (md->mt_function.input_report)
- md->mt_function.input_report(md->input, sig,
- t, tch->abs[PT_TCH_O]);
- __set_bit(t, ids);
- }
- pt_report_event(md, PT_ABS_D_OST, 0);
- /* all devices: position and pressure fields */
- for (j = 0; j <= PT_ABS_W_OST; j++) {
- if (!si->tch_abs[j].report)
- continue;
- pt_report_event(md, PT_ABS_X_OST + j,
- tch->abs[PT_TCH_X + j]);
- }
- /* Get the extended touch fields */
- for (j = 0; j < PT_NUM_EXT_TCH_FIELDS; j++) {
- if (!si->tch_abs[PT_ABS_MAJ_OST + j].report)
- continue;
- pt_report_event(md, PT_ABS_MAJ_OST + j,
- tch->abs[PT_TCH_MAJ + j]);
- }
- if (md->mt_function.input_sync)
- md->mt_function.input_sync(md->input);
- mt_sync_count++;
- pt_get_mt_touches_pr_tch:
- pt_debug(dev, DL_INFO,
- "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d obj=%d tip=%d\n",
- __func__, t,
- tch->abs[PT_TCH_X],
- tch->abs[PT_TCH_Y],
- tch->abs[PT_TCH_P],
- tch->abs[PT_TCH_MAJ],
- tch->abs[PT_TCH_MIN],
- tch->abs[PT_TCH_OR],
- tch->abs[PT_TCH_E],
- tch->abs[PT_TCH_O],
- tch->abs[PT_TCH_TIP]);
- }
- if (md->mt_function.final_sync)
- md->mt_function.final_sync(md->input,
- si->tch_abs[PT_TCH_T].max, mt_sync_count, ids);
- md->num_prv_rec = num_cur_tch;
- }
- /*******************************************************************************
- * FUNCTION: pt_xy_worker
- *
- * SUMMARY: Read xy_data for all current touches
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *md - pointer to touch data structure
- ******************************************************************************/
- static int pt_xy_worker(struct pt_mt_data *md)
- {
- struct device *dev = md->dev;
- struct pt_sysinfo *si = md->si;
- int max_tch = si->sensing_conf_data.max_tch;
- struct pt_touch tch;
- u8 num_cur_tch;
- int rc = 0;
- pt_get_touch_hdr(md, &tch, si->xy_mode + 3);
- num_cur_tch = tch.hdr[PT_TCH_NUM];
- if (num_cur_tch > max_tch) {
- pt_debug(dev, DL_ERROR, "%s: Num touch err detected (n=%d)\n",
- __func__, num_cur_tch);
- num_cur_tch = max_tch;
- }
- if (tch.hdr[PT_TCH_LO]) {
- pt_debug(dev, DL_INFO, "%s: Large area detected\n",
- __func__);
- if (md->pdata->flags & PT_MT_FLAG_NO_TOUCH_ON_LO)
- num_cur_tch = 0;
- }
- if (num_cur_tch == 0 && md->num_prv_rec == 0)
- goto pt_xy_worker_exit;
- /* extract xy_data for all currently reported touches */
- pt_debug(dev, DL_DEBUG, "%s: extract data num_cur_tch=%d\n",
- __func__, num_cur_tch);
- if (num_cur_tch)
- pt_get_mt_touches(md, &tch, num_cur_tch);
- else
- pt_mt_lift_all(md);
- rc = 0;
- pt_xy_worker_exit:
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_send_dummy_event
- *
- * SUMMARY: Send dummy/key event to wakeup upper layer of system
- *
- * PARAMETERS:
- * *cd - pointer to core data structure
- * *md - pointer to touch data structure
- ******************************************************************************/
- static void pt_mt_send_dummy_event(struct pt_core_data *cd,
- struct pt_mt_data *md)
- {
- #ifndef EASYWAKE_TSG6
- /* TSG5 EasyWake */
- unsigned long ids = 0;
- /* for easy wakeup */
- if (md->mt_function.input_report)
- md->mt_function.input_report(md->input, ABS_MT_TRACKING_ID,
- 0, PT_OBJ_STANDARD_FINGER);
- if (md->mt_function.input_sync)
- md->mt_function.input_sync(md->input);
- if (md->mt_function.final_sync)
- md->mt_function.final_sync(md->input, 0, 1, &ids);
- if (md->mt_function.report_slot_liftoff)
- md->mt_function.report_slot_liftoff(md, 1);
- if (md->mt_function.final_sync)
- md->mt_function.final_sync(md->input, 1, 1, &ids);
- #else
- /* TSG6 FW1.3 and above only. TSG6 FW1.0 - 1.2 does not */
- /* support EasyWake, and this function will not be called */
- u8 key_value = 0;
- switch (cd->gesture_id) {
- case GESTURE_DOUBLE_TAP:
- key_value = KEY_WAKEUP;
- break;
- case GESTURE_TWO_FINGERS_SLIDE:
- key_value = KEY_WAKEUP;
- break;
- case GESTURE_TOUCH_DETECTED:
- key_value = KEY_WAKEUP;
- break;
- case GESTURE_PUSH_BUTTON:
- key_value = KEY_F4;
- break;
- case GESTURE_SINGLE_SLIDE_DE_TX:
- key_value = KEY_F5;
- break;
- case GESTURE_SINGLE_SLIDE_IN_TX:
- key_value = KEY_F6;
- break;
- case GESTURE_SINGLE_SLIDE_DE_RX:
- key_value = KEY_F7;
- break;
- case GESTURE_SINGLE_SLIDE_IN_RX:
- key_value = KEY_F8;
- break;
- default:
- break;
- }
- if (key_value > 0) {
- input_report_key(md->input, key_value, 1);
- input_sync(md->input);
- input_report_key(md->input, key_value, 0);
- input_sync(md->input);
- }
- /*
- * Caution - this debug print is needed by the TTDL automated
- * regression test suite
- */
- pt_debug(md->dev, DL_INFO, "%s: report key: %d\n",
- __func__, key_value);
- #endif
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_attention
- *
- * SUMMARY: Wrapper function for pt_xy_worker() that subscribe into the TTDL
- * attention list.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_mt_attention(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- int rc;
- if (md->si->xy_mode[2] != md->si->desc.tch_report_id)
- return 0;
- /* core handles handshake */
- mutex_lock(&md->mt_lock);
- rc = pt_xy_worker(md);
- mutex_unlock(&md->mt_lock);
- if (rc < 0)
- pt_debug(dev, DL_ERROR,
- "%s: xy_worker error r=%d\n", __func__, rc);
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_wake_attention
- *
- * SUMMARY: Wrapper function for pt_mt_send_dummy_event() that register to
- * attention list.
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_mt_wake_attention(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- mutex_lock(&md->mt_lock);
- pt_mt_send_dummy_event(cd, md);
- mutex_unlock(&md->mt_lock);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_startup_attention
- *
- * SUMMARY: Wrapper function for pt_mt_lift_all() that subcribe into the TTDL
- * attention list.
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_startup_attention(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- mutex_lock(&md->mt_lock);
- pt_mt_lift_all(md);
- mutex_unlock(&md->mt_lock);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_suspend_attention
- *
- * SUMMARY: Function for touch to enter suspend state that as following steps:
- * 1) Lift all touch
- * 2) Set flag with suspend state
- * 3) Decrese pm system count
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_mt_suspend_attention(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- mutex_lock(&md->mt_lock);
- pt_mt_lift_all(md);
- md->is_suspended = true;
- mutex_unlock(&md->mt_lock);
- pm_runtime_put(dev);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_resume_attention
- *
- * SUMMARY: Function for touch to leave suspend state that as following steps:
- * 1) Increse pm system count
- * 2) Clear suspend state flag
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_mt_resume_attention(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- pm_runtime_get(dev);
- mutex_lock(&md->mt_lock);
- md->is_suspended = false;
- mutex_unlock(&md->mt_lock);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_open
- *
- * SUMMARY: Open method for input device(touch) that sets up call back
- * functions to TTDL attention list
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *input - pointer to input_dev structure
- ******************************************************************************/
- static int pt_mt_open(struct input_dev *input)
- {
- struct device *dev = input->dev.parent;
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- pm_runtime_get_sync(dev);
- mutex_lock(&md->mt_lock);
- md->is_suspended = false;
- mutex_unlock(&md->mt_lock);
- pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
- /* set up touch call back */
- _pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_MT_NAME,
- pt_mt_attention, PT_MODE_OPERATIONAL);
- /* set up startup call back */
- _pt_subscribe_attention(dev, PT_ATTEN_STARTUP, PT_MT_NAME,
- pt_startup_attention, 0);
- /* set up wakeup call back */
- _pt_subscribe_attention(dev, PT_ATTEN_WAKE, PT_MT_NAME,
- pt_mt_wake_attention, 0);
- /* set up suspend call back */
- _pt_subscribe_attention(dev, PT_ATTEN_SUSPEND, PT_MT_NAME,
- pt_mt_suspend_attention, 0);
- /* set up resume call back */
- _pt_subscribe_attention(dev, PT_ATTEN_RESUME, PT_MT_NAME,
- pt_mt_resume_attention, 0);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_close
- *
- * SUMMARY: Close method for input device(touch) that clears call back
- * functions from TTDL attention list.
- *
- * PARAMETERS:
- * *input - pointer to input_dev structure
- ******************************************************************************/
- static void pt_mt_close(struct input_dev *input)
- {
- struct device *dev = input->dev.parent;
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- _pt_unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_MT_NAME,
- pt_mt_attention, PT_MODE_OPERATIONAL);
- _pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_MT_NAME,
- pt_startup_attention, 0);
- _pt_unsubscribe_attention(dev, PT_ATTEN_WAKE, PT_MT_NAME,
- pt_mt_wake_attention, 0);
- _pt_unsubscribe_attention(dev, PT_ATTEN_SUSPEND, PT_MT_NAME,
- pt_mt_suspend_attention, 0);
- _pt_unsubscribe_attention(dev, PT_ATTEN_RESUME, PT_MT_NAME,
- pt_mt_resume_attention, 0);
- mutex_lock(&md->mt_lock);
- if (!md->is_suspended) {
- pm_runtime_put(dev);
- md->is_suspended = true;
- }
- mutex_unlock(&md->mt_lock);
- }
- /*******************************************************************************
- * FUNCTION: pt_setup_input_device
- *
- * SUMMARY: Set up resolution, event signal capabilities and
- * register input device for touch.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_setup_input_device(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- int signal = PT_IGNORE_VALUE;
- int max_x, max_y, max_p, min, max;
- int max_x_tmp, max_y_tmp;
- int i;
- int rc;
- pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
- __func__);
- __set_bit(EV_ABS, md->input->evbit);
- __set_bit(EV_REL, md->input->evbit);
- __set_bit(EV_KEY, md->input->evbit);
- #ifdef INPUT_PROP_DIRECT
- __set_bit(INPUT_PROP_DIRECT, md->input->propbit);
- #endif
- /* If virtualkeys enabled, don't use all screen */
- if (md->pdata->flags & PT_MT_FLAG_VKEYS) {
- max_x_tmp = md->pdata->vkeys_x;
- max_y_tmp = md->pdata->vkeys_y;
- } else {
- max_x_tmp = md->si->sensing_conf_data.res_x;
- max_y_tmp = md->si->sensing_conf_data.res_y;
- }
- /* get maximum values from the sysinfo data */
- if (md->pdata->flags & PT_MT_FLAG_FLIP) {
- max_x = max_y_tmp - 1;
- max_y = max_x_tmp - 1;
- } else {
- max_x = max_x_tmp - 1;
- max_y = max_y_tmp - 1;
- }
- max_p = md->si->sensing_conf_data.max_z;
- /* set event signal capabilities */
- for (i = 0; i < NUM_SIGNALS(md->pdata->frmwrk); i++) {
- signal = MT_PARAM_SIGNAL(md, i);
- if (signal != PT_IGNORE_VALUE) {
- __set_bit(signal, md->input->absbit);
- min = MT_PARAM_MIN(md, i);
- max = MT_PARAM_MAX(md, i);
- if (i == PT_ABS_ID_OST) {
- /* shift track ids down to start at 0 */
- max = max - min;
- min = min - min;
- } else if (i == PT_ABS_X_OST)
- max = max_x;
- else if (i == PT_ABS_Y_OST)
- max = max_y;
- else if (i == PT_ABS_P_OST)
- max = max_p;
- input_set_abs_params(md->input, signal, min, max,
- MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
- pt_debug(dev, DL_INFO,
- "%s: register signal=%02X min=%d max=%d\n",
- __func__, signal, min, max);
- }
- }
- md->or_min = MT_PARAM_MIN(md, PT_ABS_OR_OST);
- md->or_max = MT_PARAM_MAX(md, PT_ABS_OR_OST);
- md->t_min = MT_PARAM_MIN(md, PT_ABS_ID_OST);
- md->t_max = MT_PARAM_MAX(md, PT_ABS_ID_OST);
- rc = md->mt_function.input_register_device(md->input,
- md->si->tch_abs[PT_TCH_T].max);
- if (rc < 0)
- pt_debug(dev, DL_ERROR, "%s: Error, failed register input device r=%d\n",
- __func__, rc);
- else
- md->input_device_registered = true;
- #ifdef EASYWAKE_TSG6
- input_set_capability(md->input, EV_KEY, KEY_F1);
- input_set_capability(md->input, EV_KEY, KEY_F2);
- input_set_capability(md->input, EV_KEY, KEY_F3);
- input_set_capability(md->input, EV_KEY, KEY_F4);
- input_set_capability(md->input, EV_KEY, KEY_F5);
- input_set_capability(md->input, EV_KEY, KEY_F6);
- input_set_capability(md->input, EV_KEY, KEY_F7);
- input_set_capability(md->input, EV_KEY, KEY_F8);
- input_set_capability(md->input, EV_KEY, KEY_WAKEUP);
- #endif
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_setup_input_attention
- *
- * SUMMARY: Wrapper function for pt_setup_input_device() register to TTDL
- * attention list.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_setup_input_attention(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- int rc;
- md->si = _pt_request_sysinfo(dev);
- if (!md->si)
- return -EINVAL;
- rc = pt_setup_input_device(dev);
- _pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_MT_NAME,
- pt_setup_input_attention, 0);
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_probe
- *
- * SUMMARY: The probe function for touch input device
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- int pt_mt_probe(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_mt_data *md = &cd->md;
- struct pt_platform_data *pdata = dev_get_platdata(dev);
- struct pt_mt_platform_data *mt_pdata;
- int rc = 0;
- pt_debug(dev, DL_INFO,
- "%s: >>>>>> Register MT <<<<<<\n", __func__);
- if (!pdata || !pdata->mt_pdata) {
- pt_debug(dev, DL_ERROR,
- "%s: Missing platform data\n", __func__);
- rc = -ENODEV;
- goto error_no_pdata;
- }
- mt_pdata = pdata->mt_pdata;
- pt_init_function_ptrs(md);
- mutex_init(&md->mt_lock);
- md->dev = dev;
- md->pdata = mt_pdata;
- /* Create the input device and register it. */
- pt_debug(dev, DL_INFO,
- "%s: Create the input device and register it\n", __func__);
- md->input = input_allocate_device();
- if (!md->input) {
- pt_debug(dev, DL_ERROR, "%s: Error, failed to allocate input device\n",
- __func__);
- rc = -ENODEV;
- goto error_alloc_failed;
- } else
- md->input_device_allocated = true;
- if (md->pdata->inp_dev_name)
- md->input->name = md->pdata->inp_dev_name;
- else
- md->input->name = PT_MT_NAME;
- scnprintf(md->phys, sizeof(md->phys), "%s/input%d", dev_name(dev),
- cd->phys_num++);
- md->input->phys = md->phys;
- md->input->dev.parent = md->dev;
- md->input->open = pt_mt_open;
- md->input->close = pt_mt_close;
- input_set_drvdata(md->input, md);
- /* get sysinfo */
- md->si = _pt_request_sysinfo(dev);
- if (md->si) {
- rc = pt_setup_input_device(dev);
- if (rc)
- goto error_init_input;
- } else {
- pt_debug(dev, DL_ERROR, "%s: Fail get sysinfo pointer from core p=%p\n",
- __func__, md->si);
- _pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
- PT_MT_NAME, pt_setup_input_attention, 0);
- }
- return 0;
- error_init_input:
- input_free_device(md->input);
- md->input_device_allocated = false;
- error_alloc_failed:
- error_no_pdata:
- pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_mt_release
- *
- * SUMMARY: The release function for touch input device
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- int pt_mt_release(struct device *dev)
- {
- struct pt_core_data *cd;
- struct pt_mt_data *md;
- /* Ensure valid pointers before de-referencing them */
- if (dev) {
- cd = dev_get_drvdata(dev);
- if (cd)
- md = &cd->md;
- else
- return 0;
- } else {
- return 0;
- }
- /*
- * Second call this function may cause kernel panic if probe fail.
- * Use input_device_registered & input_device_allocated variable to
- * avoid unregister or free unavailable devive.
- */
- if (md && md->input_device_registered) {
- md->input_device_registered = false;
- input_unregister_device(md->input);
- /* Unregistering device will free the device too */
- md->input_device_allocated = false;
- } else if (md && md->input_device_allocated) {
- md->input_device_allocated = false;
- input_free_device(md->input);
- _pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
- PT_MT_NAME, pt_setup_input_attention, 0);
- }
- return 0;
- }
|