unplugged-kernel/drivers/input/touchscreen/mediatek/hxchipset/himax_platform.c

768 lines
18 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include "himax_ic.h"
int i2c_error_count;
int irq_enable_count;
DEFINE_MUTEX(hx_wr_access);
MODULE_DEVICE_TABLE(of, himax_match_table);
const struct of_device_id himax_match_table[] = {
{.compatible = "mediatek,cap_touch"}, {},
};
static int himax_tpd_int_gpio = 5;
unsigned int himax_touch_irq;
unsigned int himax_tpd_rst_gpio_number = -1;
unsigned int himax_tpd_int_gpio_number = -1;
u8 *gpDMABuf_va;
u8 *gpDMABuf_pa;
/* Custom set some config */
static int hx_panel_coords[4] = {0, 1080, 0,
1920}; /* [1]=X resolution, [3]=Y resolution */
static int hx_display_coords[4] = {0, 1080, 0, 1920};
static int report_type = PROTOCOL_TYPE_B;
struct i2c_client *i2c_client_point;
#if defined(HX_PLATFOME_DEFINE_KEY)
/*In MT6797 need to set 1 into use-tpd-button in dts */
/* kernel-3.18\arch\arm64\boot\dts\amt6797_evb_m.dts*/
/*key_range : [keyindex][key_data] {..{x,y}..}*/
static int key_range[3][2] = {{180, 2400}, {360, 2400}, {540, 2400} };
#endif
int himax_dev_set(struct himax_ts_data *ts)
{
ts->input_dev = tpd->dev;
return NO_ERR;
}
int himax_input_register_device(struct input_dev *input_dev)
{
return NO_ERR;
}
#if defined(HX_PLATFOME_DEFINE_KEY)
void himax_platform_key(void)
{
int idx = 0;
if (tpd_dts_data.use_tpd_button) {
for (idx = 0; idx < tpd_dts_data.tpd_key_num; idx++) {
input_set_capability(tpd->dev, EV_KEY,
tpd_dts_data.tpd_key_local[idx]);
I("[%d]key:%d\n", idx, tpd_dts_data.tpd_key_local[idx]);
}
}
}
/* report coordinates to system and system will transfer it into Key */
static void himax_vk_parser(struct himax_i2c_platform_data *pdata, int key_num)
{
int i = 0;
struct himax_virtual_key *vk;
uint8_t key_index = 0;
vk = kzalloc(key_num * (sizeof(*vk)), GFP_KERNEL);
for (key_index = 0; key_index < key_num; key_index++) {
/* index: def in our driver */
vk[key_index].index = key_index + 1;
/* key size */
vk[key_index].x_range_min = key_range[key_index][0],
vk[key_index].x_range_max = key_range[key_index][0];
vk[key_index].y_range_min = key_range[key_index][1],
vk[key_index].y_range_max = key_range[key_index][1];
}
pdata->virtual_key = vk;
for (i = 0; i < key_num; i++) {
I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,
pdata->virtual_key[i].index,
pdata->virtual_key[i].x_range_min,
pdata->virtual_key[i].y_range_max);
}
}
#else
void himax_vk_parser(struct device_node *dt,
struct himax_i2c_platform_data *pdata)
{
u32 data = 0;
uint8_t cnt = 0, i = 0;
uint32_t coords[4] = {0};
struct device_node *node, *pp = NULL;
struct himax_virtual_key *vk;
node = of_parse_phandle(dt, "virtualkey", 0);
if (node == NULL) {
I(" DT-No vk info in DT");
return;
}
while ((pp = of_get_next_child(node, pp)))
cnt++;
if (!cnt)
return;
vk = kzalloc(cnt * (sizeof(*vk)), GFP_KERNEL);
pp = NULL;
while ((pp = of_get_next_child(node, pp))) {
if (of_property_read_u32(pp, "idx", &data) == 0)
vk[i].index = data;
if (of_property_read_u32_array(pp, "range", coords, 4) == 0) {
vk[i].x_range_min = coords[0],
vk[i].x_range_max = coords[1];
vk[i].y_range_min = coords[2],
vk[i].y_range_max = coords[3];
} else
I(" range faile");
i++;
}
pdata->virtual_key = vk;
for (i = 0; i < cnt; i++)
I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,
pdata->virtual_key[i].index,
pdata->virtual_key[i].x_range_min,
pdata->virtual_key[i].y_range_max);
}
#endif
int himax_parse_dt(struct himax_ts_data *ts,
struct himax_i2c_platform_data *pdata)
{
struct device_node *dt = ts->client->dev.of_node;
struct i2c_client *client = ts->client;
if (dt) {
const struct of_device_id *match;
match = of_match_device(of_match_ptr(himax_match_table),
&client->dev);
if (!match) {
TPD_DMESG("[Himax]Error: No device match found\n");
return -ENODEV;
}
}
himax_tpd_rst_gpio_number = GTP_RST_PORT;
himax_tpd_int_gpio_number = GTP_INT_PORT;
pdata->gpio_reset = himax_tpd_rst_gpio_number;
pdata->gpio_irq = himax_tpd_int_gpio_number;
I("%s: int : %2.2x\n", __func__, pdata->gpio_irq);
I("%s: rst : %2.2x\n", __func__, pdata->gpio_reset);
#if defined(HX_PLATFOME_DEFINE_KEY)
/* now 3 keys */
himax_vk_parser(pdata, 3);
#else
himax_vk_parser(dt, pdata);
#endif
/* Set device tree data */
/* Set panel coordinates */
pdata->abs_x_min = hx_panel_coords[0],
pdata->abs_x_max = hx_panel_coords[1];
pdata->abs_y_min = hx_panel_coords[2],
pdata->abs_y_max = hx_panel_coords[3];
I(" %s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min,
pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max);
/* Set display coordinates */
pdata->screenWidth = hx_display_coords[1];
pdata->screenHeight = hx_display_coords[3];
I(" %s:display-coords = (%d, %d)", __func__, pdata->screenWidth,
pdata->screenHeight);
/* report type */
pdata->protocol_type = report_type;
return 0;
}
#ifdef MTK_I2C_DMA
int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data,
uint8_t length, uint8_t toRetry)
{
int ret = 0;
s32 retry = 0;
u8 buffer[1];
struct i2c_msg msg[] = {
{.addr = (client->addr & I2C_MASK_FLAG),
.flags = 0,
.buf = buffer,
.len = 1,
.timing = 400},
{.addr = (client->addr & I2C_MASK_FLAG),
.ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),
.flags = I2C_M_RD,
.buf = gpDMABuf_pa,
.len = length,
.timing = 400},
};
mutex_lock(&hx_wr_access);
buffer[0] = command;
if (data == NULL) {
mutex_unlock(&hx_wr_access);
return -1;
}
for (retry = 0; retry < toRetry; ++retry) {
ret = i2c_transfer(client->adapter, &msg[0], 2);
if (ret < 0)
continue;
memcpy(data, gpDMABuf_va, length);
mutex_unlock(&hx_wr_access);
return 0;
}
E("Dma I2C Read Error: %d byte(s), err-code: %d", length, ret);
i2c_error_count = toRetry;
mutex_unlock(&hx_wr_access);
return ret;
}
int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *buf,
uint8_t len, uint8_t toRetry)
{
int rc = 0, retry = 0;
u8 *pWriteData = gpDMABuf_va;
struct i2c_msg msg[] = {
{.addr = (client->addr & I2C_MASK_FLAG),
.ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),
.flags = 0,
.buf = gpDMABuf_pa,
.len = len + 1,
.timing = 400},
};
mutex_lock(&hx_wr_access);
if (!pWriteData) {
E("dma_alloc_coherent failed!\n");
mutex_unlock(&hx_wr_access);
return -1;
}
gpDMABuf_va[0] = command;
memcpy(gpDMABuf_va + 1, buf, len);
for (retry = 0; retry < toRetry; ++retry) {
rc = i2c_transfer(client->adapter, &msg[0], 1);
if (rc < 0)
continue;
mutex_unlock(&hx_wr_access);
return 0;
}
E("Dma I2C master write Error: %d byte(s), err-code: %d", len, rc);
i2c_error_count = toRetry;
mutex_unlock(&hx_wr_access);
return rc;
}
int i2c_himax_write_command(struct i2c_client *client, uint8_t command,
uint8_t toRetry)
{
return i2c_himax_write(client, command, NULL, 0, toRetry);
}
int i2c_himax_master_write(struct i2c_client *client, uint8_t *buf, uint8_t len,
uint8_t toRetry)
{
int rc = 0, retry = 0;
u8 *pWriteData = gpDMABuf_va;
struct i2c_msg msg[] = {
{.addr = (client->addr & I2C_MASK_FLAG),
.ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG),
.flags = 0,
.buf = gpDMABuf_pa,
.len = len,
.timing = 400},
};
mutex_lock(&hx_wr_access);
if (!pWriteData) {
E("dma_alloc_coherent failed!\n");
mutex_unlock(&hx_wr_access);
return -1;
}
memcpy(gpDMABuf_va, buf, len);
for (retry = 0; retry < toRetry; ++retry) {
rc = i2c_transfer(client->adapter, &msg[0], 1);
if (rc < 0)
continue;
mutex_unlock(&hx_wr_access);
return 0;
}
E("Dma I2C master write Error: %d byte(s), err-code: %d", len, rc);
i2c_error_count = toRetry;
mutex_unlock(&hx_wr_access);
return rc;
}
#else
int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data,
uint8_t length, uint8_t toRetry)
{
int retry;
struct i2c_msg msg[] = {{
.addr = client->addr,
.flags = 0,
.len = 1,
.buf = &command,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = length,
.buf = data,
} };
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 2) == 2)
break;
msleep(20);
}
if (retry == toRetry) {
E("%s: i2c_read_block retry over %d\n", __func__, toRetry);
i2c_error_count = toRetry;
return -EIO;
}
return 0;
}
int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data,
uint8_t length, uint8_t toRetry)
{
int retry /*, loop_i*/;
uint8_t buf[length + 1];
struct i2c_msg msg[] = {{
.addr = client->addr, .flags = 0, .len = length + 1, .buf = buf,
} };
buf[0] = command;
memcpy(buf + 1, data, length);
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 1) == 1)
break;
msleep(20);
}
if (retry == toRetry) {
E("%s: i2c_write_block retry over %d\n", __func__, toRetry);
i2c_error_count = toRetry;
return -EIO;
}
return 0;
}
int i2c_himax_write_command(struct i2c_client *client, uint8_t command,
uint8_t toRetry)
{
return i2c_himax_write(client, command, NULL, 0, toRetry);
}
int i2c_himax_master_write(struct i2c_client *client, uint8_t *data,
uint8_t length, uint8_t toRetry)
{
int retry /*, loop_i*/;
uint8_t buf[length];
struct i2c_msg msg[] = {{
.addr = client->addr, .flags = 0, .len = length, .buf = buf,
} };
memcpy(buf, data, length);
for (retry = 0; retry < toRetry; retry++) {
if (i2c_transfer(client->adapter, msg, 1) == 1)
break;
msleep(20);
}
if (retry == toRetry) {
E("%s: i2c_write_block retry over %d\n", __func__, toRetry);
i2c_error_count = toRetry;
return -EIO;
}
return 0;
}
#endif
uint8_t himax_int_gpio_read(int pinnum)
{
return gpio_get_value(himax_tpd_int_gpio);
}
void himax_int_enable(int irqnum, int enable)
{
I("%s: Entering!\n", __func__);
if (enable == 1 && irq_enable_count == 0) {
enable_irq(irqnum);
irq_enable_count++;
private_ts->irq_enabled = 1;
} else if (enable == 0 && irq_enable_count == 1) {
disable_irq_nosync(irqnum);
irq_enable_count--;
private_ts->irq_enabled = 0;
}
I("irq_enable_count = %d\n", irq_enable_count);
}
#ifdef HX_RST_PIN_FUNC
void himax_rst_gpio_set(int pinnum, uint8_t value)
{
if (value)
tpd_gpio_output(himax_tpd_rst_gpio_number, 1);
else
tpd_gpio_output(himax_tpd_rst_gpio_number, 0);
}
#endif
int himax_gpio_power_config(struct i2c_client *client,
struct himax_i2c_platform_data *pdata)
{
int error = 0;
error = regulator_enable(tpd->reg);
if (error != 0)
TPD_DMESG("Failed to enable reg-vgp6: %d\n", error);
msleep(100);
#ifdef HX_RST_PIN_FUNC
tpd_gpio_output(himax_tpd_rst_gpio_number, 1);
msleep(20);
tpd_gpio_output(himax_tpd_rst_gpio_number, 0);
msleep(20);
tpd_gpio_output(himax_tpd_rst_gpio_number, 1);
#endif
TPD_DMESG("mtk_tpd: himax reset over\n");
/* set INT mode */
tpd_gpio_as_int(himax_tpd_int_gpio_number);
return 0;
}
static void himax_ts_isr_func(struct himax_ts_data *ts)
{
himax_ts_work(ts);
}
irqreturn_t himax_ts_thread(int irq, void *ptr)
{
struct himax_ts_data *ts = ptr;
if (ts->debug_log_level & BIT(2))
himax_log_touch_int_devation(HX_FINGER_ON);
himax_ts_isr_func((struct himax_ts_data *)ptr);
if (ts->debug_log_level & BIT(2))
himax_log_touch_int_devation(HX_FINGER_LEAVE);
return IRQ_HANDLED;
}
static void himax_ts_work_func(struct work_struct *work)
{
struct himax_ts_data *ts =
container_of(work, struct himax_ts_data, work);
himax_ts_work(ts);
}
int himax_int_register_trigger(struct i2c_client *client)
{
int ret = NO_ERR;
struct himax_ts_data *ts = i2c_get_clientdata(client);
if (ic_data->HX_INT_IS_EDGE) {
ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->name, ts);
} else {
ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
client->name, ts);
}
return ret;
}
int himax_int_en_set(struct i2c_client *client)
{
int ret = NO_ERR;
ret = himax_int_register_trigger(client);
return ret;
}
int himax_ts_register_interrupt(struct i2c_client *client)
{
struct himax_ts_data *ts = i2c_get_clientdata(client);
struct device_node *node = NULL;
u32 ints[2] = {0, 0};
int ret = 0;
node = of_find_matching_node(node, touch_of_match);
if (node) {
of_property_read_u32_array(node, "debounce", ints,
ARRAY_SIZE(ints));
gpio_set_debounce(ints[0], ints[1]);
himax_touch_irq = irq_of_parse_and_map(node, 0);
I("himax_touch_irq=%ud\n", himax_touch_irq);
client->irq = himax_touch_irq;
ts->client->irq = himax_touch_irq;
} else {
I("[%s] tpd request_irq can not find touch eint device node!.",
__func__);
}
ts->irq_enabled = 0;
ts->use_irq = 0;
/* Work functon */
if (client->irq) { /*INT mode*/
ts->use_irq = 1;
ret = himax_int_register_trigger(client);
if (ret == 0) {
ts->irq_enabled = 1;
irq_enable_count = 1;
I("%s: irq enabled at qpio: %d\n", __func__,
client->irq);
#ifdef HX_SMART_WAKEUP
irq_set_irq_wake(client->irq, 1);
#endif
} else {
ts->use_irq = 0;
E("%s: request_irq failed\n", __func__);
}
} else {
I("%s: client->irq is empty, use polling mode.\n", __func__);
}
if (!ts->use_irq) /*if use polling mode need to disable */
/* HX_ESD_RECOVERY function*/
{
ts->himax_wq = create_singlethread_workqueue("himax_touch");
INIT_WORK(&ts->work, himax_ts_work_func);
hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ts->timer.function = himax_ts_timer_func;
hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
I("%s: polling mode enabled\n", __func__);
}
return ret;
}
int himax_common_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
#if defined(MTK_I2C_DMA)
client->dev.coherent_dma_mask = DMA_BIT_MASK(32);
gpDMABuf_va = (u8 *)dma_alloc_coherent(
&client->dev, 4096, (dma_addr_t *)&gpDMABuf_pa, GFP_KERNEL);
if (!gpDMABuf_va) {
E("Allocate DMA I2C Buffer failed\n");
ret = -ENODEV;
goto err_alloc_MTK_DMA_failed;
}
memset(gpDMABuf_va, 0, 4096);
#endif
i2c_client_point = client;
client->addr = 0x48;
ret = himax_chip_common_probe(client, id);
#if defined(MTK_I2C_DMA)
if (ret) {
if (gpDMABuf_va) {
dma_free_coherent(&client->dev, 4096, gpDMABuf_va,
(dma_addr_t)gpDMABuf_pa);
gpDMABuf_va = NULL;
gpDMABuf_pa = NULL;
}
}
err_alloc_MTK_DMA_failed:
#endif
return ret;
}
int himax_common_remove(struct i2c_client *client)
{
int ret = 0;
himax_chip_common_remove(client);
if (gpDMABuf_va) {
dma_free_coherent(&client->dev, 4096, gpDMABuf_va,
(dma_addr_t)gpDMABuf_pa);
gpDMABuf_va = NULL;
gpDMABuf_pa = NULL;
}
return ret;
}
static void himax_common_suspend(struct device *dev)
{
struct himax_ts_data *ts = dev_get_drvdata(&i2c_client_point->dev);
I("%s: enter\n", __func__);
himax_chip_common_suspend(ts);
I("%s: END\n", __func__);
}
static void himax_common_resume(struct device *dev)
{
struct himax_ts_data *ts = dev_get_drvdata(&i2c_client_point->dev);
I("%s: enter\n", __func__);
himax_chip_common_resume(ts);
I("%s: END\n", __func__);
}
#if defined(CONFIG_FB)
int fb_notifier_callback(struct notifier_block *self, unsigned long event,
void *data)
{
struct fb_event *evdata = data;
int *blank;
struct himax_ts_data *ts =
container_of(self, struct himax_ts_data, fb_notif);
I(" %s\n", __func__);
if (evdata && evdata->data && event == FB_EVENT_BLANK && ts &&
ts->client) {
blank = evdata->data;
switch (*blank) {
case FB_BLANK_UNBLANK:
himax_common_resume(&ts->client->dev);
break;
case FB_BLANK_POWERDOWN:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_NORMAL:
himax_common_suspend(&ts->client->dev);
break;
}
}
return 0;
}
#endif
static int himax_common_detect(struct i2c_client *client,
struct i2c_board_info *info)
{
strcpy(info->type, TPD_DEVICE);
return 0;
}
static const struct i2c_device_id himax_common_ts_id[] = {
{HIMAX_common_NAME, 0}, {} };
static struct i2c_driver tpd_i2c_driver = {
.probe = himax_common_probe,
.remove = himax_common_remove,
.detect = himax_common_detect,
.driver = {
.name = HIMAX_common_NAME,
.of_match_table = of_match_ptr(himax_match_table),
},
.id_table = himax_common_ts_id,
.address_list = (const unsigned short *)forces,
};
static int himax_common_local_init(void)
{
int retval;
I("[Himax] Himax_ts I2C Touchscreen Driver local init\n");
tpd->reg = regulator_get(tpd->tpd_dev, "vtouch");
retval = regulator_set_voltage(tpd->reg, 2800000, 2800000);
if (retval != 0)
E("Failed to set voltage 2V8: %d\n", retval);
if (i2c_add_driver(&tpd_i2c_driver) != 0) {
I("unable to add i2c driver.\n");
return -1;
}
/* input_set_abs_params(tpd->input_dev, ABS_MT_TRACKING_ID, 0, */
/* (HIMAX_MAX_TOUCH-1), 0, 0); */
/* set vendor string */
/* client->input_devid.vendor = 0x00; */
/* client->input_dev->id.product = tpd_info.pid; */
/* client-->input_dev->id.version = tpd_info.vid; */
#if defined(HX_PLATFOME_DEFINE_KEY)
if (tpd_dts_data.use_tpd_button) {
I("tpd_dts_data.use_tpd_button %d\n",
tpd_dts_data.use_tpd_button);
tpd_button_setting(tpd_dts_data.tpd_key_num,
tpd_dts_data.tpd_key_local,
tpd_dts_data.tpd_key_dim_local);
}
#endif
I("end %s, %d\n", __func__, __LINE__);
tpd_type_cap = 1;
return 0;
}
static struct tpd_driver_t tpd_device_driver = {
.tpd_device_name = HIMAX_common_NAME,
.tpd_local_init = himax_common_local_init,
.suspend = himax_common_suspend,
.resume = himax_common_resume,
#ifdef TPD_HAVE_BUTTON
.tpd_have_button = 1,
#else
.tpd_have_button = 0,
#endif
};
static int __init himax_common_init(void)
{
I("Himax_common touch panel driver init\n");
tpd_get_dts_info();
if (tpd_driver_add(&tpd_device_driver) < 0)
E("Failed to add Driver!\n");
return 0;
}
static void __exit himax_common_exit(void)
{
tpd_driver_remove(&tpd_device_driver);
}
module_init(himax_common_init);
module_exit(himax_common_exit);
MODULE_DESCRIPTION("Himax_common driver");
MODULE_LICENSE("GPL");