diff --git a/drivers/input/misc/anc_fps_mmi/jiiov_platform.c b/drivers/input/misc/anc_fps_mmi/jiiov_platform.c index f2af27608cf8..036a5e0ee83e 100644 --- a/drivers/input/misc/anc_fps_mmi/jiiov_platform.c +++ b/drivers/input/misc/anc_fps_mmi/jiiov_platform.c @@ -986,67 +986,6 @@ static int use_gpio_init(struct anc_data *p_data) { return ret_val; } -static int anc_gpio_init(struct anc_data *p_data) { - int ret_val = 0; - - if (p_data == NULL) { - ANC_LOGE("p_data is NULL"); - return -EINVAL; - } - ANC_LOGD("init gpio"); - if (p_data->resource_requested) { - ANC_LOGW("warning: resource is already requested, return!"); - return 0; - } - - if (p_data->vdd_use_gpio) { - ret_val = anc_request_named_gpio(p_data, "anc,gpio_pwr", &p_data->pwr_gpio); - if (ret_val) { - ANC_LOGE("request power gpio failed, ret_val:%d", ret_val); - return ret_val; - } - - ret_val = gpio_direction_output(p_data->pwr_gpio, 0); - if (ret_val) { - ANC_LOGE("power gpio direction output failed, ret_val:%d", ret_val); - return ret_val; - } - } - - if (p_data->use_gpio_init == false) { - ret_val = use_pinctrl_init(p_data); - if (ret_val) { - ANC_LOGE("use pinctrl init failed, ret_val:%d", ret_val); - return ret_val; - } - } - - ret_val = use_gpio_init(p_data); - if (ret_val) { - ANC_LOGE("use gpio init failed, ret_val:%d", ret_val); - return ret_val; - } - -#ifdef SAMSUNG_PLATFORM - /* Init spi clock */ - ret_val = anc_spi_clk_init(p_data); - if (ret_val) { - ANC_LOGE("spi init failed, ret_val:%d", ret_val); - return ret_val; - } -#endif - - if (of_property_read_bool(p_data->dev->of_node, "anc,enable-on-boot")) { - ANC_LOGD("Enabling hardware"); - device_power_up(p_data); - } - - p_data->resource_requested = true; - ANC_LOGD("success"); - - return 0; -} - static int anc_gpio_deinit(struct anc_data *p_data) { if (p_data == NULL) { ANC_LOGE("p_data is NULL"); @@ -1054,10 +993,6 @@ static int anc_gpio_deinit(struct anc_data *p_data) { } ANC_LOGD("deinit gpio"); - if (!p_data->resource_requested) { - ANC_LOGW("warning: resource is already released, return!"); - return 0; - } if (p_data->vdd_use_gpio) { if (gpio_is_valid(p_data->pwr_gpio)) { @@ -1085,12 +1020,71 @@ static int anc_gpio_deinit(struct anc_data *p_data) { anc_spi_clk_deinit(p_data); #endif - p_data->resource_requested = false; ANC_LOGD("success"); return 0; } +static int anc_gpio_init(struct anc_data *p_data) { + int ret_val = 0; + + if (p_data == NULL) { + ANC_LOGE("p_data is NULL"); + return -EINVAL; + } + + ANC_LOGD("init gpio"); + if (p_data->vdd_use_gpio) { + ret_val = anc_request_named_gpio(p_data, "anc,gpio_pwr", &p_data->pwr_gpio); + if (ret_val) { + ANC_LOGE("request power gpio failed, ret_val:%d", ret_val); + goto ANC_INIT_FAIL; + } + + ret_val = gpio_direction_output(p_data->pwr_gpio, 0); + if (ret_val) { + ANC_LOGE("power gpio direction output failed, ret_val:%d", ret_val); + goto ANC_INIT_FAIL; + } + } + + if (p_data->use_gpio_init == false) { + ret_val = use_pinctrl_init(p_data); + if (ret_val) { + ANC_LOGE("use pinctrl init failed, ret_val:%d", ret_val); + goto ANC_INIT_FAIL; + } + } + + ret_val = use_gpio_init(p_data); + if (ret_val) { + ANC_LOGE("use gpio init failed, ret_val:%d", ret_val); + goto ANC_INIT_FAIL; + } + +#ifdef SAMSUNG_PLATFORM + /* Init spi clock */ + ret_val = anc_spi_clk_init(p_data); + if (ret_val) { + ANC_LOGE("spi init failed, ret_val:%d", ret_val); + goto ANC_INIT_FAIL; + } +#endif + + if (of_property_read_bool(p_data->dev->of_node, "anc,enable-on-boot")) { + ANC_LOGD("Enabling hardware"); + device_power_up(p_data); + } + + ANC_LOGD("success"); + + return 0; + +ANC_INIT_FAIL: + anc_gpio_deinit(p_data); + return ret_val; +} + static int anc_open(struct inode *inode, struct file *filp) { struct anc_data *p_data = NULL; p_data = container_of(inode->i_cdev, struct anc_data, cdev); @@ -1110,10 +1104,18 @@ static int anc_platform_init(struct anc_data *p_data) { ANC_LOGE("p_data is NULL"); return -EINVAL; } + + if (p_data->resource_requested) { + ANC_LOGW("warning: resource is already requested, return!"); + return 0; + } + ret_val = anc_gpio_init(p_data); if (ret_val) { ANC_LOGE("Failed to init gpio, ret_val: %d", ret_val); return ret_val; + } else { + p_data->resource_requested = true; } return ret_val; @@ -1126,10 +1128,18 @@ static int anc_platform_free(struct anc_data *p_data) { ANC_LOGE("p_data is NULL"); return -EINVAL; } + + if (!p_data->resource_requested) { + ANC_LOGW("warning: resource is already released, return!"); + return 0; + } + ret_val = anc_gpio_deinit(p_data); if (ret_val) { ANC_LOGE("Failed to deinit gpio"); return ret_val; + } else { + p_data->resource_requested = false; } return ret_val; diff --git a/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c b/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c index ec76edff7a28..e93e929674f5 100644 --- a/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c +++ b/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c @@ -8,6 +8,7 @@ * as published by the Free Software Foundation. */ +#include #include #include #include @@ -28,6 +29,10 @@ #define RESET_HIGH_SLEEP2_MIN_US 5000 #define RESET_HIGH_SLEEP2_MAX_US (RESET_HIGH_SLEEP2_MIN_US + 100) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 25)) +#define devm_gpio_free(a, b) NULL +#endif + struct FPS_data { unsigned int enabled; unsigned int state; diff --git a/drivers/input/misc/goodix_fod_mmi/platform.c b/drivers/input/misc/goodix_fod_mmi/platform.c index 5e1d6b4830d4..6bb245f3f35a 100644 --- a/drivers/input/misc/goodix_fod_mmi/platform.c +++ b/drivers/input/misc/goodix_fod_mmi/platform.c @@ -13,6 +13,7 @@ * GNU General Public License for more details. * */ +#include #include #include #include @@ -30,6 +31,10 @@ #include #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 25)) +#define devm_gpio_free(a, b) NULL +#endif + int gf_parse_dts(struct gf_dev *gf_dev) { int rc = 0; @@ -129,7 +134,9 @@ err_pwr: void gf_cleanup(struct gf_dev *gf_dev) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 25)) struct device *dev = &gf_dev->spi->dev; +#endif pr_info("goodix: %s\n", __func__); if (gpio_is_valid(gf_dev->irq_gpio)) { diff --git a/drivers/input/misc/vl53L1_14_1_2/stmvl53l1_module-i2c.c b/drivers/input/misc/vl53L1_14_1_2/stmvl53l1_module-i2c.c index 348ff40bf2ff..d74e9de32b9a 100644 --- a/drivers/input/misc/vl53L1_14_1_2/stmvl53l1_module-i2c.c +++ b/drivers/input/misc/vl53L1_14_1_2/stmvl53l1_module-i2c.c @@ -501,6 +501,30 @@ done_freemem: return -1; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) +static void stmvl53l1_remove(struct i2c_client *client) +{ + struct stmvl53l1_data *data = i2c_get_clientdata(client); + struct i2c_data *i2c_data = (struct i2c_data *)data->client_object; + + vl53l1_dbgmsg("Enter\n"); + mutex_lock(&data->work_mutex); + + stmvl53l1_sysfs_laser(data, false); + + /* main driver cleanup */ + stmvl53l1_cleanup(data); + + /* release gpios */ + stmvl53l1_release_gpios(i2c_data); + + mutex_unlock(&data->work_mutex); + + stmvl53l1_put(data->client_object); + + vl53l1_dbgmsg("End\n"); +} +#else static int stmvl53l1_remove(struct i2c_client *client) { struct stmvl53l1_data *data = i2c_get_clientdata(client); @@ -525,6 +549,7 @@ static int stmvl53l1_remove(struct i2c_client *client) return 0; } +#endif #ifdef CONFIG_PM_SLEEP static int stmvl53l1_suspend(struct device *dev) diff --git a/drivers/input/touchscreen/focaltech_0flash_v2_mmi/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech_0flash_v2_mmi/focaltech_ex_fun.c index 51b13c1478e7..6179f80169b6 100644 --- a/drivers/input/touchscreen/focaltech_0flash_v2_mmi/focaltech_ex_fun.c +++ b/drivers/input/touchscreen/focaltech_0flash_v2_mmi/focaltech_ex_fun.c @@ -1788,15 +1788,14 @@ static int fts_sysfs_class(void *_data, bool create) int i, error = 0; static struct class *touchscreen_class; static struct device *ts_class_dev; - static int minor; + dev_t devno; if (create) { - minor = input_get_new_minor(data->spi->chip_select, - 1, false); - if (minor < 0) - minor = input_get_new_minor(TSDEV_MINOR_BASE, - TSDEV_MINOR_MAX, true); - pr_info("assigned minor %d\n", minor); + error = alloc_chrdev_region(&devno, 0, 1, FTS_CHIP_NAME); + if (error) { + pr_err("Alloc input devno failed\n"); + return error; + } touchscreen_class = class_create(THIS_MODULE, "touchscreen"); if (IS_ERR(touchscreen_class)) { @@ -1807,11 +1806,11 @@ static int fts_sysfs_class(void *_data, bool create) #ifdef FTS_LAST_TIME_EN ts_class_dev = device_create(touchscreen_class, NULL, - MKDEV(INPUT_MAJOR, minor), + devno, data, FTS_PRIMARY_NAME); #else ts_class_dev = device_create(touchscreen_class, NULL, - MKDEV(INPUT_MAJOR, minor), + devno, data, FTS_CHIP_NAME); #endif @@ -1845,7 +1844,7 @@ static int fts_sysfs_class(void *_data, bool create) device_destroy: for (--i; i >= 0; --i) device_remove_file(ts_class_dev, &attrs[i]); - device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor)); + device_destroy(touchscreen_class, devno); ts_class_dev = NULL; class_unregister(touchscreen_class); pr_err("error creating touchscreen class\n"); diff --git a/drivers/input/touchscreen/focaltech_touch_v3/Android.mk b/drivers/input/touchscreen/focaltech_touch_v3/Android.mk index bc25407b4655..89ab92680a79 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/Android.mk +++ b/drivers/input/touchscreen/focaltech_touch_v3/Android.mk @@ -1,7 +1,7 @@ DLKM_DIR := motorola/kernel/modules LOCAL_PATH := $(call my-dir) -ifeq ($(call is-board-platform-in-list,taro kalama), true) +ifeq ($(call is-board-platform-in-list,taro kalama parrot), true) ifneq ($(FOCALTECH_TOUCH_IC_NAME),) KBUILD_OPTIONS += CONFIG_INPUT_FOCALTECH_V3_MMI_IC_NAME=$(FOCALTECH_TOUCH_IC_NAME) diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_common.h b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_common.h index dfbc9497a711..14155c223eea 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_common.h +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_common.h @@ -82,6 +82,8 @@ #define FTS_REG_CHIP_ID 0xA3 #define FTS_REG_CHIP_ID2 0x9F #define FTS_REG_POWER_MODE 0xA5 +#define FTS_REG_POWER_MODE_ACTIVE 0 +#define FTS_REG_POWER_MODE_STANDBY 0x02 #define FTS_REG_POWER_MODE_SLEEP 0x03 #define FTS_REG_FW_VER 0xA6 #define FTS_REG_VENDOR_ID 0xA8 diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c index cd1cefa93584..027dd3bb2899 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.c @@ -1972,6 +1972,11 @@ static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata) if (pdata->sample_ctrl) FTS_INFO("support focaltech sample mode"); + pdata->stowed_mode_ctrl = of_property_read_bool(np, + "focaltech,stowed-mode-ctrl"); + if (pdata->stowed_mode_ctrl) + FTS_INFO("Support focaltech touch stowed mode"); + FTS_FUNC_EXIT(); return 0; diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h index eec08c0315f2..8f8952aca0e7 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_core.h @@ -161,6 +161,7 @@ struct fts_ts_platform_data { bool interpolation_ctrl; bool report_rate_ctrl; bool sample_ctrl; + bool stowed_mode_ctrl; }; struct ts_event { @@ -201,6 +202,7 @@ struct fts_mode_info { int sample; int report_rate_mode; int edge_mode[2]; + int stowed; }; struct fts_ts_data { struct i2c_client *client; diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_config.c b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_config.c index 23e2a29673c2..7908b4fc96dd 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_config.c +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_config.c @@ -13,7 +13,7 @@ #include "focaltech_ts_config.h" struct focaltech_ic_report_rate_config report_rate_config_info = { -#if defined(PRODUCT_BANGKK) +#if defined(PRODUCT_BANGKK)|| defined(PRODUCT_AVATRN) .rate_config_count = 2, .refresh_rate_ctrl = 0, .interpolation_ctrl = 1, diff --git a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c index 4bd6406dbd72..8b5a7717ef1b 100644 --- a/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c +++ b/drivers/input/touchscreen/focaltech_touch_v3/focaltech_ts_mmi.c @@ -71,6 +71,10 @@ static ssize_t fts_sample_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size); static ssize_t fts_sample_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t fts_stowed_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size); +static ssize_t fts_stowed_show(struct device *dev, + struct device_attribute *attr, char *buf); static DEVICE_ATTR(edge, (S_IRUGO | S_IWUSR | S_IWGRP), @@ -79,6 +83,8 @@ static DEVICE_ATTR(interpolation, (S_IRUGO | S_IWUSR | S_IWGRP), fts_interpolation_show, fts_interpolation_store); static DEVICE_ATTR(sample, (S_IRUGO | S_IWUSR | S_IWGRP), fts_sample_show, fts_sample_store); +static DEVICE_ATTR(stowed, (S_IWUSR | S_IWGRP | S_IRUGO), + fts_stowed_show, fts_stowed_store); #define ADD_ATTR(name) { \ if (idx < MAX_ATTRS_ENTRIES) { \ @@ -397,6 +403,67 @@ static ssize_t fts_sample_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "0x%02x", ts_data->set_mode.sample); } +static ssize_t fts_stowed_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned long mode = 0; + struct fts_ts_data *ts_data; + + dev = MMI_DEV_TO_TS_DEV(dev); + GET_TS_DATA(dev); + + ret = kstrtoul(buf, 0, &mode); + if (ret < 0) { + FTS_INFO("Failed to convert value.\n"); + return -EINVAL; + } + + mutex_lock(&ts_data->mode_lock); + + ts_data->get_mode.stowed = mode; + if (ts_data->set_mode.stowed == mode) { + FTS_DEBUG("The value = %lu is same, so not to write", mode); + ret = size; + goto exit; + } + + if ((ts_data->power_disabled == false) && (ts_data->suspended == true)) { + if (mode) + ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_STANDBY); + else + ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_ACTIVE); + if (ret < 0) { + FTS_ERROR("failed to set report rate, mode = %lu", mode); + goto exit; + } + } else { + FTS_INFO("Skip stowed mode setting suspended:%d, power_disabled:%d.\n", ts_data->suspended, ts_data->power_disabled); + ret = size; + goto exit; + } + + ts_data->set_mode.stowed = mode; + FTS_INFO("Success to set stowed mode %lu\n", mode); + + ret = size; +exit: + mutex_unlock(&ts_data->mode_lock); + return ret; +} + +static ssize_t fts_stowed_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fts_ts_data *ts_data; + + dev = MMI_DEV_TO_TS_DEV(dev); + GET_TS_DATA(dev); + + FTS_INFO("Stowed state = %d.\n", ts_data->set_mode.stowed); + return scnprintf(buf, PAGE_SIZE, "0x%02x", ts_data->set_mode.stowed); +} + static int fts_mmi_methods_get_vendor(struct device *dev, void *cdata) { return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", "focaltech"); @@ -804,6 +871,10 @@ exit: } } + if (pdata->stowed_mode_ctrl) { + ts_data->set_mode.stowed = 0; + } + mutex_unlock(&ts_data->mode_lock); FTS_FUNC_EXIT(); @@ -833,8 +904,11 @@ static int fts_mmi_pre_suspend(struct device *dev) static int fts_mmi_post_suspend(struct device *dev) { struct fts_ts_data *ts_data; + struct fts_ts_platform_data *pdata; + int ret = 0; GET_TS_DATA(dev); + pdata = ts_data->pdata; FTS_FUNC_ENTER(); @@ -848,6 +922,19 @@ static int fts_mmi_post_suspend(struct device *dev) #endif ts_data->suspended = true; + + if (pdata->stowed_mode_ctrl && ts_data->get_mode.stowed && (ts_data->power_disabled == false)) { + mutex_lock(&ts_data->mode_lock); + ret = fts_write_reg(FTS_REG_POWER_MODE, FTS_REG_POWER_MODE_STANDBY); + if (ret < 0) { + FTS_ERROR("Failed to set stowed mode %d", ts_data->get_mode.stowed); + } else { + ts_data->set_mode.stowed = ts_data->get_mode.stowed; + FTS_INFO("Enable stowed mode %d success.", ts_data->set_mode.stowed); + } + mutex_unlock(&ts_data->mode_lock); + } + FTS_FUNC_EXIT(); return 0; @@ -1000,6 +1087,9 @@ static int fts_mmi_extend_attribute_group(struct device *dev, struct attribute_g if (pdata->sample_ctrl) ADD_ATTR(sample); + if (pdata->stowed_mode_ctrl) + ADD_ATTR(stowed); + if (idx) { ext_attributes[idx] = NULL; *group = &ext_attr_group; diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c index 885011598fdd..ae3a1b914f3a 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_brl_hw.c @@ -1479,10 +1479,8 @@ static int brl_event_handler(struct goodix_ts_core *cd, ts_event->event_type = EVENT_GESTURE; ts_event->gesture_report_info = pre_buf[2]; ts_event->gesture_type = pre_buf[4]; -#ifdef CONFIG_GTP_FOD memcpy(ts_event->gesture_data, &pre_buf[8], GOODIX_GESTURE_DATA_LEN); -#endif } else { ts_info("Unsupported event status"); return -EINVAL; diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_config.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_config.c index 9f703ade9dff..4836556bf60d 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_config.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_config.c @@ -16,7 +16,8 @@ struct goodix_ic_report_rate_config report_rate_config_info = { #if defined(PRODUCT_LI) || defined(PRODUCT_ONELI) || defined(PRODUCT_TUNDRA) \ ||defined(PRODUCT_EQS) || defined(PRODUCT_RTWO) || defined(PRODUCT_BRONCO) \ || defined(PRODUCT_ZEEKR) || defined(PRODUCT_LYNKCO) || defined(PRODUCT_BANGKK) \ - || defined(PRODUCT_CTWO) + || defined(PRODUCT_EQE) || defined(PRODUCT_CTWO) || defined(PRODUCT_BOSTON) \ + || defined(PRODUCT_AVATRN) .rate_config_count = 2, .refresh_rate_ctrl = 0, .interpolation_ctrl = 1, diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c index eb79956856f1..f0fc32163d88 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.c @@ -2484,9 +2484,9 @@ static int pen_notifier_callback(struct notifier_block *self, ts_info("Received event(%lu) for pen detection\n", event); if (event == PEN_DETECTION_INSERT) - cd->gtp_pen_detect_flag = 0x0; + cd->gtp_pen_detect_flag = GTP_FINGER_MODE; else if (event == PEN_DETECTION_PULL) - cd->gtp_pen_detect_flag = 0x1; + cd->gtp_pen_detect_flag = GTP_PEN_MODE; mutex_lock_interruptible(&cd->mode_lock); @@ -2664,7 +2664,7 @@ static int goodix_ts_probe(struct platform_device *pdev) #endif #ifdef GTP_PEN_NOTIFIER - core_data->gtp_pen_detect_flag = PEN_DETECTION_INSERT; + core_data->gtp_pen_detect_flag = GTP_FINGER_MODE; core_data->pen_notif.notifier_call = pen_notifier_callback; ret = pen_detection_register_client(&core_data->pen_notif); if (ret) diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h index d9d7357594bc..00d088cbc6f7 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h @@ -428,9 +428,7 @@ struct goodix_ts_event { u8 gesture_report_info; struct goodix_touch_data touch_data; struct goodix_pen_data pen_data; -#ifdef CONFIG_GTP_FOD u8 gesture_data[GOODIX_GESTURE_DATA_LEN]; -#endif }; enum goodix_ic_bus_type { @@ -603,6 +601,11 @@ struct goodix_ts_core { #endif }; +#ifdef GTP_PEN_NOTIFIER +#define GTP_FINGER_MODE 0 +#define GTP_PEN_MODE 1 +#endif + /* external module structures */ enum goodix_ext_priority { EXTMOD_PRIO_RESERVED = 0, diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c index 0dc8d74dba87..44eacb470657 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture.c @@ -290,6 +290,8 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd, mmi_event.evcode =4; } + mmi_event.evdata.x = le16_to_cpup((__le16 *)gs_event.gesture_data); + mmi_event.evdata.y = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2)); /* call class method */ ret = cd->imports->report_gesture(&mmi_event); if (!ret) diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture_fod.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture_fod.c index 00c97dd9c4f2..874d4a28c9f6 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture_fod.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_gesture_fod.c @@ -419,6 +419,8 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd, mmi_event.evcode =1; fod_down = 0; + mmi_event.evdata.x = le16_to_cpup((__le16 *)gs_event.gesture_data); + mmi_event.evdata.y = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2)); /* call class method */ ret = cd->imports->report_gesture(&mmi_event); if (!ret) @@ -429,6 +431,8 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd, mmi_event.evcode =4; fod_down = 0; + mmi_event.evdata.x = le16_to_cpup((__le16 *)gs_event.gesture_data); + mmi_event.evdata.y = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2)); /* call class method */ ret = cd->imports->report_gesture(&mmi_event); if (!ret) diff --git a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c index da4dc410d474..087a41ac7f9f 100644 --- a/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c +++ b/drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_mmi.c @@ -1277,8 +1277,8 @@ static int goodix_ts_mmi_post_resume(struct device *dev) { } #ifdef GTP_PEN_NOTIFIER - if (core_data->gtp_pen_detect_flag) { - ret = goodix_ts_send_cmd(core_data, 0x32, 5, 0x1, 0x00); + if (core_data->gtp_pen_detect_flag == GTP_PEN_MODE) { + ret = goodix_ts_send_cmd(core_data, 0x32, 5, GTP_PEN_MODE, 0x00); if (ret < 0) ts_err("failed to send passive pen mode cmd"); } diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/Android.mk b/drivers/input/touchscreen/goodix_gt96x_mmi/Android.mk index b8a5ff7cf855..977c212fcdc2 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/Android.mk +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/Android.mk @@ -9,6 +9,9 @@ else endif endif +ifeq ($(DRM_PANEL_EVENT_NOTIFICATIONS),true) + KBUILD_OPTIONS += CONFIG_DRM_PANEL_EVENT_NOTIFICATIONS=y +endif include $(CLEAR_VARS) LOCAL_MODULE := goodix_gt96x_mmi.ko diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/Kbuild b/drivers/input/touchscreen/goodix_gt96x_mmi/Kbuild index 8d599929b010..fab6fa25a372 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/Kbuild +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/Kbuild @@ -20,4 +20,13 @@ ifneq ($(filter m y,$(CONFIG_TOUCHSCREEN_GOODIX_BRL_SPI)),) EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_GOODIX_BRL_SPI endif +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),) + EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI + goodix_gt96x_mmi-objs += goodix_ts_mmi.o +endif + +ifneq ($(filter m y, $(CONFIG_DRM_PANEL_EVENT_NOTIFICATIONS)),) + EXTRA_CFLAGS += -DCONFIG_DRM_PANEL_EVENT_NOTIFICATIONS +endif + KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../touchscreen_mmi/$(GKI_OBJ_MODULE_DIR)/Module.symvers diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_fwupdate.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_fwupdate.c index f975ee979162..ee845316b985 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_fwupdate.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_fwupdate.c @@ -40,16 +40,20 @@ #define ISP_RAM_ADDR_BRA 0x18400 #define ISP_RAM_ADDR_BRB 0x57000 #define ISP_RAM_ADDR_BRD 0x23800 +#define ISP_RAM_ADDR_MAR 0x3B800 #define HW_REG_CPU_RUN_FROM 0x10000 #define FLASH_CMD_REG_BRA 0x10400 #define FLASH_CMD_REG_BRB 0x13400 #define FLASH_CMD_REG_BRD 0x12400 +#define FLASH_CMD_REG_MAR 0x10174 #define HW_REG_ISP_BUFFER_BRA 0x10410 #define HW_REG_ISP_BUFFER_BRB 0x13410 #define HW_REG_ISP_BUFFER_BRD 0x12410 +#define HW_REG_ISP_BUFFER_MAR 0x12400 #define CONFIG_DATA_ADDR_BRA 0x3E000 #define CONFIG_DATA_ADDR_BRB 0x40000 #define CONFIG_DATA_ADDR_BRD 0x3E000 +#define CONFIG_DATA_ADDR_MAR 0x3F000 #define HOLD_CPU_REG_W 0x0002 #define HOLD_CPU_REG_R 0x2000 @@ -131,6 +135,19 @@ struct update_info_t update_brd = { ENABLE_MISCTL_BRD, }; +/* Marseille update info */ +struct update_info_t update_mar = { + FW_HEADER_SIZE, + FW_SUBSYS_INFO_OFFSET, + ISP_RAM_ADDR_MAR, + FLASH_CMD_REG_MAR, + HW_REG_ISP_BUFFER_MAR, + CONFIG_DATA_ADDR_MAR, + MISCTL_REG_BRD, + WATCH_DOG_REG_BRD, + ENABLE_MISCTL_BRD, +}; + enum compare_status { COMPARE_EQUAL = 0, COMPARE_NOCODE, @@ -484,7 +501,8 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl) /* enable misctl clock */ if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D || - fwu_ctrl->core_data->bus->ic_type == IC_TYPE_NOTTINGHAM) + fwu_ctrl->core_data->bus->ic_type == IC_TYPE_NOTTINGHAM || + fwu_ctrl->core_data->bus->ic_type == IC_TYPE_MARSEILLE) hw_ops->write(cd, misctl_reg, (u8 *)&enable_misctl_val, 4); else hw_ops->write(cd, misctl_reg, (u8 *)&enable_misctl_val, 1); @@ -1202,6 +1220,8 @@ int goodix_fw_update_init(struct goodix_ts_core *core_data) core_data->update_ctrl.update_info = &update_bra; else if (core_data->bus->ic_type == IC_TYPE_BERLIN_B) core_data->update_ctrl.update_info = &update_brb; + else if (core_data->bus->ic_type == IC_TYPE_MARSEILLE) + core_data->update_ctrl.update_info = &update_mar; else core_data->update_ctrl.update_info = &update_brd; diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_hw.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_hw.c index a75f0947eb59..68c66484053c 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_hw.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_hw.c @@ -1585,7 +1585,8 @@ static int brl_get_capacitance_data(struct goodix_ts_core *cd, } if (cd->bus->ic_type == IC_TYPE_BERLIN_D || - cd->bus->ic_type == IC_TYPE_NOTTINGHAM) + cd->bus->ic_type == IC_TYPE_NOTTINGHAM || + cd->bus->ic_type == IC_TYPE_MARSEILLE) return brld_get_cap_data(cd, info); /* disable irq & close esd */ diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_i2c.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_i2c.c index 664ad4192881..94b6abe59544 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_i2c.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_i2c.c @@ -208,6 +208,7 @@ static const struct of_device_id i2c_matchs[] = { {.compatible = "goodix,brl-b",}, {.compatible = "goodix,brl-d",}, {.compatible = "goodix,nottingham",}, + {.compatible = "goodix,marseille",}, {}, }; MODULE_DEVICE_TABLE(of, i2c_matchs); diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_spi.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_spi.c index aaf2c8782936..8d46aff6958c 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_spi.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_brl_spi.c @@ -222,6 +222,8 @@ static int goodix_spi_probe(struct spi_device *spi) dev_res->pdev.id = dev_res->id; dev_res->pdev.num_resources = 0; + spi_set_drvdata(spi, &dev_res->pdev); + /* register platform device, then the goodix_ts_core * module will probe the touch deivce. */ @@ -245,6 +247,7 @@ static const struct of_device_id spi_matchs[] = { {.compatible = "goodix,brl-b",}, {.compatible = "goodix,brl-d",}, {.compatible = "goodix,nottingham",}, + {.compatible = "goodix,marseille",}, {}, }; #endif diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.c index d04bf1352619..1cb01b727970 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.c @@ -23,12 +23,15 @@ #include #define INPUT_TYPE_B_PROTOCOL #endif +#include "goodix_ts_mmi.h" /* goodix fb test */ // #include "../../../video/fbdev/core/fb_firefly.h" #define GOODIX_DEFAULT_CFG_NAME "goodix_cfg_group.cfg" struct goodix_device_manager goodix_devices; +#define PINCTRL_STATE_ACTIVE "cli_pmx_ts_active" +#define PINCTRL_STATE_SUSPEND "cli_pmx_ts_suspend" static void goodix_device_manager_init(void) { @@ -886,6 +889,16 @@ static int goodix_parse_dt(struct device_node *node, board_data->pen_enable = of_property_read_bool(node, "goodix,pen-enable"); + /* get ic compatible */ + r = of_property_read_string(node, "compatible", &name_tmp); + if (r) { + ts_err("get compatible failed"); + return r; + } else { + ts_info("ic_name form dt: %s", name_tmp); + strncpy(board_data->ic_name, name_tmp, sizeof(board_data->ic_name)); + } + ts_info("[DT]x:%d, y:%d, w:%d, p:%d sleep_enable:%d pen_enable:%d", board_data->panel_max_x, board_data->panel_max_y, board_data->panel_max_w, board_data->panel_max_p, @@ -1156,6 +1169,54 @@ int goodix_ts_power_off(struct goodix_ts_core *cd) return ret; } +/** + * goodix_ts_pinctrl_init - Get pinctrl handler and pinctrl_state + * @core_data: pointer to touch core data + * return: 0 ok, <0 failed + */ +static int goodix_ts_pinctrl_init(struct goodix_ts_core *core_data) +{ + int r = 0; + + /* get pinctrl handler from of node */ + core_data->pinctrl = devm_pinctrl_get(core_data->bus->dev); + if (IS_ERR_OR_NULL(core_data->pinctrl)) { + ts_info("Failed to get pinctrl handler[need confirm]"); + core_data->pinctrl = NULL; + return -EINVAL; + } + ts_debug("success get pinctrl"); + /* active state */ + core_data->pin_sta_active = pinctrl_lookup_state(core_data->pinctrl, + PINCTRL_STATE_ACTIVE); + if (IS_ERR_OR_NULL(core_data->pin_sta_active)) { + r = PTR_ERR(core_data->pin_sta_active); + ts_err("Failed to get pinctrl state:%s, r:%d", + PINCTRL_STATE_ACTIVE, r); + core_data->pin_sta_active = NULL; + goto exit_pinctrl_put; + } + ts_info("success get avtive pinctrl state"); + + /* suspend state */ + core_data->pin_sta_suspend = pinctrl_lookup_state(core_data->pinctrl, + PINCTRL_STATE_SUSPEND); + if (IS_ERR_OR_NULL(core_data->pin_sta_suspend)) { + r = PTR_ERR(core_data->pin_sta_suspend); + ts_err("Failed to get pinctrl state:%s, r:%d", + PINCTRL_STATE_SUSPEND, r); + core_data->pin_sta_suspend = NULL; + goto exit_pinctrl_put; + } + ts_info("success get suspend pinctrl state"); + + return 0; +exit_pinctrl_put: + devm_pinctrl_put(core_data->pinctrl); + core_data->pinctrl = NULL; + return r; +} + /** * goodix_ts_gpio_setup - Request gpio resources from GPIO subsysten * @core_data: pointer to touch core data @@ -1233,7 +1294,7 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data) core_data->input_dev = input_dev; input_set_drvdata(input_dev, core_data); - sprintf(core_data->input_name, "%s.%d", GOODIX_CORE_DRIVER_NAME, dev_id); + sprintf(core_data->input_name, "%s_%d", GOODIX_CORE_DRIVER_NAME, dev_id); input_dev->name = core_data->input_name; input_dev->id.bustype = core_data->bus->bus_type; @@ -1443,7 +1504,7 @@ int goodix_ts_esd_init(struct goodix_ts_core *cd) return 0; } -static void goodix_ts_release_connects(struct goodix_ts_core *core_data) +void goodix_ts_release_connects(struct goodix_ts_core *core_data) { struct input_dev *input_dev = core_data->input_dev; struct input_dev *pen_dev = core_data->pen_dev; @@ -1473,6 +1534,7 @@ static void goodix_ts_release_connects(struct goodix_ts_core *core_data) core_data->hw_ops->after_event_handler(core_data); } +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI /** * goodix_ts_suspend - Touchscreen suspend function * Called by PM/FB/EARLYSUSPEN module to put the device to sleep @@ -1552,6 +1614,7 @@ static void goodix_ts_resume_work(struct work_struct *work) container_of(work, struct goodix_ts_core, resume_work); goodix_ts_resume(cd); } +#endif #if IS_ENABLED(CONFIG_FB) /** @@ -1580,7 +1643,7 @@ int goodix_ts_fb_notifier_callback(struct notifier_block *self, return 0; } -#elif IS_ENABLED(CONFIG_PM) +#elif IS_ENABLED(CONFIG_PM) && !defined(CONFIG_INPUT_TOUCHSCREEN_MMI) /** * goodix_ts_pm_suspend - PM suspend function * Called by kernel during system suspend phrase @@ -1607,6 +1670,29 @@ static const struct dev_pm_ops dev_pm_ops = { .suspend = goodix_ts_pm_suspend, .resume = goodix_ts_pm_resume, }; +#else +/** + * goodix_ts_pm_suspend - PM suspend function + * Called by kernel during system suspend phrase + */ +static int goodix_ts_pm_suspend(struct device *dev) +{ + ts_info("system enters into pm_suspend"); + return 0; +} +/** + * goodix_ts_pm_resume - PM resume function + * Called by kernel during system wakeup + */ +static int goodix_ts_pm_resume(struct device *dev) +{ + ts_info("system resumes from pm_suspend"); + return 0; +} +static const struct dev_pm_ops dev_pm_ops = { + .suspend = goodix_ts_pm_suspend, + .resume = goodix_ts_pm_resume, +}; #endif static void goodix_self_check(struct work_struct *work) @@ -1679,7 +1765,9 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd) /* inspect init */ inspect_module_init(cd); +#ifndef CONFIG_INPUT_TOUCHSCREEN_MMI INIT_WORK(&cd->resume_work, goodix_ts_resume_work); +#endif /* Do self check on first boot */ INIT_WORK(&cd->self_check_work, goodix_self_check); @@ -1867,6 +1955,24 @@ static int goodix_ts_probe(struct platform_device *pdev) goto err_out; } + /* Pinctrl handle is optional. */ + ret = goodix_ts_pinctrl_init(core_data); + if (!ret && core_data->pinctrl) { + ret = pinctrl_select_state(core_data->pinctrl, + core_data->pin_sta_active); + if (ret < 0) + ts_err("Failed to select active pinstate, r:%d", ret); + } + +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI + ts_info("%s:goodix_ts_mmi_dev_register",__func__); + ret = goodix_ts_mmi_dev_register(pdev); + if (ret) { + ts_info("Failed register touchscreen mmi."); + goto err_out; + } +#endif + /* debug node init */ ret = goodix_tools_init(core_data); if (ret) { @@ -1900,6 +2006,11 @@ static int goodix_ts_remove(struct platform_device *pdev) struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops; struct goodix_ts_esd *ts_esd = &core_data->ts_esd; +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI + ts_info("%s:goodix_ts_mmi_dev_unregister",__func__); + goodix_ts_mmi_dev_unregister(pdev); +#endif + goodix_tools_exit(core_data); goodix_fw_update_uninit(core_data); diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.h b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.h index faafcca88bfc..cf554d226193 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.h +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_core.h @@ -47,9 +47,9 @@ #include #endif -#define GOODIX_CORE_DRIVER_NAME "goodix_ts" +#define GOODIX_CORE_DRIVER_NAME "gdx_cli" #define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen" -#define GOODIX_DRIVER_VERSION "v1.3.13" +#define GOODIX_DRIVER_VERSION "v1.3.15" #define GOODIX_MAX_TOUCH 10 #define GOODIX_MAX_KEY 10 #define GOODIX_PEN_MAX_PRESSURE 4096 @@ -117,7 +117,8 @@ enum IC_TYPE_ID { IC_TYPE_BERLIN_A, IC_TYPE_BERLIN_B, IC_TYPE_BERLIN_D, - IC_TYPE_NOTTINGHAM + IC_TYPE_NOTTINGHAM, + IC_TYPE_MARSEILLE }; /* SUB-ID @@ -439,6 +440,7 @@ struct goodix_module { * @fw_name: name of the firmware image */ struct goodix_ts_board_data { + char ic_name[GOODIX_MAX_STR_LABLE_LEN]; char avdd_name[GOODIX_MAX_STR_LABLE_LEN]; char iovdd_name[GOODIX_MAX_STR_LABLE_LEN]; int reset_gpio; @@ -735,6 +737,9 @@ struct goodix_ts_core { struct goodix_ic_config ic_configs[GOODIX_MAX_CONFIG_GROUP]; struct regulator *avdd; struct regulator *iovdd; + struct pinctrl *pinctrl; + struct pinctrl_state *pin_sta_active; + struct pinctrl_state *pin_sta_suspend; u32 gesture_type; char input_name[32]; @@ -777,12 +782,23 @@ extern int goodix_device_register(struct goodix_device_resource *device); /* log macro */ extern bool debug_log_flag; #define ts_info(fmt, arg...) \ - pr_info("[GTP-INF][%s] "fmt"\n", __func__, ##arg) + pr_info("[GDX-CLI-INF][%s] "fmt"\n", __func__, ##arg) #define ts_err(fmt, arg...) \ - pr_err("[GTP-ERR][%s] "fmt"\n", __func__, ##arg) + pr_err("[GDX-CLI-ERR][%s] "fmt"\n", __func__, ##arg) #define ts_debug(fmt, arg...) \ {if (debug_log_flag) \ - pr_info("[GTP-DBG][%s] "fmt"\n", __func__, ##arg);} + pr_info("[GDX-CLI-DBG][%s] "fmt"\n", __func__, ##arg);} + +/* + * get board data pointer + */ +static inline struct goodix_ts_board_data *board_data( + struct goodix_ts_core *core) +{ + if (!core) + return NULL; + return &(core->board_data); +} struct goodix_ts_hw_ops *goodix_get_hw_ops(void); int goodix_get_config_proc(struct goodix_ts_core *cd); @@ -814,4 +830,8 @@ void goodix_ts_esd_off(struct goodix_ts_core *cd); int goodix_ts_report_gesture(struct goodix_ts_core *cd, struct goodix_ts_event *event); +int goodix_ts_power_on(struct goodix_ts_core *cd); +int goodix_ts_power_off(struct goodix_ts_core *cd); +void goodix_ts_release_connects(struct goodix_ts_core *core_data); + #endif diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_inspect.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_inspect.c index 26f0c9f41357..a0e4371d2ad1 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_inspect.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_inspect.c @@ -31,7 +31,7 @@ #define DISCARD_FRAMES 3 -#define GOODIX_TEST_FILE_NAME "goodix_test_limits" +#define GOODIX_TEST_FILE_NAME "gdx_test_limits" #define MAX_PROC_OUTPUT_SIZE 2 * 1024 * 1024 #define MAX_DATA_BUFFER 30000 #define MAX_SHORT_NUM 15 @@ -112,6 +112,17 @@ #define DRV_SEN_SELFCODE_REG_NOT 0x14152 #define DIFF_CODE_DATA_REG_NOT 0x14734 +/* marseille */ +#define MAX_DRV_NUM_MAR 20 +#define MAX_SEN_NUM_MAR 34 +#define SHORT_TEST_TIME_REG_MAR 0x138AC +#define SHORT_TEST_STATUS_REG_MAR 0x12400 +#define SHORT_TEST_RESULT_REG_MAR 0x12408 +#define DRV_DRV_SELFCODE_REG_MAR 0x12448 +#define SEN_SEN_SELFCODE_REG_MAR 0x127E0 +#define DRV_SEN_SELFCODE_REG_MAR 0x137D0 +#define DIFF_CODE_DATA_REG_MAR 0x1383E + #define ABS(val) ((val < 0)? -(val) : val) #define MAX(a, b) ((a > b)? a : b) @@ -144,6 +155,7 @@ enum GTP_MUTUAL_DATA_TYPE { static int output_offset; static char *output_buf; +static bool auto_test_result; /* berlin A drv-sen map */ static u8 brl_a_drv_map[] = { @@ -212,6 +224,19 @@ static u8 not_sen_map[] = { 28, 29, 30, 31, 32, 33, 34 }; +/* marseille drv-sen map */ +static u8 mar_drv_map[] = { + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +}; + +static u8 mar_sen_map[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33 +}; + typedef struct __attribute__((packed)) { u8 result; u8 drv_drv_num; @@ -322,6 +347,23 @@ struct params_info_t params_not = { 0, }; +struct params_info_t params_mar = { + MAX_DRV_NUM_MAR, + MAX_SEN_NUM_MAR, + mar_drv_map, + mar_sen_map, + SHORT_TEST_TIME_REG_MAR, + SHORT_TEST_STATUS_REG_MAR, + SHORT_TEST_RESULT_REG_MAR, + DRV_DRV_SELFCODE_REG_MAR, + SEN_SEN_SELFCODE_REG_MAR, + DRV_SEN_SELFCODE_REG_MAR, + DIFF_CODE_DATA_REG_MAR, + 0, + 0, + 0, +}; + struct ts_test_params { bool test_items[MAX_TEST_ITEMS]; @@ -402,8 +444,10 @@ static int cal_cha_to_cha_res(struct goodix_ts_test *ts_test, int v1, int v2) return (v1 - v2) * 74 / v2 + 20; else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D) return (v1 / v2 - 1) * 70 + 59; + else if (ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) + return (v1 / v2 - 1) * 14; else - return (v1 / v2 - 1) * 55 + 45; + return (v1 / v2 - 1) * 55 + 45; // nottingham } static int cal_cha_to_avdd_res(struct goodix_ts_test *ts_test, int v1, int v2) @@ -414,8 +458,10 @@ static int cal_cha_to_avdd_res(struct goodix_ts_test *ts_test, int v1, int v2) return 64 * (2 * v2 - 25) * 99 / v1 - 60; else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D) return 64 * (2 * v2 - 25) * 93 / v1 - 20; + else if (ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) + return 64 * (2 * v2 - 25) * 72 / v1 - 13; else - return 64 * (2 * v2 - 25) * 76 / v1 - 15; + return 64 * (2 * v2 - 25) * 76 / v1 - 15; // nottingham } static int cal_cha_to_gnd_res(struct goodix_ts_test *ts_test, int v) @@ -426,8 +472,10 @@ static int cal_cha_to_gnd_res(struct goodix_ts_test *ts_test, int v) return 150500 / v - 60; else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D) return 145000 / v - 15; + else if (ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) + return 28800 / v - 13; else - return 120000 / v - 16; + return 120000 / v - 16; // nottingham } static int ts_test_reset(struct goodix_ts_test *ts_test, @@ -659,6 +707,8 @@ static void goodix_init_params(struct goodix_ts_test *ts_test) test_params->params_info = ¶ms_brd; else if (ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM) test_params->params_info = ¶ms_not; + else if (ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) + test_params->params_info = ¶ms_mar; } static int goodix_init_testlimits(struct goodix_ts_test *ts_test) @@ -1414,6 +1464,27 @@ static void goodix_shortcircut_test(struct goodix_ts_test *ts_test) return; } + if (ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) { + ts_test_read(ts_test, 0x10400, &status, 1); + if (status != 0xFD) { + ts_err("marseille short status[0x%02x] != 0xFD", status); + return; + } + status = 0; + ts_test_write(ts_test, 0x10400, &status, 1); + retry = 20; + while (retry--) { + msleep(20); + ts_test_read(ts_test, 0x10400, &status, 1); + if (status == 0xAA) + break; + } + if (retry < 0) { + ts_err("marseille short status[0x%02x] != 0xAA", status); + return; + } + } + msleep(500); //BerlinB quick check need to delay at least 500ms /* get short test time */ @@ -1495,7 +1566,8 @@ static int goodix_cap_test_prepare(struct goodix_ts_test *ts_test) /* switch rawdata mode */ if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D || - ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM) { + ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM || + ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) { temp_cmd.cmd = 0x90; temp_cmd.data[0] = 0x81; temp_cmd.len = 5; @@ -1532,7 +1604,8 @@ static int goodix_poll_rawdata(struct goodix_ts_test *ts_test, u8 data_type, u8 int retry; if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D || - ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM) + ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM || + ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) flag_addr = ts_test->ts->ic_info.misc.frame_data_addr; if (data_type == GTP_MUTUAL_RAW) { @@ -1563,7 +1636,8 @@ static int goodix_poll_rawdata(struct goodix_ts_test *ts_test, u8 data_type, u8 frame_buf = kzalloc(FRAME_DATA_MAX_SIZE, GFP_KERNEL); if (cd->bus->ic_type == IC_TYPE_BERLIN_D || - cd->bus->ic_type == IC_TYPE_NOTTINGHAM) { + cd->bus->ic_type == IC_TYPE_NOTTINGHAM || + cd->bus->ic_type == IC_TYPE_MARSEILLE) { ret = ts_test_read(ts_test, flag_addr, frame_buf, FRAME_DATA_MAX_SIZE); if (ret < 0) goto free_exit; @@ -1611,7 +1685,8 @@ static int goodix_cache_rawdata(struct goodix_ts_test *ts_test) u32 flag_addr = ts_test->ts->ic_info.misc.touch_data_addr; if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D || - ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM) + ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM || + ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE) flag_addr = ts_test->ts->ic_info.misc.frame_data_addr; for (i = 0; i < DISCARD_FRAMES; i++) { @@ -1717,7 +1792,8 @@ static int goodix_cache_noisedata(struct goodix_ts_test *ts_test) u32 flag_addr = ts_test->ts->ic_info.misc.touch_data_addr; if (cd->bus->ic_type == IC_TYPE_BERLIN_D || - cd->bus->ic_type == IC_TYPE_NOTTINGHAM) { + cd->bus->ic_type == IC_TYPE_NOTTINGHAM || + cd->bus->ic_type == IC_TYPE_MARSEILLE) { flag_addr = ts_test->ts->ic_info.misc.frame_data_addr; temp_cmd.cmd = 0x90; temp_cmd.data[0] = 0x82; @@ -2048,7 +2124,8 @@ static void goodix_check_key_info_test(struct goodix_ts_test *ts_test) //read chip load info for berlin if (cd->bus->ic_type == IC_TYPE_BERLIN_B || cd->bus->ic_type == IC_TYPE_BERLIN_D || - cd->bus->ic_type == IC_TYPE_NOTTINGHAM) { + cd->bus->ic_type == IC_TYPE_NOTTINGHAM || + cd->bus->ic_type == IC_TYPE_MARSEILLE) { if (cd->bus->ic_type == IC_TYPE_BERLIN_B) chip_info_addr = 0x3F300; else @@ -2208,6 +2285,8 @@ static int goodix_save_header(struct goodix_ts_test *ts_test) proc_append_string("%s\n", result ? "NG" : "OK"); proc_append_string("GT%s\n%d\n", ts->fw_version.patch_pid, ts->fw_version.sensor_id); + auto_test_result = !result; + ts_info("GT%s TP test total result: %d", ts->fw_version.patch_pid, auto_test_result); /* save test config */ goodix_save_test_config(ts_test); @@ -2220,64 +2299,82 @@ static int goodix_save_header(struct goodix_ts_test *ts_test) if (ts_test->test_params.test_items[GTP_VERSION_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_VERSION_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_CHIP_KEY_INFO_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_CHIP_KEY_INFO_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_CUSTOM_INFO_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_CUSTOM_INFO_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_CAP_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_CAP_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_DELTA_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_DELTA_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_NOISE_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_NOISE_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_SELFNOISE_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_SELFNOISE_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_SELFCAP_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_SELFCAP_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } if (ts_test->test_params.test_items[GTP_SHORT_TEST]) { if (GTP_TEST_OK == ts_test->test_result[GTP_SHORT_TEST]) proc_append_string("\n"); - else - proc_append_string("\n"); + else { + proc_append_string("\n"); + ts_err("\n"); + } } proc_append_string("\n"); @@ -2748,9 +2845,46 @@ static const struct file_operations auto_test_ops = { }; #endif +static int auto_test_result_proc_show(struct seq_file *file, void *v) +{ + struct goodix_ts_core * core_data = (struct goodix_ts_core *)file->private; + if (!core_data) { + ts_err("no goodix_ts_core set"); + return -EIO; + } + + seq_printf(file, "result=%d\n", auto_test_result); + + return 0; +} + +static int auto_test_result_proc_open(struct inode *inode, struct file *file) +{ + return single_open_size(file, auto_test_result_proc_show, PDE_DATA(inode), PAGE_SIZE * 10); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) +static const struct file_operations auto_test_result_ops = { + .owner = THIS_MODULE, + .open = auto_test_result_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#else +static const struct proc_ops auto_test_result_ops = { + .proc_open = auto_test_result_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#endif + + int inspect_module_init(struct goodix_ts_core *core_data) { struct proc_dir_entry *proc_entry; + struct proc_dir_entry *result_proc_entry; proc_entry = proc_create_data("auto_test", 0660, core_data->proc_dir_entry, &auto_test_ops, core_data); @@ -2759,6 +2893,13 @@ int inspect_module_init(struct goodix_ts_core *core_data) return -ENODEV; } + result_proc_entry = proc_create_data("auto_test_result", + 0660, core_data->proc_dir_entry, &auto_test_result_ops, core_data); + if (!result_proc_entry) { + ts_err("failed to create auto_test_result proc entry"); + return -ENODEV; + } + ts_info("inspect module init success"); return 0; } diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_mmi.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_mmi.c new file mode 100644 index 000000000000..5c4ac5171687 --- /dev/null +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_mmi.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2023 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include "goodix_ts_mmi.h" +#include +#include + +#define GET_GOODIX_DATA(dev) { \ + pdev = dev_get_drvdata(dev); \ + if (!pdev) { \ + ts_err("Failed to get platform device"); \ + return -ENODEV; \ + } \ + core_data = platform_get_drvdata(pdev); \ + if (!core_data) { \ + ts_err("Failed to get driver data"); \ + return -ENODEV; \ + } \ +} + +static int goodix_ts_mmi_methods_get_vendor(struct device *dev, void *cdata) { + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", "goodix"); +} + +static int goodix_ts_mmi_methods_get_productinfo(struct device *dev, void *cdata) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + struct goodix_ts_board_data *ts_bdata; + char* ic_info; + + GET_GOODIX_DATA(dev); + + ts_bdata = board_data(core_data); + if (!ts_bdata) { + ts_err("Failed to get ts board data"); + return -ENODEV; + } + + ic_info = strstr(ts_bdata->ic_name, ","); + ic_info++; + + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "%s", ic_info); +} + +#define TOUCH_CFG_VERSION_ADDR 0x10076 +static int goodix_ts_mmi_methods_get_build_id(struct device *dev, void *cdata) { + int ret; + struct platform_device *pdev; + struct goodix_ts_core *core_data; + u32 cfg_id; + + GET_GOODIX_DATA(dev); + + ret = core_data->hw_ops->read(core_data, TOUCH_CFG_VERSION_ADDR, + (u8*)&cfg_id, sizeof(cfg_id)); + if (ret) { + ts_info("failed get fw version data, %d", ret); + return -EINVAL; + } + + return snprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%04x", le32_to_cpu(cfg_id)); +} + +#define TOUCH_FW_VERSION_ADDR 0x1007E +/*return firmware version*/ +static int goodix_ts_mmi_methods_get_config_id(struct device *dev, void *cdata) { + int ret; + struct platform_device *pdev; + struct goodix_ts_core *core_data; + u8 fw_id[4] = {0}; + + GET_GOODIX_DATA(dev); + + ret = core_data->hw_ops->read(core_data, TOUCH_FW_VERSION_ADDR, + fw_id, sizeof(fw_id)); + if (ret) { + ts_info("failed get fw version data, %d", ret); + return -EINVAL; + } + + return snprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%02x%02x%02x%02x", + fw_id[0], fw_id[1], fw_id[2], fw_id[3]); +} + +static int goodix_ts_mmi_methods_get_bus_type(struct device *dev, void *idata) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + TO_INT(idata) = core_data->bus->bus_type == GOODIX_BUS_TYPE_I2C ? + TOUCHSCREEN_MMI_BUS_TYPE_I2C : TOUCHSCREEN_MMI_BUS_TYPE_SPI; + return 0; +} + +static int goodix_ts_mmi_methods_get_irq_status(struct device *dev, void *idata) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + struct goodix_ts_board_data *ts_bdata; + + GET_GOODIX_DATA(dev); + + ts_bdata = board_data(core_data); + if (!ts_bdata) { + ts_err("Failed to get ts board data"); + return -ENODEV; + } + TO_INT(idata) = gpio_get_value(ts_bdata->irq_gpio); + return 0; +} + +static int goodix_ts_mmi_methods_get_drv_irq(struct device *dev, void *idata) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + TO_INT(idata) = atomic_read(&core_data->irq_enabled); + return 0; +} + +static int goodix_ts_mmi_methods_get_poweron(struct device *dev, void *idata) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + TO_INT(idata) = core_data->power_on; + return 0; +} + +static int goodix_ts_mmi_methods_get_flashprog(struct device *dev, void *idata) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + TO_INT(idata) = core_data->update_ctrl.status; + return 0; +} + +/* reset chip + * type:can control software reset and hardware reset, + * but GOODIX has no software reset, + * so the type parameter is not used here. + */ +static int goodix_ts_mmi_methods_reset(struct device *dev, int type) { + int ret = -ENODEV; + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + if (core_data->hw_ops->reset) + ret = core_data->hw_ops->reset(core_data, GOODIX_NORMAL_RESET_DELAY_MS); + return ret; +} + +static int goodix_ts_mmi_methods_drv_irq(struct device *dev, int state) { + int ret = -ENODEV; + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + if (core_data->hw_ops->irq_enable) + ret = core_data->hw_ops->irq_enable(core_data, !(!state)); + + return ret; +} + +static int goodix_ts_mmi_methods_power(struct device *dev, int on) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + if (on == TS_MMI_POWER_ON) + return goodix_ts_power_on(core_data); + else if(on == TS_MMI_POWER_OFF) + return goodix_ts_power_off(core_data); + else { + ts_err("Invalid power parameter %d.\n", on); + return -EINVAL; + } +} + +static int goodix_ts_mmi_pre_suspend(struct device *dev) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + ts_info("Suspend start"); + atomic_set(&core_data->suspended, 1); + + /* + * notify suspend event, inform the esd protector + * and charger detector to turn off the work + */ + goodix_ts_esd_off(core_data); + + return 0; +} + +static int goodix_ts_mmi_panel_state(struct device *dev, + enum ts_mmi_pm_mode from, enum ts_mmi_pm_mode to) +{ + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + switch (to) { + case TS_MMI_PM_GESTURE: + break; + case TS_MMI_PM_DEEPSLEEP: + break; + case TS_MMI_PM_ACTIVE: + break; + default: + ts_err("Invalid power state parameter %d.\n", to); + return -EINVAL; + } + + return 0; +} + +static int goodix_ts_mmi_post_suspend(struct device *dev) { + struct goodix_ts_core *core_data; + struct platform_device *pdev; + + GET_GOODIX_DATA(dev); + + goodix_ts_release_connects(core_data); + + ts_info("Suspend end"); + return 0; +} + +static int goodix_ts_mmi_pre_resume(struct device *dev) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + ts_info("Resume start"); + GET_GOODIX_DATA(dev); + + atomic_set(&core_data->suspended, 0); + return 0; +} + +static int goodix_ts_mmi_post_resume(struct device *dev) { + struct platform_device *pdev; + struct goodix_ts_core *core_data; + + GET_GOODIX_DATA(dev); + + /* open esd */ + goodix_ts_esd_on(core_data); + ts_info("Resume end"); + return 0; +} +static struct ts_mmi_methods goodix_ts_mmi_methods = { + .get_vendor = goodix_ts_mmi_methods_get_vendor, + .get_productinfo = goodix_ts_mmi_methods_get_productinfo, + .get_build_id = goodix_ts_mmi_methods_get_build_id, + .get_config_id = goodix_ts_mmi_methods_get_config_id, + .get_bus_type = goodix_ts_mmi_methods_get_bus_type, + .get_irq_status = goodix_ts_mmi_methods_get_irq_status, + .get_drv_irq = goodix_ts_mmi_methods_get_drv_irq, + .get_poweron = goodix_ts_mmi_methods_get_poweron, + .get_flashprog = goodix_ts_mmi_methods_get_flashprog, + /* SET methods */ + .reset = goodix_ts_mmi_methods_reset, + .drv_irq = goodix_ts_mmi_methods_drv_irq, + .power = goodix_ts_mmi_methods_power, + /* PM callback */ + .pre_suspend = goodix_ts_mmi_pre_suspend, + .panel_state = goodix_ts_mmi_panel_state, + .post_suspend = goodix_ts_mmi_post_suspend, + .pre_resume = goodix_ts_mmi_pre_resume, + .post_resume = goodix_ts_mmi_post_resume, +}; + +int goodix_ts_mmi_dev_register(struct platform_device *pdev) { + int ret; + struct goodix_ts_core *core_data; + + core_data = platform_get_drvdata(pdev); + if (!core_data) { + ts_err("Failed to get driver data"); + return -ENODEV; + } + ret = ts_mmi_dev_register(core_data->bus->dev, &goodix_ts_mmi_methods); + if (ret) { + dev_err(&pdev->dev, "Failed to register ts mmi\n"); + return ret; + } + + return 0; +} + +void goodix_ts_mmi_dev_unregister(struct platform_device *pdev) { + struct goodix_ts_core *core_data; + + core_data = platform_get_drvdata(pdev); + if (!core_data) + ts_err("Failed to get driver data"); + ts_mmi_dev_unregister(core_data->bus->dev); +} diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_mmi.h b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_mmi.h new file mode 100644 index 000000000000..1abf4c84a06c --- /dev/null +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_mmi.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ +#ifndef __GOODIX_TS_MMI_H__ +#define __GOODIX_TS_MMI_H__ + +#include +#include +#include +#include "goodix_ts_core.h" + +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI +int goodix_ts_mmi_dev_register(struct platform_device *ts_device); +void goodix_ts_mmi_dev_unregister(struct platform_device *ts_device); +#else +static int inline goodix_ts_mmi_dev_register(struct platform_device *ts_device) { + return -ENOSYS; +} +static int inline goodix_ts_mmi_dev_unregister(struct platform_device *ts_device) { + return -ENOSYS; +} +#endif + +#endif diff --git a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_utils.c b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_utils.c index de90dfb94bc6..dfdce7bf8197 100644 --- a/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_utils.c +++ b/drivers/input/touchscreen/goodix_gt96x_mmi/goodix_ts_utils.c @@ -273,6 +273,11 @@ int goodix_get_ic_type(struct device_node *node, bus_inf->ic_type = IC_TYPE_NOTTINGHAM; return 0; } + if (strstr(ic_name, "marseille")) { + ts_info("ic type is marseille"); + bus_inf->ic_type = IC_TYPE_MARSEILLE; + return 0; + } ts_err("unsupported ic type %s", ic_name); return -EINVAL; diff --git a/drivers/input/touchscreen/nova_0flash_mmi/nt36xxx.c b/drivers/input/touchscreen/nova_0flash_mmi/nt36xxx.c index 3eb7752eaa47..2dc13d7e9ef1 100644 --- a/drivers/input/touchscreen/nova_0flash_mmi/nt36xxx.c +++ b/drivers/input/touchscreen/nova_0flash_mmi/nt36xxx.c @@ -414,7 +414,12 @@ int32_t CTP_SPI_READ(struct spi_device *client, uint8_t *buf, uint16_t len) while (retries < 5) { ret = spi_read_write(client, buf, len, NVTREAD); - if (ret == 0) break; + if (ret == 0) + break; + else if (ret == -ETIMEDOUT) { + NVT_ERR("read error, ret = %d\n", ret); + break; + } retries++; } @@ -448,7 +453,13 @@ int32_t CTP_SPI_WRITE(struct spi_device *client, uint8_t *buf, uint16_t len) while (retries < 5) { ret = spi_read_write(client, buf, len, NVTWRITE); - if (ret == 0) break; + if (ret == 0) + break; + else if (ret == -ETIMEDOUT) { + NVT_ERR("write error, ret = %d\n", ret); + break; + } + retries++; } diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c index ac41dc663a00..139c4c4e956c 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c @@ -238,8 +238,13 @@ static int ts_mmi_gesture_handler(struct gesture_event_data *gev) { int key_code; struct ts_mmi_dev *touch_cdev = sensor_pdata->touch_cdev; + struct ts_mmi_dev_pdata *ppdata = &touch_cdev->pdata; unsigned char mode_type = touch_cdev->gesture_mode_type; + if (ppdata->resolution_boost) { + gev->evdata.x /= ppdata->resolution_boost; + gev->evdata.y /= ppdata->resolution_boost; + } switch (gev->evcode) { case 1: if (!(mode_type & TS_MMI_GESTURE_SINGLE)) @@ -247,7 +252,9 @@ static int ts_mmi_gesture_handler(struct gesture_event_data *gev) ts_mmi_single_tap_handler(touch_cdev); key_code = BTN_TRIGGER_HAPPY3; - pr_info("%s: single tap\n", __func__); + input_report_abs(sensor_pdata->input_sensor_dev, ABS_X, gev->evdata.x); + input_report_abs(sensor_pdata->input_sensor_dev, ABS_Y, gev->evdata.y); + pr_info("%s: single tap; x=%d, y=%d\n", __func__, gev->evdata.x, gev->evdata.y); break; case 2: if (!(mode_type & TS_MMI_GESTURE_ZERO)) @@ -277,7 +284,9 @@ static int ts_mmi_gesture_handler(struct gesture_event_data *gev) return 1; key_code = BTN_TRIGGER_HAPPY6; - pr_info("%s: double tap\n", __func__); + input_report_abs(sensor_pdata->input_sensor_dev, ABS_X, gev->evdata.x); + input_report_abs(sensor_pdata->input_sensor_dev, ABS_Y, gev->evdata.y); + pr_info("%s: double tap; x=%d, y=%d\n", __func__, gev->evdata.x, gev->evdata.y); touch_cdev->double_tap_pressed = true; sysfs_notify(&DEV_MMI->kobj, NULL, "double_tap_pressed"); break; diff --git a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c index 1b037dd32a1a..f5858b32d14e 100644 --- a/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c +++ b/drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_panel.c @@ -186,6 +186,9 @@ int ts_mmi_parse_dt(struct ts_mmi_dev *touch_cdev, touch_cdev->clip.xBR, touch_cdev->clip.yBR); } + if (!of_property_read_u32(of_node, "mmi,resolution_boost", &ppdata->resolution_boost)) + dev_info(DEV_TS, "%s: resolution_boost = %d\n", __func__, ppdata->resolution_boost); + chosen = of_find_node_by_name(NULL, "chosen"); if (chosen) { struct device_node *child; diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c index 6d072b63cb52..04ce3f1501f0 100644 --- a/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/aw862xx.c @@ -294,7 +294,7 @@ static void aw862xx_play_mode(struct aw_haptic *aw_haptic, uint8_t play_mode) case AW_RTP_MODE: aw_info("enter rtp mode"); aw_haptic->play_mode = AW_RTP_MODE; - aw862xx_set_pwm(aw_haptic, AW_PWM_24K); + aw862xx_set_pwm(aw_haptic, AW_PWM_12K); aw862xx_auto_brk_config(aw_haptic, true); haptic_nv_i2c_write_bits(aw_haptic, AW862XX_REG_PLAYCFG3, AW862XX_BIT_PLAYCFG3_PLAY_MODE_MASK, diff --git a/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c index 1c00b742f245..13f5941b946c 100644 --- a/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c +++ b/drivers/misc/awinic/aw862x_haptic_nv_v1/haptic_nv.c @@ -48,11 +48,57 @@ static char aw_ram_name[][AW_NAME_MAX] = { }; static char aw_rtp_name[][AW_NAME_MAX] = { - {"haptic_nv_rtp_osc_24K_5s.bin"}, - {"haptic_nv_rtp.bin"}, - {"haptic_nv_rtp_lighthouse.bin"}, - {"haptic_nv_rtp_silk.bin"}, - {"haptic_nv_rtp_autosin.bin"}, + {"aw862xx_rtp.bin"}, + {"aw862xx_rtp_Argo_Navis.bin"}, + {"aw862xx_rtp_Attentive.bin"}, + {"aw862xx_rtp_Awake.bin"}, + {"aw862xx_rtp_Bird_Loop.bin"}, + {"aw862xx_rtp_Brilliant_Times.bin"}, + {"aw862xx_rtp_Chimey_Phone.bin"}, + {"aw862xx_rtp_Complex.bin"}, + {"aw862xx_rtp_Crazy_Dream.bin"}, + {"aw862xx_rtp_Curve_Ball_Blend.bin"}, + {"aw862xx_rtp_Digital_Phone.bin"}, + {"aw862xx_rtp_Electrovision.bin"}, + {"aw862xx_rtp_Ether_Shake.bin"}, + {"aw862xx_rtp_Fateful_Words.bin"}, + {"aw862xx_rtp_Flutey_Phone.bin"}, + {"aw862xx_rtp_Future_Funk.bin"}, + {"aw862xx_rtp_Future_Hi_Tech.bin"}, + {"aw862xx_rtp_Girtab.bin"}, + {"aw862xx_rtp_Hello.bin"}, + {"aw862xx_rtp_Hexagon.bin"}, + {"aw862xx_rtp_Hydra.bin"}, + {"aw862xx_rtp_Insert_Coin.bin"}, + {"aw862xx_rtp_Jumping_Dots.bin"}, + {"aw862xx_rtp_Keys.bin"}, + {"aw862xx_rtp_Loopy.bin"}, + {"aw862xx_rtp_Loopy_Lounge.bin"}, + {"aw862xx_rtp_Modular.bin"}, + {"aw862xx_rtp_Momentum.bin"}, + {"aw862xx_rtp_Morning.bin"}, + {"aw862xx_rtp_Moto.bin"}, + {"aw862xx_rtp_Natural.bin"}, + {"aw862xx_rtp_New_Player.bin"}, + {"aw862xx_rtp_Onward.bin"}, + {"aw862xx_rtp_Organ_Dub.bin"}, + {"aw862xx_rtp_Overclocked.bin"}, + {"aw862xx_rtp_Pegasus.bin"}, + {"aw862xx_rtp_Pyxis.bin"}, + {"aw862xx_rtp_Regrade.bin"}, + {"aw862xx_rtp_Scarabaeus.bin"}, + {"aw862xx_rtp_Sceptrum.bin"}, + {"aw862xx_rtp_Simple.bin"}, + {"aw862xx_rtp_Solarium.bin"}, + {"aw862xx_rtp_Sparse.bin"}, + {"aw862xx_rtp_Terrabytes.bin"}, + {"aw862xx_rtp_Zero_Hour.bin"}, + {"aw862xx_rtp_Play.bin"}, + {"aw862xx_rtp_TJINGLE.bin"}, + {"aw862xx_rtp_Verizon_Airwaves.bin"}, + {"aw862xx_rtp_City_Lights.bin"}, + {"aw862xx_rtp_Firefly.bin"}, + {"aw862xx_rtp_Now_or_Never.bin"}, }; #ifdef AW_TIKTAP @@ -1684,6 +1730,18 @@ static ssize_t seq_store(struct device *dev, struct device_attribute *attr, cons return count; } +static ssize_t rtp_interface_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +static ssize_t rtp_interface_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return count; +} + static ssize_t loop_show(struct device *dev, struct device_attribute *attr, char *buf) { uint8_t i = 0; @@ -2469,6 +2527,7 @@ static DEVICE_ATTR_RW(activate_mode); static DEVICE_ATTR_RW(index); static DEVICE_ATTR_RW(gain); static DEVICE_ATTR_RW(seq); +static DEVICE_ATTR_RW(rtp_interface); static DEVICE_ATTR_RW(loop); static DEVICE_ATTR_RW(ram_update); static DEVICE_ATTR_RW(f0); @@ -2501,6 +2560,7 @@ static struct attribute *vibrator_attributes[] = { &dev_attr_index.attr, &dev_attr_gain.attr, &dev_attr_seq.attr, + &dev_attr_rtp_interface.attr, &dev_attr_loop.attr, &dev_attr_reg.attr, &dev_attr_ram_update.attr, diff --git a/drivers/misc/awinic/sarsensor/Android.mk b/drivers/misc/awinic/sarsensor/Android.mk index c9500f25e070..1d99f6133d70 100644 --- a/drivers/misc/awinic/sarsensor/Android.mk +++ b/drivers/misc/awinic/sarsensor/Android.mk @@ -3,6 +3,7 @@ LOCAL_PATH := $(call my-dir) ifeq ($(AW96XX_USB_USE_ONLINE),true) KERNEL_CFLAGS += CONFIG_AW96XX_POWER_SUPPLY_ONLINE=y + KBUILD_OPTIONS += CONFIG_AW96XX_POWER_SUPPLY_ONLINE=y endif include $(CLEAR_VARS) diff --git a/drivers/moto_f_usbnet/f_usbnet.c b/drivers/moto_f_usbnet/f_usbnet.c index 2131da211a85..8a81bc9dd7ed 100644 --- a/drivers/moto_f_usbnet/f_usbnet.c +++ b/drivers/moto_f_usbnet/f_usbnet.c @@ -621,7 +621,11 @@ static void usb_ether_setup(struct net_device *dev) ether_setup(dev); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 25) eth_random_addr((u8 *)dev->dev_addr); +#else + eth_hw_addr_random(dev); +#endif } /*-------------------------------------------------------------------------*/ diff --git a/drivers/moto_swap/hybridswap/hybridswap_eswap.c b/drivers/moto_swap/hybridswap/hybridswap_eswap.c index 9bad6d608ef8..844ec14e703c 100644 --- a/drivers/moto_swap/hybridswap/hybridswap_eswap.c +++ b/drivers/moto_swap/hybridswap/hybridswap_eswap.c @@ -5490,7 +5490,7 @@ void hybridswap_force_reclaim(struct mem_cgroup *mcg) return; mutex_lock(&hybs->swap_lock); - require_size = atomic64_read(&hybs->zram_stored_size); + require_size = atomic64_read(&hybs->zram_stored_size) / 2; hybs->force_swapout = true; hybridswap_permcg_reclaim(mcg, require_size, &mcg_reclaimed_size); hybs->force_swapout = false; diff --git a/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c b/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c index 6edbd1a01c38..2b01168d3073 100644 --- a/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c +++ b/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c @@ -225,6 +225,7 @@ struct bq2589x { /* enable dynamic adjust vindpm */ bool enable_dynamic_adjust_vindpm; int vindpm_flag; + bool vindpm_track_flag; /*mmi qc3*/ bool mmi_qc3_support; @@ -2730,7 +2731,31 @@ static void bq2589x_monitor_workfunc(struct work_struct *work) schedule_delayed_work(&bq->monitor_work, 10 * HZ); } - +static void bq2589x_set_vindpm_track(struct bq2589x *bq, bool enable) +{ + u8 val; + int ret; + + ret = bq2589x_read_byte(bq, &val, 0x85); + if (ret < 0) { + bq2589x_write_byte(bq, 0x7D, 0x48); + bq2589x_write_byte(bq, 0x7D, 0x54); + bq2589x_write_byte(bq, 0x7D, 0x53); + bq2589x_write_byte(bq, 0x7D, 0x38); + bq2589x_read_byte(bq, &val, 0x85); + } + dev_info(bq->dev, "%s:0x85_1 = %x\n", __func__,val); + if (enable) + bq2589x_write_byte(bq, 0x85, val|0x06); + else + bq2589x_write_byte(bq, 0x85, val & 0xF9); + bq2589x_read_byte(bq, &val, 0x85); + dev_info(bq->dev, "%s:0x85_2 = %x\n", __func__,val); + bq2589x_write_byte(bq, 0x7D, 0x48); + bq2589x_write_byte(bq, 0x7D, 0x54); + bq2589x_write_byte(bq, 0x7D, 0x53); + bq2589x_write_byte(bq, 0x7D, 0x38); +} static void bq2589x_charger_irq_workfunc(struct work_struct *work) { @@ -2784,12 +2809,21 @@ static void bq2589x_charger_irq_workfunc(struct work_struct *work) bq->cv_tune = 0; bq2589x_set_chargevoltage(bq, bq->final_cv/1000); } + if (bq->part_no == SC89890H && bq->vindpm_track_flag) { + bq2589x_set_vindpm_track(bq,false); + bq->vindpm_track_flag = false; + } } else if ((bq->vbus_type != BQ2589X_VBUS_NONE) && (bq->vbus_type != BQ2589X_VBUS_OTG) && (!(bq->status & BQ2589X_STATUS_PLUGIN) || (reapsd_complete == true)) && state.online) { dev_info(bq->dev, "%s:adapter plugged in\n", __func__); bq->status |= BQ2589X_STATUS_PLUGIN; bq2589x_adapter_in_func(bq); + if ((bq->part_no == SC89890H) && (bq->vbus_type == BQ2589X_VBUS_USB_CDP) + && !bq->vindpm_track_flag) { + bq2589x_set_vindpm_track(bq,true); + bq->vindpm_track_flag = true; + } } diff --git a/drivers/power/mmi-smbcharger-iio/mmi-smbcharger-iio.c b/drivers/power/mmi-smbcharger-iio/mmi-smbcharger-iio.c index b9d2edc7cabe..a3d2d34cddbc 100755 --- a/drivers/power/mmi-smbcharger-iio/mmi-smbcharger-iio.c +++ b/drivers/power/mmi-smbcharger-iio/mmi-smbcharger-iio.c @@ -526,6 +526,10 @@ struct smb_mmi_charger { bool enable_dcp_ffc; bool enable_fcc_large_qg_iterm; + + /*Battery info*/ + unsigned long manufacturing_date; + unsigned long first_usage_date; }; #define CHGR_FAST_CHARGE_CURRENT_CFG_REG (CHGR_BASE + 0x61) @@ -736,6 +740,7 @@ enum smb_mmi_ext_iio_channels { SMB5_QG_CHARGE_FULL, SMB5_QG_CHARGE_FULL_DESIGN, SMB5_QG_BATT_FULL_CURRENT, + SMB5_QG_SOH, }; static const char * const smb_mmi_ext_iio_chan_name[] = { @@ -759,6 +764,7 @@ static const char * const smb_mmi_ext_iio_chan_name[] = { [SMB5_QG_CHARGE_FULL] = "charge_full", [SMB5_QG_CHARGE_FULL_DESIGN] = "charge_full_design", [SMB5_QG_BATT_FULL_CURRENT] = "batt_full_current", + [SMB5_QG_SOH] = "soh", }; bool is_chan_valid(struct smb_mmi_charger *chip, @@ -3712,7 +3718,11 @@ static void mmi_basic_charge_sm(struct smb_mmi_charger *chip, prm->pres_chrg_step = STEP_FULL; } } else if (prm->pres_chrg_step == STEP_FULL) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,25) + if (stat->batt_soc <= 95) { +#else if (stat->batt_mv < (max_fv_mv - HYST_STEP_MV * 2)) { +#endif prm->chrg_taper_cnt = 0; prm->pres_chrg_step = STEP_NORM; } @@ -4226,29 +4236,40 @@ static void mmi_heartbeat_work(struct work_struct *work) } } else if (!chip->factory_mode) { - cap_err = 0; - rc = smb_mmi_read_iio_chan(chip, - SMB5_QG_CHARGE_FULL, - &pval.intval); + //Get soh from qcom gauge, or soh=age=fcc/fcc_designed + rc = smb_mmi_read_iio_chan(chip, SMB5_QG_SOH, &pval.intval); if (rc < 0) { - mmi_err(chip, "Couldn't get charge full\n"); - cap_err = rc; - } else - main_cap = pval.intval; + mmi_err(chip, "Couldn't get qcom battery soh\n"); + //chip->age = 100; + cap_err = 0; + rc = smb_mmi_read_iio_chan(chip, + SMB5_QG_CHARGE_FULL, + &pval.intval); + if (rc < 0) { + mmi_err(chip, "Couldn't get charge full\n"); + cap_err = rc; + } else + main_cap = pval.intval; - rc = smb_mmi_read_iio_chan(chip, - SMB5_QG_CHARGE_FULL_DESIGN, - &pval.intval); - if (rc < 0) { - mmi_err(chip, "Couldn't get charge full design\n"); - cap_err = rc; - } else - main_cap_full = pval.intval; + rc = smb_mmi_read_iio_chan(chip, + SMB5_QG_CHARGE_FULL_DESIGN, + &pval.intval); + if (rc < 0) { + mmi_err(chip, "Couldn't get charge full design\n"); + cap_err = rc; + } else + main_cap_full = pval.intval; - if (cap_err == 0) - chip->age = ((main_cap / 10) / (main_cap_full / 1000)); + if (cap_err == 0) + chip->age = ((main_cap / 10) / (main_cap_full / 1000)); - mmi_dbg(chip, "Age %d\n", chip->age); + mmi_dbg(chip, "mmi_age %d\n", chip->age); + } else { + chip->age = pval.intval; + mmi_dbg(chip, "get qg soh=%d\n", chip->age); + if (chip->cycles < 50) + chip->age = 100; + } /* Fall here for Basic Step and Thermal Charging */ mmi_basic_charge_sm(chip, &chg_stat); @@ -4343,7 +4364,6 @@ sch_hb: envp[0] = chrg_rate_string; envp[1] = NULL; } - if (chip->batt_psy) { smb_mmi_power_supply_changed(chip->batt_psy, envp); } else if (chip->qcom_psy) { @@ -4503,7 +4523,13 @@ static int batt_get_prop(struct power_supply *psy, val->intval = chip->last_reported_soc; break; case POWER_SUPPLY_PROP_CYCLE_COUNT: - val->intval = chip->cycles / 100; + if (chip->max_main_psy && chip->max_flip_psy) + val->intval = chip->cycles / 100; + else { + rc = power_supply_get_property(chip->qcom_psy, psp, val); + if (rc >= 0) + chip->cycles = val->intval; + } break; case POWER_SUPPLY_PROP_HEALTH: if (chip->max_main_psy && chip->max_flip_psy) @@ -4568,7 +4594,13 @@ static int batt_set_prop(struct power_supply *psy, switch (prop) { case POWER_SUPPLY_PROP_CYCLE_COUNT: - chip->cycles += val->intval * 100; + if (chip->max_main_psy && chip->max_flip_psy) { + chip->cycles += val->intval * 100; + } else { + rc = power_supply_set_property(chip->qcom_psy, prop, val); + if (rc < 0) + mmi_err(chip, "set cycle_count failed, rc=%d\n", rc); + } break; case POWER_SUPPLY_PROP_CURRENT_MAX: if (val->intval < 0) { @@ -4957,9 +4989,100 @@ static ssize_t age_show(struct device *dev, } static DEVICE_ATTR(age, S_IRUGO, age_show, NULL); +static ssize_t state_of_health_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + if (!this_chip) { + pr_err("mmi_charger: chip is invalid\n"); + return -ENODEV; + } + + return scnprintf(buf, CHG_SHOW_MAX_SIZE, "%d\n", this_chip->age); +} + +static DEVICE_ATTR(state_of_health, S_IRUGO, state_of_health_show, NULL); + +static ssize_t first_usage_date_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + if (!this_chip) { + pr_err("mmi_charger: chip is invalid\n"); + return -ENODEV; + } + + return scnprintf(buf, CHG_SHOW_MAX_SIZE, "%lu\n", this_chip->first_usage_date); +} + +static ssize_t first_usage_date_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long r; + unsigned long first_usage_date; + + if (!this_chip) { + pr_err("mmi_charger: chip is invalid\n"); + return -ENODEV; + } + + r = kstrtoul(buf, 0, &first_usage_date); + if (r) { + mmi_err(this_chip, "Invalid first_usage_date value = %lu\n", first_usage_date); + return -EINVAL; + } + + this_chip->first_usage_date = first_usage_date; + + return r ? r : count; +} + +static DEVICE_ATTR(first_usage_date, 0644, first_usage_date_show, first_usage_date_store); + +static ssize_t manufacturing_date_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + if (!this_chip) { + pr_err("mmi_charger: chip is invalid\n"); + return -ENODEV; + } + + return scnprintf(buf, CHG_SHOW_MAX_SIZE, "%lu\n", this_chip->manufacturing_date); +} + +static ssize_t manufacturing_date_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long r; + unsigned long manufacturing_date; + + if (!this_chip) { + pr_err("mmi_charger: chip is invalid\n"); + return -ENODEV; + } + + r = kstrtoul(buf, 0, &manufacturing_date); + if (r) { + mmi_err(this_chip, "Invalid manufacturing_date value = %lu\n", manufacturing_date); + return -EINVAL; + } + + this_chip->manufacturing_date = manufacturing_date; + + return r ? r : count; +} + +static DEVICE_ATTR(manufacturing_date, 0644, manufacturing_date_show, manufacturing_date_store); + static struct attribute * mmi_g[] = { &dev_attr_charge_rate.attr, &dev_attr_age.attr, + &dev_attr_state_of_health.attr, + &dev_attr_manufacturing_date.attr, + &dev_attr_first_usage_date.attr, NULL, }; diff --git a/drivers/power/mmi_charger/mmi_charger.c b/drivers/power/mmi_charger/mmi_charger.c index 9fa081203381..d402099ad5ef 100644 --- a/drivers/power/mmi_charger/mmi_charger.c +++ b/drivers/power/mmi_charger/mmi_charger.c @@ -40,7 +40,7 @@ #define BATT_PAIR_ID_MASK ((1 << BATT_PAIR_ID_BITS) - 1) #define HEARTBEAT_DELAY_MS 60000 -#define HEARTBEAT_FACTORY_MS 1000 +#define HEARTBEAT_FACTORY_MS 5000 #define HEARTBEAT_DISCHARGE_MS 100000 #define HEARTBEAT_WAKEUP_INTRVAL_NS 70000000000 @@ -71,6 +71,7 @@ enum { NOTIFY_EVENT_TYPE_LPD_PRESENT, NOTIFY_EVENT_TYPE_VBUS_PRESENT, NOTIFY_EVENT_TYPE_POWER_WATT, + NOTIFY_EVENT_TYPE_CHG_REAL_TYPE, }; static char *charge_rate[] = { @@ -219,6 +220,7 @@ struct mmi_charger_chip { int charge_full_design; int init_cycles; int max_charger_rate; + int real_charger_type; bool vbus_present; bool lpd_present; int power_watt; @@ -240,12 +242,14 @@ struct mmi_charger_chip { bool enable_factory_poweroff; bool factory_syspoweroff_wait; bool start_factory_kill_disabled; + int upper_limit_en_mv; int upper_limit_capacity; int lower_limit_capacity; struct wakeup_source *mmi_hb_wake_source; struct alarm heartbeat_alarm; int heartbeat_interval; + int heartbeat_factory_interval; struct notifier_block mmi_reboot; struct notifier_block mmi_psy_notifier; struct delayed_work heartbeat_work; @@ -361,6 +365,8 @@ static ssize_t state_sync_store(struct device *dev, NOTIFY_EVENT_TYPE_VBUS_PRESENT); mmi_notify_charger_event(this_chip, NOTIFY_EVENT_TYPE_POWER_WATT); + mmi_notify_charger_event(this_chip, + NOTIFY_EVENT_TYPE_CHG_REAL_TYPE); mutex_unlock(&this_chip->charger_lock); cancel_delayed_work(&this_chip->heartbeat_work); schedule_delayed_work(&this_chip->heartbeat_work, @@ -1502,7 +1508,8 @@ static void mmi_update_charger_status(struct mmi_charger_chip *chip, if (chip->enable_charging_limit && chip->factory_version) { charging_limit_modes = status->charging_limit_modes; if ((charging_limit_modes != CHARGING_LIMIT_RUN) - && (batt_info->batt_soc >= chip->upper_limit_capacity)) + && (batt_info->batt_soc >= chip->upper_limit_capacity) + && (batt_info->batt_mv >= chip->upper_limit_en_mv)) charging_limit_modes = CHARGING_LIMIT_RUN; else if ((charging_limit_modes != CHARGING_LIMIT_OFF) && (batt_info->batt_soc <= chip->lower_limit_capacity)) @@ -1776,6 +1783,11 @@ static void mmi_notify_charger_event(struct mmi_charger_chip *chip, int type) "POWER_SUPPLY_POWER_WATT=%d", chip->power_watt / 1000); break; + case NOTIFY_EVENT_TYPE_CHG_REAL_TYPE: + scnprintf(event_string, CHG_SHOW_MAX_SIZE, + "POWER_SUPPLY_CHARGE_REAL_TYPE=%d", + chip->real_charger_type); + break; default: mmi_err(chip, "Invalid notify event type %d\n", type); kfree(event_string); @@ -1989,6 +2001,8 @@ static void mmi_update_battery_status(struct mmi_charger_chip *chip) int batt_health = POWER_SUPPLY_HEALTH_UNKNOWN; int charger_rate = MMI_POWER_SUPPLY_CHARGE_RATE_NONE; int max_charger_rate = MMI_POWER_SUPPLY_CHARGE_RATE_NONE; + int charger_type = 0; + int real_charger_type = 0; struct mmi_charger *charger = NULL; struct mmi_battery_pack *battery = NULL; struct mmi_battery_info *batt_info = NULL; @@ -2027,6 +2041,11 @@ static void mmi_update_battery_status(struct mmi_charger_chip *chip) if (charger->chg_info.chrg_pmax_mw > power_watt) power_watt = charger->chg_info.chrg_pmax_mw; + /* update charger type */ + charger_type = charger->chg_info.chrg_type; + if (charger_type != 0xFF && real_charger_type < charger_type) + real_charger_type = charger_type; + /* update charging status */ if (batt_info->batt_status == POWER_SUPPLY_STATUS_FULL || battery->status == POWER_SUPPLY_STATUS_FULL || @@ -2056,6 +2075,7 @@ static void mmi_update_battery_status(struct mmi_charger_chip *chip) battery->cycles, charge_rate[battery->charger_rate]); } + /* update vbus and liquid present detection status */ if (!vbus_present && charger->chg_info.vbus_present) vbus_present = true; @@ -2127,6 +2147,13 @@ static void mmi_update_battery_status(struct mmi_charger_chip *chip) mmi_info(chip, "charger power is %d mW\n", power_watt); } + if ((chip->real_charger_type) != real_charger_type) { + mmi_changed = true; + chip->real_charger_type = real_charger_type; + mmi_notify_charger_event(chip, NOTIFY_EVENT_TYPE_CHG_REAL_TYPE); + mmi_info(chip, "charger real type is %d\n", real_charger_type); + } + list_for_each_entry(battery, &chip->battery_list, list) { if (batt_health == POWER_SUPPLY_HEALTH_UNKNOWN) { batt_health = battery->health; @@ -2254,7 +2281,7 @@ static void mmi_charger_heartbeat_work(struct work_struct *work) chip->suspended = 0; if (chip->factory_mode) - hb_resch_time = HEARTBEAT_FACTORY_MS; + hb_resch_time = chip->heartbeat_factory_interval; else if (chip->max_charger_rate != MMI_POWER_SUPPLY_CHARGE_RATE_NONE && chip->combo_status != POWER_SUPPLY_STATUS_FULL) hb_resch_time = chip->heartbeat_interval; @@ -2627,10 +2654,12 @@ static int mmi_charger_reboot(struct notifier_block *nb, if (!chip->factory_mode) return NOTIFY_DONE; + pr_info("Reboot notifier call mmi charger reboot!\n"); switch (event) { case SYS_POWER_OFF: factory_kill_disable = true; chip->force_charger_disabled = true; + cancel_delayed_work(&chip->heartbeat_work); schedule_delayed_work(&chip->heartbeat_work, msecs_to_jiffies(0)); while (chip->max_charger_rate != MMI_POWER_SUPPLY_CHARGE_RATE_NONE && (shutdown_triggered || chip->factory_syspoweroff_wait) && !chip->empty_vbat_shutdown_triggered) { @@ -2788,6 +2817,11 @@ static int mmi_parse_dt(struct mmi_charger_chip *chip) if (rc) chip->factory_kill_debounce_ms = 0; + rc = of_property_read_u32(node, "mmi,upper-limit-en-voltage", + &chip->upper_limit_en_mv); + if (rc) + chip->upper_limit_en_mv = 4000; + rc = of_property_read_u32(node, "mmi,upper-limit-capacity", &chip->upper_limit_capacity); if (rc) @@ -2803,6 +2837,11 @@ static int mmi_parse_dt(struct mmi_charger_chip *chip) if (rc) chip->heartbeat_interval = HEARTBEAT_DELAY_MS; + rc = of_property_read_u32(node, "mmi,heartbeat-factory-interval", + &chip->heartbeat_factory_interval); + if (rc) + chip->heartbeat_factory_interval = HEARTBEAT_FACTORY_MS; + rc = of_property_read_u32(node, "mmi,dcp-power-max", &chip->dcp_pmax); if (rc) @@ -3049,6 +3088,7 @@ static void mmi_charger_shutdown(struct platform_device *pdev) { struct mmi_charger_chip *chip = platform_get_drvdata(pdev); + cancel_delayed_work(&chip->heartbeat_work); mmi_info(chip, "MMI charger shutdown\n"); return; diff --git a/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.c b/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.c index c3b6da56e971..f538eebcd217 100644 --- a/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.c +++ b/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.c @@ -232,7 +232,7 @@ static int sc760x_enable_chip(struct sc760x_chip *sc, bool en) if (sc->sc760x_enable) { - if (!sc->irq_enabled) { + if (sc->irq && !sc->irq_enabled) { enable_irq_wake(sc->irq); enable_irq(sc->irq); sc->irq_enabled = true; @@ -242,7 +242,7 @@ static int sc760x_enable_chip(struct sc760x_chip *sc, bool en) pr_info("init device failed(%d)\n", ret); } } else { - if (sc->irq_enabled) { + if (sc->irq && sc->irq_enabled) { disable_irq_wake(sc->irq); disable_irq(sc->irq); sc->irq_enabled = false; @@ -1063,6 +1063,9 @@ static int sc760x_parse_dt(struct sc760x_chip *sc, struct device *dev) sc->init_data.charger_disabled = of_property_read_bool(node, "init-charger-disabled"); + sc->irq_dis_cfg = + of_property_read_bool(node, "irq-dis-cfg"); + ret = device_property_read_u32(sc->dev, "iterm-microamp", &sc->init_data.iterm); @@ -1193,6 +1196,12 @@ static int sc760x_register_interrupt(struct sc760x_chip *sc, struct i2c_client * { int ret = 0; + if (sc->irq_dis_cfg) { + sc->irq = 0; + dev_err(sc->dev, "irq_dis_cfg is ture\n"); + return 0; + } + ret = devm_request_threaded_irq(sc->dev, client->irq, NULL, sc760x_irq_handler, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, @@ -1202,6 +1211,8 @@ static int sc760x_register_interrupt(struct sc760x_chip *sc, struct i2c_client * return ret; } + disable_irq_wake(client->irq); + disable_irq(client->irq); sc->irq_enabled = false; sc->irq = client->irq; dev_err(sc->dev, "request thread irq success\n"); @@ -1421,11 +1432,6 @@ static void charger_detect_work_func(struct work_struct *work) goto err; } - if (state_changed) { - sc760x_dump_reg(sc); - power_supply_changed(sc->charger_psy); - } - return; err: //release wakelock if (state_changed) @@ -2099,9 +2105,13 @@ static int sc760x_suspend(struct device *dev) struct sc760x_chip *sc = dev_get_drvdata(dev); int ret = 0; dev_info(sc->dev, "Suspend successfully!"); - if (device_may_wakeup(dev)) - enable_irq_wake(sc->irq); - disable_irq(sc->irq); + + if (sc->irq) { + if (device_may_wakeup(dev)) + enable_irq_wake(sc->irq); + disable_irq(sc->irq); + sc->irq_enabled = false; + } ret = sc760x_set_adc_enable(sc, false); if (ret < 0) { dev_err(sc->dev, "%s Failed to disable adc(%d)\n", __func__, ret); @@ -2119,10 +2129,12 @@ static int sc760x_resume(struct device *dev) struct sc760x_chip *sc = dev_get_drvdata(dev); int ret = 0; dev_info(sc->dev, "Resume successfully!"); - if (device_may_wakeup(dev)) - disable_irq_wake(sc->irq); - enable_irq(sc->irq); - + if (sc->irq) { + if (device_may_wakeup(dev)) + disable_irq_wake(sc->irq); + enable_irq(sc->irq); + sc->irq_enabled = true; + } ret = sc760x_set_lowpower_mode(sc, false); if (ret < 0) { dev_err(sc->dev, "%s Failed to exit lowpower(%d)\n", __func__, ret); diff --git a/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.h b/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.h index dc13dd7902ee..15add4f117cb 100644 --- a/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.h +++ b/drivers/power/sc760x_charger_mmi/sc760x_charger_mmi.h @@ -201,6 +201,7 @@ struct sc760x_chip { int irq; bool irq_enabled; + bool irq_dis_cfg; int role; int sc760x_enable; u32 *thermal_levels; diff --git a/drivers/regulator/wl2866d/Makefile b/drivers/regulator/wl2866d/Makefile index 4191dea22679..365d3fe73a44 100644 --- a/drivers/regulator/wl2866d/Makefile +++ b/drivers/regulator/wl2866d/Makefile @@ -1,10 +1,15 @@ -KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build +all: modules -all: - $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) +modules: + $(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS) modules_install: - $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install + +%: + $(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS) clean: - $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean + rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers + rm -rf .tmp_versions + diff --git a/drivers/uwb/qm35/qm35-spi.c b/drivers/uwb/qm35/qm35-spi.c index e8bf1235c930..f01de2488d91 100644 --- a/drivers/uwb/qm35/qm35-spi.c +++ b/drivers/uwb/qm35/qm35-spi.c @@ -47,6 +47,7 @@ #include #endif +#include #include #include #include @@ -1008,6 +1009,13 @@ static int qm35_probe(struct spi_device *spi) struct clk *uwb_clk; int ret = 0; + if (spi->dev.of_node && !mmi_device_is_available(spi->dev.of_node)) { + pr_err("%s : mmi: device not supported\n", __func__); + return -ENODEV; + } else { + pr_err("%s : supported uwb device found\n", __func__); + } + if (fwname) { qmrom_set_fwname(fwname); } diff --git a/drivers/wlan_antenna/wlan_antenna.c b/drivers/wlan_antenna/wlan_antenna.c index 7f71369330e4..209fbd9bac88 100644 --- a/drivers/wlan_antenna/wlan_antenna.c +++ b/drivers/wlan_antenna/wlan_antenna.c @@ -25,13 +25,15 @@ #include #include #include - +#include +#include #define DRIVER_VERSION "0.0.1" struct wlan_antenna_drvdata { struct device *dev; struct pinctrl *pinctrl; + int wlan_antenna_gpio; struct pinctrl_state *pstate_active; struct pinctrl_state *pstate_suspend; }; @@ -47,7 +49,10 @@ static ssize_t wlan_antenna_en_read(struct device *dev, return -EINVAL; } - return snprintf(buf, PAGE_SIZE, "wlan_antenna: not support!\n"); + if (gpio_get_value(data->wlan_antenna_gpio)) + return snprintf(buf, PAGE_SIZE, "high\n"); + else + return snprintf(buf, PAGE_SIZE, "low\n"); } static ssize_t wlan_antenna_en_write(struct device *dev, @@ -77,8 +82,6 @@ static ssize_t wlan_antenna_en_write(struct device *dev, if(ret) { pr_err("wlan_antenna failed to set pinctrl!\n"); - } else { - pr_info("wlan_antenna success set pinctrl\n"); } return count; @@ -108,6 +111,13 @@ static int wlan_antenna_probe(struct platform_device *pdev) drvdata->dev = &pdev->dev; platform_set_drvdata(pdev, drvdata); + drvdata->wlan_antenna_gpio = of_get_named_gpio(dev->of_node, "qcom,wlan_antenna-gpio", 0); + ret = gpio_request(drvdata->wlan_antenna_gpio, "wlan_antenna_gpio"); + if (ret) { + pr_err("%s, unable to request gpio %d (%d)\n", __func__, drvdata->wlan_antenna_gpio, ret); + return ret; + } + /* Get pinctrl if target uses pinctrl */ drvdata->pinctrl = devm_pinctrl_get(dev); if (IS_ERR_OR_NULL(drvdata->pinctrl)) { diff --git a/include/linux/touchscreen_mmi.h b/include/linux/touchscreen_mmi.h index 48ff3f67aabd..3655136150a1 100644 --- a/include/linux/touchscreen_mmi.h +++ b/include/linux/touchscreen_mmi.h @@ -467,6 +467,7 @@ struct ts_mmi_dev_pdata { #ifdef CONFIG_BOARD_USES_DOUBLE_TAP_CTRL int supported_gesture_type; #endif + int resolution_boost; }; /**