blob: bc927f87e3e1f345d2105308f4b9787f995c3750 [file] [log] [blame]
/*
* Himax Android Driver Sample Code for HX83112 chipset
*
* Copyright (C) 2018 Himax Corporation.
*
* 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 "himax_ic_HX83112.h"
extern unsigned char IC_TYPE;
static bool hx83112_sense_off(void)
{
uint8_t cnt = 0;
uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
do {
/*
*===========================================
* I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27
*===========================================
*/
tmp_data[0] = pic_op->data_i2c_psw_lb[0];
if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
/*
*===========================================
* I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95
*===========================================
*/
tmp_data[0] = pic_op->data_i2c_psw_ub[0];
if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
/*
*===========================================
* I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x00
*===========================================
*/
tmp_data[0] = 0x00;
if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
/*
*==========================================
* I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27
*===========================================
*/
tmp_data[0] = pic_op->data_i2c_psw_lb[0];
if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
/*
*==========================================
* I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95
*==========================================
*/
tmp_data[0] = pic_op->data_i2c_psw_ub[0];
if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
/*
*=====================
* Check enter_save_mode
*=====================
*/
g_core_fp.fp_register_read(pic_op->addr_cs_central_state, FOUR_BYTE_ADDR_SZ, tmp_data, 0);
D("%s: Check enter_save_mode data[0]=%X\n",
__func__, tmp_data[0]);
if (tmp_data[0] == 0x0C) {
/*
*===================================
* Reset TCON
*====================================
*/
g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, pic_op->data_rst);
msleep(20);
tmp_data[3] = pic_op->data_rst[3];
tmp_data[2] = pic_op->data_rst[2];
tmp_data[1] = pic_op->data_rst[1];
tmp_data[0] = pic_op->data_rst[0] | 0x01;
g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, tmp_data);
/*
*===================================
* Reset ADC
*====================================
*/
g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, pic_op->data_rst);
msleep(20);
tmp_data[3] = pic_op->data_rst[3];
tmp_data[2] = pic_op->data_rst[2];
tmp_data[1] = pic_op->data_rst[1];
tmp_data[0] = pic_op->data_rst[0] | 0x01;
g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, tmp_data);
return true;
}
msleep(20);
#ifdef HX_RST_PIN_FUNC
g_core_fp.fp_ic_reset(false, false);
#endif
} while (cnt++ < 15);
return false;
}
static void hx83112_func_re_init(void)
{
g_core_fp.fp_sense_off = hx83112_sense_off;
}
static void hx83112_reg_re_init(void)
{
}
static bool hx83112_chip_detect(void)
{
uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
bool ret_data = false;
int i = 0;
himax_mcu_in_cmd_struct_init();
himax_mcu_in_cmd_init();
hx83112_reg_re_init();
hx83112_func_re_init();
g_core_fp.fp_sense_off();
for (i = 0; i < 5; i++) {
g_core_fp.fp_register_read(pfw_op->addr_icid_addr, FOUR_BYTE_DATA_SZ, tmp_data, false);
I("%s:Read driver IC ID = %X, %X, %X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1]);
if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x11) && ((tmp_data[1] == 0x2a) || (tmp_data[1] == 0x2b))) {
if (tmp_data[1] == 0x2a)
strlcpy(private_ts->chip_name, HX_83112A_SERIES_PWON, 30);
else if (tmp_data[1] == 0x2b)
strlcpy(private_ts->chip_name, HX_83112B_SERIES_PWON, 30);
I("%s:IC name = %s\n", __func__, private_ts->chip_name);
D("Himax IC package %x%x%x in\n",
tmp_data[3], tmp_data[2], tmp_data[1]);
ret_data = true;
break;
}
ret_data = false;
E("%s:Read driver ID register Fail:\n", __func__);
}
return ret_data;
}
static void hx83112_chip_init(void)
{
private_ts->chip_cell_type = CHIP_IS_IN_CELL;
D("%s:IC cell type = %d\n", __func__, private_ts->chip_cell_type);
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
}
#ifdef CONFIG_CHIP_DTCFG
static int himax_hx83112_probe(struct platform_device *pdev)
{
D("%s:Enter\n", __func__);
g_core_fp.fp_chip_detect = hx83112_chip_detect;
g_core_fp.fp_chip_init = hx83112_chip_init;
return 0;
}
static int himax_hx83112_remove(struct platform_device *pdev)
{
g_core_fp.fp_chip_detect = NULL;
g_core_fp.fp_chip_init = NULL;
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id himax_hx83112_mttable[] = {
{ .compatible = "himax,hx83112"},
{ },
};
#else
#define himax_hx83112_mttabl NULL
#endif
static struct platform_driver himax_hx83112_driver = {
.probe = himax_hx83112_probe,
.remove = himax_hx83112_remove,
.driver = {
.name = "HIMAX_HX83112",
.owner = THIS_MODULE,
.of_match_table = himax_hx83112_mttable,
},
};
static int __init himax_hx83112_init(void)
{
D("%s\n", __func__);
platform_driver_register(&himax_hx83112_driver);
return 0;
}
static void __exit himax_hx83112_exit(void)
{
platform_driver_unregister(&himax_hx83112_driver);
}
#else
static int himax_hx83112_probe(void)
{
D("%s:Enter\n", __func__);
g_core_fp.fp_chip_detect = hx83112_chip_detect;
g_core_fp.fp_chip_init = hx83112_chip_init;
return 0;
}
static int himax_hx83112_remove(void)
{
g_core_fp.fp_chip_detect = NULL;
g_core_fp.fp_chip_init = NULL;
return 0;
}
static int __init himax_hx83112_init(void)
{
int ret = 0;
D("%s\n", __func__);
ret = himax_hx83112_probe();
return 0;
}
static void __exit himax_hx83112_exit(void)
{
himax_hx83112_remove();
}
#endif
module_init(himax_hx83112_init);
module_exit(himax_hx83112_exit);
MODULE_DESCRIPTION("HIMAX HX83112 touch driver");
MODULE_LICENSE("GPL v2");