Merge tag 'MMI-V1UG35H.75-14' of https://github.com/MotorolaMobilityLLC/motorola-kernel-modules into lineage-22.2

"Fogos push for Android 15"

# By Wenge Zhu (6) and others
# Via Andrea dos Santos
* tag 'MMI-V1UG35H.75-14' of https://github.com/MotorolaMobilityLLC/motorola-kernel-modules:
  mmi-smbcharger: the battery age value switch to qcom gauge soh
  mmi_smbcharger_iio: allow to set fuelgauge cycle_count
  mmi_smbcharger_iio: Get batt cycyle_count from qcom_fg
  mmi_smbcharger_iio: recharge <=95%
  mmi_charger: Add state_of_health/first_usage_date/manufacturing_date
  moto_swap: Reduce force eswap out size of half
  dlkm: goodix_fod_mmi: fix KE issue
  dlkm: goodix_fod: support drm panel notification
  moto_swap: Add reset_bdev to close backing dev for ramboost2.0
  avatrn: support touch sensitivity in game mode
  boston: support touch sensitivity in game mode
  focaltech: support stowed detection when gesture mode for focal
  insmod qorvo uwb driver according to mmi_info
  arm64/dts: update the wlan_antenna driver code for boston
  usbnet: fix incorrect dev_addr
  add page fault pages to list head to avoid be swapped out soon
  input: goodix_berlin: set default touch state to finger mode
  Report tapping coordinate when report gesture event
  awinic sar:add KBUILD_OPTIONS
  dlkm/fps:optimse driver for jiiov
  fogos: TP: open 1st icnl9916c force up config
  workaround fix long page fault issue
  kernel/fogo:fix The device automatically restarts during use
  cusco: WL2866d bringup [1/4]
  Support touch mmi class for GT9615
  sc760x: Relax wakelock
  Upgrade gt9615 touch driver version
  Support factory test
  mmi_charger: Add heartbeat-factory-interval
  add sc89890h vindpm_track
  Revert "(CR) moto_swap: Add SWP_SYNCHRONOUS_IO cmd for ioctl"
  sc760x_charger: irq-dis-cfg
  eqe: input touch support game mode
  Distinguish log print with main touch
  Add IC type of GT9615
  avatrn: add parrot build config for fts
  charger: add factory charge limit enable voltage
  Chipone: Fix compatibility with 5.4.0 api
  fix null pointer at quota_day_store
  moto_swap: Add SWP_SYNCHRONOUS_IO cmd for ioctl
  Add charger type uevent
  eqe: vibrator add haptic rtp support
  charge: config qg iterm small than FCC
  Take FPS driver compile error
  ctwov: Solve iic_driver .remove compatibility issue

 Conflicts:
	drivers/input/misc/goodix_fod_mmi/Kbuild
	drivers/input/touchscreen/focaltech_touch_v3/Kbuild
	drivers/input/touchscreen/goodix_berlin_mmi/Kbuild
	drivers/input/touchscreen/touchscreen_mmi/touchscreen_mmi_gesture.c
	drivers/power/mmi-smbcharger-iio/mmi-smbcharger-iio.c

Change-Id: I49de02f202aba2d0a355bd8b86d5a8378e962e61
This commit is contained in:
Michael Bestas 2025-05-05 09:47:07 +03:00
commit b487e97532
No known key found for this signature in database
47 changed files with 1317 additions and 175 deletions

View file

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

View file

@ -8,6 +8,7 @@
* as published by the Free Software Foundation.
*/
#include <linux/version.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
@ -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;

View file

@ -13,6 +13,7 @@
* GNU General Public License for more details.
*
*/
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/of_gpio.h>
@ -30,6 +31,10 @@
#include <linux/platform_device.h>
#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)) {

View file

@ -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)

View file

@ -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");

View file

@ -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)

View file

@ -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

View file

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

View file

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

View file

@ -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,

View file

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

View file

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

View file

@ -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,

View file

@ -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)

View file

@ -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,

View file

@ -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)

View file

@ -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)

View file

@ -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");
}

View file

@ -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

View file

@ -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

View file

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

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -23,12 +23,15 @@
#include <linux/input/mt.h>
#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);

View file

@ -47,9 +47,9 @@
#include <linux/fb.h>
#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

View file

@ -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 = &params_brd;
else if (ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM)
test_params->params_info = &params_not;
else if (ts_test->ts->bus->ic_type == IC_TYPE_MARSEILLE)
test_params->params_info = &params_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("<Result>%s</Result>\n", result ? "NG" : "OK");
proc_append_string("<DeviceType>GT%s</DeviceType>\n<SensorId>%d</SensorId>\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("<Item name=\"Version Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Version Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Version Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Version Test\" result=\"NG\"/>\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("<Item name=\"Check Chip Key Info\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Check Chip Key Info\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Check Chip Key Info\" result=\"NG\"/>\n");
ts_err("<Item name=\"Check Chip Key Info\" result=\"NG\"/>\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("<Item name=\"Custom Info Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Custom Info Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Custom Info Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Custom Info Test\" result=\"NG\"/>\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("<Item name=\"Rawdata MAX/MIN Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Rawdata MAX/MIN Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Rawdata MAX/MIN Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Rawdata MAX/MIN Test\" result=\"NG\"/>\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("<Item name=\"Rawdata Adjcent Deviation Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Rawdata Adjcent Deviation Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Rawdata Adjcent Deviation Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Rawdata Adjcent Deviation Test\" result=\"NG\"/>\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("<Item name=\"Diffdata Jitter Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Diffdata Jitter Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Diffdata Jitter Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Diffdata Jitter Test\" result=\"NG\"/>\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("<Item name=\"Self Diffdata Jitter Limit Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Self Diffdata Jitter Limit Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Self Diffdata Jitter Limit Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Self Diffdata Jitter Limit Test\" result=\"NG\"/>\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("<Item name=\"Self Rawdata Upper Limit Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Self Rawdata Upper Limit Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Self Rawdata Upper Limit Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Self Rawdata Upper Limit Test\" result=\"NG\"/>\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("<Item name=\"Short Test\" result=\"OK\"/>\n");
else
proc_append_string("<Item name=\"Short Test\" result=\"NG\"/>\n");
else {
proc_append_string("<Item name=\"Short Test\" result=\"NG\"/>\n");
ts_err("<Item name=\"Short Test\" result=\"NG\"/>\n");
}
}
proc_append_string("</ItemList>\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;
}

View file

@ -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 <linux/delay.h>
#include <linux/input/mt.h>
#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);
}

View file

@ -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 <linux/platform_device.h>
#include <linux/touchscreen_mmi.h>
#include <linux/mmi_wake_lock.h>
#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

View file

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

View file

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

View file

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

View file

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

View file

@ -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,

View file

@ -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,

View file

@ -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)

View file

@ -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
}
/*-------------------------------------------------------------------------*/

View file

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

View file

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

View file

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

View file

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

View file

@ -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);

View file

@ -201,6 +201,7 @@ struct sc760x_chip {
int irq;
bool irq_enabled;
bool irq_dis_cfg;
int role;
int sc760x_enable;
u32 *thermal_levels;

View file

@ -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

View file

@ -47,6 +47,7 @@
#include <linux/ktime.h>
#endif
#include <linux/mmi_device.h>
#include <linux/uwb/qmrom.h>
#include <linux/uwb/qmrom_spi.h>
#include <linux/uwb/qmrom_log.h>
@ -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);
}

View file

@ -25,13 +25,15 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#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)) {

View file

@ -467,6 +467,7 @@ struct ts_mmi_dev_pdata {
#ifdef CONFIG_BOARD_USES_DOUBLE_TAP_CTRL
int supported_gesture_type;
#endif
int resolution_boost;
};
/**