/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include "himax_ic.h" static int iref_number = 11; static bool iref_found; #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) uint8_t test_counter; uint8_t TEST_DATA_TIMES = 3; #endif /* 1uA */ static unsigned char E_IrefTable_1[16][2] = { {0x20, 0x0F}, {0x20, 0x1F}, {0x20, 0x2F}, {0x20, 0x3F}, {0x20, 0x4F}, {0x20, 0x5F}, {0x20, 0x6F}, {0x20, 0x7F}, {0x20, 0x8F}, {0x20, 0x9F}, {0x20, 0xAF}, {0x20, 0xBF}, {0x20, 0xCF}, {0x20, 0xDF}, {0x20, 0xEF}, {0x20, 0xFF} }; /* 2uA */ static unsigned char E_IrefTable_2[16][2] = { {0xA0, 0x0E}, {0xA0, 0x1E}, {0xA0, 0x2E}, {0xA0, 0x3E}, {0xA0, 0x4E}, {0xA0, 0x5E}, {0xA0, 0x6E}, {0xA0, 0x7E}, {0xA0, 0x8E}, {0xA0, 0x9E}, {0xA0, 0xAE}, {0xA0, 0xBE}, {0xA0, 0xCE}, {0xA0, 0xDE}, {0xA0, 0xEE}, {0xA0, 0xFE} }; /* 3uA */ static unsigned char E_IrefTable_3[16][2] = { {0x20, 0x0E}, {0x20, 0x1E}, {0x20, 0x2E}, {0x20, 0x3E}, {0x20, 0x4E}, {0x20, 0x5E}, {0x20, 0x6E}, {0x20, 0x7E}, {0x20, 0x8E}, {0x20, 0x9E}, {0x20, 0xAE}, {0x20, 0xBE}, {0x20, 0xCE}, {0x20, 0xDE}, {0x20, 0xEE}, {0x20, 0xFE} }; /* 4uA */ static unsigned char E_IrefTable_4[16][2] = { {0xA0, 0x0D}, {0xA0, 0x1D}, {0xA0, 0x2D}, {0xA0, 0x3D}, {0xA0, 0x4D}, {0xA0, 0x5D}, {0xA0, 0x6D}, {0xA0, 0x7D}, {0xA0, 0x8D}, {0xA0, 0x9D}, {0xA0, 0xAD}, {0xA0, 0xBD}, {0xA0, 0xCD}, {0xA0, 0xDD}, {0xA0, 0xED}, {0xA0, 0xFD} }; /* 5uA */ static unsigned char E_IrefTable_5[16][2] = { {0x20, 0x0D}, {0x20, 0x1D}, {0x20, 0x2D}, {0x20, 0x3D}, {0x20, 0x4D}, {0x20, 0x5D}, {0x20, 0x6D}, {0x20, 0x7D}, {0x20, 0x8D}, {0x20, 0x9D}, {0x20, 0xAD}, {0x20, 0xBD}, {0x20, 0xCD}, {0x20, 0xDD}, {0x20, 0xED}, {0x20, 0xFD} }; /* 6uA */ static unsigned char E_IrefTable_6[16][2] = { {0xA0, 0x0C}, {0xA0, 0x1C}, {0xA0, 0x2C}, {0xA0, 0x3C}, {0xA0, 0x4C}, {0xA0, 0x5C}, {0xA0, 0x6C}, {0xA0, 0x7C}, {0xA0, 0x8C}, {0xA0, 0x9C}, {0xA0, 0xAC}, {0xA0, 0xBC}, {0xA0, 0xCC}, {0xA0, 0xDC}, {0xA0, 0xEC}, {0xA0, 0xFC} }; /* 7uA */ static unsigned char E_IrefTable_7[16][2] = { {0x20, 0x0C}, {0x20, 0x1C}, {0x20, 0x2C}, {0x20, 0x3C}, {0x20, 0x4C}, {0x20, 0x5C}, {0x20, 0x6C}, {0x20, 0x7C}, {0x20, 0x8C}, {0x20, 0x9C}, {0x20, 0xAC}, {0x20, 0xBC}, {0x20, 0xCC}, {0x20, 0xDC}, {0x20, 0xEC}, {0x20, 0xFC} }; #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) static int Selftest_flag; uint16_t *mutual_bank; uint16_t *self_bank; bool raw_data_chk_arr[20] = {false}; #endif #ifdef HX_TP_PROC_2T2R bool Is_2T2R; int HX_2T2R_Addr = 0x96; /* Need to check with project FW eng. */ int HX_2T2R_en_setting = 0x02; /* Need to check with project FW eng. */ #endif #if defined(HX_ESD_RECOVERY) u8 ESD_R36_FAIL; #endif uint8_t IC_STATUS_CHECK = 0xAA; int himax_touch_data_size = 128; int himax_get_touch_data_size(void) { return himax_touch_data_size; } #ifdef HX_RST_PIN_FUNC void himax_pin_reset(void) { I("%s: Now reset the Touch chip.\n", __func__); himax_rst_gpio_set(private_ts->rst_gpio, 0); msleep(20); himax_rst_gpio_set(private_ts->rst_gpio, 1); msleep(20); } void himax_reload_config(void) { himax_loadSensorConfig(private_ts->client, private_ts->pdata); himax_power_on_init(private_ts->client); if (himax_report_data_init()) E("%s: allocate data fail\n", __func__); ; calculate_point_number(); } void himax_irq_switch(int switch_on) { int ret = 0; if (switch_on) { if (private_ts->use_irq) himax_int_enable(private_ts->client->irq, switch_on); else hrtimer_start(&private_ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); } else { if (private_ts->use_irq) himax_int_enable(private_ts->client->irq, switch_on); else { hrtimer_cancel(&private_ts->timer); ret = cancel_work_sync(&private_ts->work); } } } void himax_ic_reset(uint8_t loadconfig, uint8_t int_off) { struct himax_ts_data *ts = private_ts; HX_HW_RESET_ACTIVATE = 1; I("%s,status: loadconfig=%d,int_off=%d\n", __func__, loadconfig, int_off); if (ts->rst_gpio >= 0) { if (int_off) himax_irq_switch(0); himax_pin_reset(); if (loadconfig) himax_reload_config(); if (int_off) himax_irq_switch(1); } } #endif #if defined(HX_ESD_RECOVERY) int g_zero_event_count; int himax_ic_esd_recovery(int hx_esd_event, int hx_zero_event, int length) { int shaking_ret = 0; /* hand shaking status: 0:Running, 1:Stop, 2:I2C Fail */ shaking_ret = himax_hand_shaking(private_ts->client); if (shaking_ret == 2) { I("[HIMAX TP MSG]: I2C Fail.\n"); goto err_workqueue_out; } if (hx_esd_event == length) { goto checksum_fail; } else if (shaking_ret == 1 && hx_zero_event == length) { I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); goto checksum_fail; } else goto workqueue_out; checksum_fail: return CHECKSUM_FAIL; err_workqueue_out: return ERR_WORK_OUT; workqueue_out: return WORK_OUT; } void himax_esd_ic_reset(void) { uint8_t read_R36[2] = {0}; while (ESD_R36_FAIL <= 3) { HX_ESD_RESET_ACTIVATE = 1; #ifdef HX_RST_PIN_FUNC himax_pin_reset(); #endif if (himax_loadSensorConfig(private_ts->client, private_ts->pdata) < 0) { ESD_R36_FAIL++; continue; } if (i2c_himax_read(private_ts->client, 0x36, read_R36, 2, 10) < 0) { ESD_R36_FAIL++; continue; } if (read_R36[0] != 0x0F || read_R36[1] != 0x53) { E("%s R36 Fail : R36[0]=%d,R36[1]=%d,R36 Counter=%d\n", __func__, read_R36[0], read_R36[1], ESD_R36_FAIL); ESD_R36_FAIL++; } else { himax_power_on_init(private_ts->client); if (himax_report_data_init()) E("%s: allocate data fail\n", __func__); ; calculate_point_number(); break; } } /* reset status */ ESD_R36_FAIL = 0; } #endif int himax_hand_shaking( struct i2c_client *client) /* 0:Running, 1:Stop, 2:I2C Fail */ { int ret, result; uint8_t hw_reset_check[1]; uint8_t hw_reset_check_2[1]; uint8_t buf0[2]; memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2)); buf0[0] = 0xF2; if (IC_STATUS_CHECK == 0xAA) { buf0[1] = 0xAA; IC_STATUS_CHECK = 0x55; } else { buf0[1] = 0x55; IC_STATUS_CHECK = 0xAA; } ret = i2c_himax_master_write(client, buf0, 2, DEFAULT_RETRY_CNT); if (ret < 0) { E("[Himax]:write 0xF2 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } msleep(50); buf0[0] = 0xF2; buf0[1] = 0x00; ret = i2c_himax_master_write(client, buf0, 2, DEFAULT_RETRY_CNT); if (ret < 0) { E("[Himax]:write 0x92 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } msleep(20); ret = i2c_himax_read(client, 0x90, hw_reset_check, 1, DEFAULT_RETRY_CNT); if (ret < 0) { E("[Himax]:i2c_himax_read 0x90 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } if (hw_reset_check[0] != IC_STATUS_CHECK) { msleep(20); ret = i2c_himax_read(client, 0x90, hw_reset_check_2, 1, DEFAULT_RETRY_CNT); if (ret < 0) { E("[Himax]:i2c_himax_read 0x90 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } if (hw_reset_check[0] == hw_reset_check_2[0]) result = 1; else result = 0; } else { result = 0; } return result; work_func_send_i2c_msg_fail: return 2; } void himax_idle_mode(struct i2c_client *client, int disable) { } int himax_determin_diag_rawdata(int diag_command) { return (diag_command / 10 > 0) ? 0 : diag_command % 10; } int himax_determin_diag_storage(int diag_command) { return 0; } int himax_switch_mode(struct i2c_client *client, int mode) { return 1; } void himax_return_event_stack(struct i2c_client *client) { } void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command) { uint8_t command_F1h[2] = {0xF1, 0x00}; /* diag_command = diag_command - '0'; */ if (diag_command > 8) { E("[Himax]Diag command error!diag_command=0x%x\n", diag_command); return; } command_F1h[1] = diag_command; i2c_himax_write(client, command_F1h[0], &command_F1h[1], 1, DEFAULT_RETRY_CNT); } void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer) { int i = 0, j = 0, k = 0, l = 0; int buffer_ptr = 0; uint8_t x81_command[2] = {HX_CMD_TSSLPOUT, 0x00}; uint8_t x82_command[2] = {HX_CMD_TSSOFF, 0x00}; uint8_t x43_command[4] = {HX_CMD_FLASH_ENABLE, 0x00, 0x00, 0x00}; uint8_t x44_command[4] = {HX_CMD_FLASH_SET_ADDRESS, 0x00, 0x00, 0x00}; uint8_t x59_tmp[4] = {0, 0, 0, 0}; uint8_t page_tmp[128]; himax_int_enable(client->irq, 0); #ifdef HX_CHIP_STATUS_MONITOR g_chip_monitor_data->HX_CHIP_POLLING_COUNT = 0; g_chip_monitor_data->HX_CHIP_MONITOR_EN = 0; cancel_delayed_work_sync(&private_ts->himax_chip_monitor); #endif setFlashDumpGoing(true); local_flash_command = getFlashCommand(); #ifdef HX_RST_PIN_FUNC himax_ic_reset(false, false); #endif if (i2c_himax_master_write(client, x81_command, 1, 3) < 0) { /* sleep out */ E("%s i2c write 81 fail.\n", __func__); goto Flash_Dump_i2c_transfer_error; } msleep(120); if (i2c_himax_master_write(client, x82_command, 1, 3) < 0) { E("%s i2c write 82 fail.\n", __func__); goto Flash_Dump_i2c_transfer_error; } msleep(100); x43_command[1] = 0x01; if (i2c_himax_write(client, x43_command[0], &x43_command[1], 1, DEFAULT_RETRY_CNT) < 0) { goto Flash_Dump_i2c_transfer_error; } msleep(100); for (i = 0; i < 8; i++) { for (j = 0; j < 32; j++) { /* I(" Step 2 i=%d , j=%d %s\n",i,j,__func__); */ /* read page start */ for (k = 0; k < 128; k++) page_tmp[k] = 0x00; for (k = 0; k < 32; k++) { x44_command[1] = k; x44_command[2] = j; x44_command[3] = i; if (i2c_himax_write(client, x44_command[0], &x44_command[1], 3, DEFAULT_RETRY_CNT) < 0) { E("%s i2c write 44 fail.\n", __func__); goto Flash_Dump_i2c_transfer_error; } if (i2c_himax_write_command(client, 0x46, DEFAULT_RETRY_CNT) < 0) { E("%s i2c write 46 fail.\n", __func__); goto Flash_Dump_i2c_transfer_error; } /* msleep(20); */ if (i2c_himax_read(client, 0x59, x59_tmp, 4, DEFAULT_RETRY_CNT) < 0) { E("%s i2c write 59 fail.\n", __func__); goto Flash_Dump_i2c_transfer_error; } /* msleep(20); */ for (l = 0; l < 4; l++) page_tmp[k * 4 + l] = x59_tmp[l]; /* msleep(20); */ } /* read page end */ for (k = 0; k < 128; k++) flash_buffer[buffer_ptr++] = page_tmp[k]; setFlashDumpProgress(i * 32 + j); } } I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n"); if (local_flash_command == 0x01) { I(" buffer_ptr = %d\n", buffer_ptr); for (i = 0; i < buffer_ptr; i++) { I("%2.2X ", flash_buffer[i]); if ((i % 16) == 15) I("\n"); } I("End~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); } else if (local_flash_command == 2) { struct file *fn; fn = filp_open(FLASH_DUMP_FILE, O_CREAT | O_WRONLY, 0); if (!IS_ERR(fn)) { fn->f_op->write(fn, flash_buffer, buffer_ptr * sizeof(uint8_t), &fn->f_pos); filp_close(fn, NULL); } } #ifdef HX_RST_PIN_FUNC himax_ic_reset(true, false); #endif himax_int_enable(client->irq, 1); #ifdef HX_CHIP_STATUS_MONITOR g_chip_monitor_data->HX_CHIP_POLLING_COUNT = 0; g_chip_monitor_data->HX_CHIP_MONITOR_EN = 1; queue_delayed_work(private_ts->himax_chip_monitor_wq, &private_ts->himax_chip_monitor, g_chip_monitor_data->HX_POLLING_TIMES * HZ); #endif setFlashDumpGoing(false); setFlashDumpComplete(1); setSysOperation(0); return; Flash_Dump_i2c_transfer_error: #ifdef HX_RST_PIN_FUNC himax_ic_reset(true, false); #endif himax_int_enable(client->irq, 1); #ifdef HX_CHIP_STATUS_MONITOR g_chip_monitor_data->HX_CHIP_POLLING_COUNT = 0; g_chip_monitor_data->HX_CHIP_MONITOR_EN = 1; queue_delayed_work(private_ts->himax_chip_monitor_wq, &private_ts->himax_chip_monitor, g_chip_monitor_data->HX_POLLING_TIMES * HZ); #endif setFlashDumpGoing(false); setFlashDumpComplete(0); setFlashDumpFail(1); setSysOperation(0); } #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) void himax_get_raw_data(uint8_t diag_command, uint16_t mutual_num, uint16_t self_num) { uint8_t command_F1h_bank[2] = {0xF1, diag_command}; int i = 0; I("Start get raw data\n"); memset(mutual_bank, 0xFF, mutual_num * sizeof(uint16_t)); memset(self_bank, 0xFF, self_num * sizeof(uint16_t)); Selftest_flag = 1; I(" mutual_num = %d, self_num = %d\n", mutual_num, self_num); I(" Selftest_flag = %d\n", Selftest_flag); i2c_himax_write(private_ts->client, command_F1h_bank[0], &command_F1h_bank[1], 1, DEFAULT_RETRY_CNT); msleep(100); himax_int_enable(private_ts->client->irq, 1); for (i = 0; i < 100; i++) { /* check for max 1000 times */ I(" conuter = %d ,Selftest_flag = %d\n", i, Selftest_flag); if (Selftest_flag == 0) break; msleep(20); } himax_int_enable(private_ts->client->irq, 0); I(" Write diag cmd = %d\n", command_F1h_bank[1]); } #endif #ifdef HX_TP_SELF_TEST_DRIVER static uint8_t Self_Test_Bank(uint8_t *RB1H) { uint8_t i; uint8_t x_channel = 0; uint8_t y_channel = 0; uint16_t mutual_num = 0; uint16_t self_num = 0; uint32_t bank_sum, m; uint8_t bank_avg; uint8_t bank_ulmt, bank_dlmt; uint8_t bank_min, bank_max; uint8_t slf_tx_fail_cnt, slf_rx_fail_cnt; uint8_t mut_fail_cnt; int fail_flag; uint8_t bank_val_tmp; uint8_t set_bnk_ulmt; uint8_t set_bnk_dlmt; uint8_t set_avg_bnk_ulmt; uint8_t set_avg_bnk_dlmt; uint8_t set_slf_bnk_ulmt; uint8_t set_slf_bnk_dlmt; I("Start self_test\n"); x_channel = ic_data->HX_RX_NUM; y_channel = ic_data->HX_TX_NUM; mutual_num = x_channel * y_channel; self_num = x_channel + y_channel; /* don't add KEY_COUNT */ mutual_bank = kcalloc(mutual_num, sizeof(uint16_t), GFP_KERNEL); self_bank = kcalloc(self_num, sizeof(uint16_t), GFP_KERNEL); himax_get_raw_data(0x03, mutual_num, self_num); /* get bank data */ if (RB1H[0] == 0x80) { I(" Enter Test flow\n"); set_bnk_ulmt = RB1H[2]; set_bnk_dlmt = RB1H[3]; set_avg_bnk_ulmt = RB1H[4]; set_avg_bnk_dlmt = RB1H[5]; set_slf_bnk_ulmt = RB1H[6]; /* Increase @ 2012/05/24 for weak open/short */ set_slf_bnk_dlmt = RB1H[7]; fail_flag = 0; bank_sum = 0; bank_avg = 0; mut_fail_cnt = 0; /* Calculate Bank Average */ for (m = 0; m < mutual_num; m++) bank_sum += mutual_bank[m]; I(" bank_sum = %d\n", bank_sum); bank_avg = (bank_sum / mutual_num); I(" bank_avg = %d\n", bank_avg); /* ======Condition 1======Check average bank with absolute value */ if ((bank_avg > set_avg_bnk_ulmt) || (bank_avg < set_avg_bnk_dlmt)) fail_flag = 1; I(" fail_flag = %d\n", fail_flag); if (fail_flag) { RB1H[0] = 0xF1; /* Fail ID for Condition 1 */ RB1H[1] = bank_avg; RB1H[2] = set_avg_bnk_ulmt; RB1H[3] = set_avg_bnk_dlmt; RB1H[4] = 0xFF; for (i = 0; i < 8; i++) I(" RB1H[%d] = %X\n", i, RB1H[i]); } else { /* ======Condition 2======Check every block's bank with average value */ #if 1 /* def SLF_TEST_BANK_ABS_LMT */ bank_ulmt = set_bnk_ulmt; bank_dlmt = set_bnk_dlmt; #else if ((bank_avg + set_bnk_ulmt) > 245) bank_ulmt = 245; else bank_ulmt = bank_avg + set_bnk_ulmt; if (bank_avg > set_bnk_dlmt) { bank_dlmt = bank_avg - set_bnk_dlmt; if (bank_dlmt < 10) bank_dlmt = 10; } else bank_dlmt = 10; #endif bank_min = 0xFF; bank_max = 0x00; I(" bank_ulmt = %d, bank_dlmt = %d\n", bank_ulmt, bank_dlmt); for (m = 0; m < mutual_num; m++) { bank_val_tmp = mutual_bank[m]; if ((bank_val_tmp > bank_ulmt) || (bank_val_tmp < bank_dlmt)) { fail_flag = 1; mut_fail_cnt++; } /* Bank information record */ if (bank_val_tmp > bank_max) bank_max = bank_val_tmp; else if (bank_val_tmp < bank_min) bank_min = bank_val_tmp; } I(" fail_flag = %d, mut_fail_cnt = %d\n", fail_flag, mut_fail_cnt); if (fail_flag) { RB1H[0] = 0xF2; /* Fail ID for Condition 2 */ RB1H[1] = mut_fail_cnt; RB1H[2] = bank_avg; RB1H[3] = bank_max; RB1H[4] = bank_min; RB1H[5] = bank_ulmt; RB1H[6] = bank_dlmt; RB1H[7] = 0xFF; for (i = 0; i < 8; i++) I(" RB1H[%d] = %X\n", i, RB1H[i]); for (m = 0; m < mutual_num; m++) { I(" mutual_bank[%d] = %X\n", m, mutual_bank[m]); } for (m = 0; m < self_num; m++) { I(" self_bank[%d] = %X\n", m, self_bank[m]); } } else { /* ======Condition 3======Check every self */ /* channel bank */ slf_rx_fail_cnt = 0x00; /* Check SELF RX BANK */ slf_tx_fail_cnt = 0x00; /* Check SELF TX BANK */ for (i = 0; i < (x_channel + y_channel); i++) { bank_val_tmp = self_bank[i]; if ((i < x_channel) && (bank_val_tmp > set_slf_bnk_ulmt) || (bank_val_tmp < set_slf_bnk_dlmt)) { fail_flag = 1; slf_rx_fail_cnt++; } if ((i >= x_channel) && (bank_val_tmp > set_slf_bnk_ulmt) || (bank_val_tmp < set_slf_bnk_dlmt)) { fail_flag = 1; slf_tx_fail_cnt++; } } I(" rx_fail_cnt = %d, tx_fail_cnt = %d\n", slf_rx_fail_cnt, slf_tx_fail_cnt); if (fail_flag) { RB1H [0] = 0xF3; /* Fail ID for Condition 3 */ RB1H[1] = slf_rx_fail_cnt; RB1H[2] = slf_tx_fail_cnt; RB1H[3] = set_slf_bnk_ulmt; RB1H[4] = set_slf_bnk_dlmt; RB1H[5] = 0xFF; for (i = 0; i < 8; i++) { I(" RB1H[%d] = %X\n", i, RB1H[i]); } for (m = 0; m < mutual_num; m++) { I(" mutual_bank[%d] = %X\n", m, mutual_bank[m]); } for (m = 0; m < self_num; m++) { I(" self_bank[%d] = %X\n", m, self_bank[m]); } } else { RB1H[0] = 0xAA; /* //PASS ID */ RB1H[1] = bank_avg; RB1H[2] = bank_max; RB1H[3] = bank_min; } } } } kfree(mutual_bank); kfree(self_bank); return RB1H[0]; } #endif int himax_chip_self_test(struct i2c_client *client) { uint8_t cmdbuf[11]; uint8_t valuebuf[16]; int pf_value = 0x00; int retry_times = 3; int retry_readB1 = 10; #ifdef HX_TP_SELF_TEST_DRIVER uint8_t RB1H[8]; #else int i = 0; #endif test_retry: memset(cmdbuf, 0x00, sizeof(cmdbuf)); memset(valuebuf, 0x00, sizeof(valuebuf)); #ifdef HX_TP_SELF_TEST_DRIVER memset(RB1H, 0x00, sizeof(RB1H)); Selftest_flag = 1; g_diag_command = 0x03; himax_int_enable(client->irq, 1); /* Get Criteria */ i2c_himax_read(client, 0xB1, RB1H, 8, DEFAULT_RETRY_CNT); msleep(20); I("[Himax]: self-test RB1H[0]=%x\n", RB1H[0]); RB1H[0] = RB1H[0] | 0x80; I("[Himax]: disable reK RB1H[0]=%x\n", RB1H[0]); i2c_himax_write(client, 0xB1, &RB1H[0], 1, DEFAULT_RETRY_CNT); msleep(20); #else cmdbuf[0] = 0x06; i2c_himax_write(client, 0xF1, &cmdbuf[0], 1, DEFAULT_RETRY_CNT); msleep(120); #endif i2c_himax_write(client, HX_CMD_TSSON, &cmdbuf[0], 0, DEFAULT_RETRY_CNT); msleep(120); i2c_himax_write(client, HX_CMD_TSSLPOUT, &cmdbuf[0], 0, DEFAULT_RETRY_CNT); #ifdef HX_TP_SELF_TEST_DRIVER msleep(120); valuebuf[0] = Self_Test_Bank(&RB1H[0]); #else memset(valuebuf, 0x00, sizeof(valuebuf)); msleep(2000); #endif while (valuebuf[0] == 0x00 && retry_readB1 > 0) { i2c_himax_read(client, 0xB1, valuebuf, 2, DEFAULT_RETRY_CNT); msleep(100); retry_readB1--; } i2c_himax_write(client, HX_CMD_TSSOFF, &cmdbuf[0], 0, DEFAULT_RETRY_CNT); msleep(120); i2c_himax_write(client, HX_CMD_TSSLPIN, &cmdbuf[0], 0, DEFAULT_RETRY_CNT); msleep(120); #ifdef HX_TP_SELF_TEST_DRIVER himax_int_enable(client->irq, 0); g_diag_command = 0x00; Selftest_flag = 0; RB1H[0] = 0x00; I("[Himax]: enable reK RB1H[0]=%x\n", RB1H[0]); i2c_himax_write(client, 0xB1, &RB1H[0], 1, DEFAULT_RETRY_CNT); #else cmdbuf[0] = 0x00; i2c_himax_write(client, 0xF1, &cmdbuf[0], 1, DEFAULT_RETRY_CNT); msleep(120); i2c_himax_read(client, 0xB1, valuebuf, 8, DEFAULT_RETRY_CNT); msleep(20); for (i = 0; i < 8; i++) { I("[Himax]: After slf test 0xB1 buff_back[%d] = 0x%x\n", i, valuebuf[i]); } msleep(30); #endif if (valuebuf[0] == 0xAA) { I("[Himax]: self-test pass\n"); pf_value = 0x1; } else { E("[Himax]: self-test fail : 0x%x\n", valuebuf[0]); if (retry_times > 0) { retry_times--; goto test_retry; } pf_value = 0x0; } return pf_value; } void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable, bool suspended) { uint8_t buf[4]; i2c_himax_read(client, 0x8F, buf, 1, DEFAULT_RETRY_CNT); if (HSEN_enable == 1 && !suspended) buf[0] |= 0x40; else buf[0] &= 0xBF; if (i2c_himax_write(client, 0x8F, buf, 1, DEFAULT_RETRY_CNT) < 0) E("%s i2c write fail.\n", __func__); } int himax_palm_detect(uint8_t *buf) { int loop_i = 0; int base = 0; int x = 0; int y = 0; int w = 0; loop_i = 0; base = loop_i * 4; x = buf[base] << 8 | buf[base + 1]; y = (buf[base + 2] << 8 | buf[base + 3]); w = buf[(private_ts->nFinger_support * 4) + loop_i]; I(" %s HX_PALM_REPORT_loopi=%d,base=%x,X=%x,Y=%x,W=%x\n", __func__, loop_i, base, x, y, w); if ((!atomic_read(&private_ts->suspend_mode)) && (x == 0xFA5A) && (y == 0xFA5A) && (w == 0x00)) { return NO_ERR; } else { return GESTURE_DETECT_FAIL; } } void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable, bool suspended) { uint8_t buf[4]; i2c_himax_read(client, 0x8F, buf, 1, DEFAULT_RETRY_CNT); if (SMWP_enable == 1 && suspended) buf[0] |= 0x20; else buf[0] &= 0xDF; if (i2c_himax_write(client, 0x8F, buf, 1, DEFAULT_RETRY_CNT) < 0) E("%s i2c write fail.\n", __func__); } void himax_usb_detect_set(struct i2c_client *client, uint8_t *cable_config) { uint8_t tmp_data[4]; uint8_t retry_cnt = 0; do { i2c_himax_master_write(client, cable_config, 2, DEFAULT_RETRY_CNT); i2c_himax_read(client, cable_config[0], tmp_data, 1, DEFAULT_RETRY_CNT); /* I("%s: tmp_data[0]=%d, retry_cnt=%d\n", __func__, */ /* tmp_data[0],retry_cnt); */ retry_cnt++; } while (tmp_data[0] != cable_config[1] && retry_cnt < HIMAX_REG_RETRY_TIMES); } void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data, bool cfg_flag) { uint8_t outData[4]; if (cfg_flag) { outData[0] = 0x14; i2c_himax_write(client, 0x8C, &outData[0], 1, DEFAULT_RETRY_CNT); msleep(20); outData[0] = 0x00; outData[1] = read_addr[0]; i2c_himax_write(client, 0x8B, &outData[0], 2, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_read(client, 0x5A, read_data, read_length, DEFAULT_RETRY_CNT); msleep(20); outData[0] = 0x00; i2c_himax_write(client, 0x8C, &outData[0], 1, DEFAULT_RETRY_CNT); } else { i2c_himax_read(client, read_addr[0], read_data, read_length, DEFAULT_RETRY_CNT); } } void himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data, bool cfg_flag) { uint8_t outData[4]; if (cfg_flag) { outData[0] = 0x14; i2c_himax_write(client, 0x8C, &outData[0], 1, DEFAULT_RETRY_CNT); msleep(20); outData[0] = 0x00; outData[1] = write_addr[0]; i2c_himax_write(client, 0x8B, &outData[0], 2, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_write(client, 0x40, &write_data[0], write_length, DEFAULT_RETRY_CNT); msleep(20); outData[0] = 0x00; i2c_himax_write(client, 0x8C, &outData[0], 1, DEFAULT_RETRY_CNT); I("CMD: FE(%x), %x, %d\n", write_addr[0], write_data[0], write_length); } else { i2c_himax_write(client, write_addr[0], &write_data[0], write_length, DEFAULT_RETRY_CNT); } } void himax_interface_on(struct i2c_client *client) { } bool wait_wip(struct i2c_client *client, int Timing) { return true; } void himax_sense_off(struct i2c_client *client) { i2c_himax_write_command(client, HX_CMD_TSSOFF, DEFAULT_RETRY_CNT); msleep(50); i2c_himax_write_command(client, HX_CMD_TSSLPIN, DEFAULT_RETRY_CNT); msleep(50); } void himax_sense_on(struct i2c_client *client, uint8_t FlashMode) { i2c_himax_write_command(client, HX_CMD_TSSON, DEFAULT_RETRY_CNT); msleep(30); i2c_himax_write_command(client, HX_CMD_TSSLPOUT, DEFAULT_RETRY_CNT); msleep(50); } static int himax_ManualMode(struct i2c_client *client, int enter) { uint8_t cmd[2]; cmd[0] = enter; if (i2c_himax_write(client, HX_CMD_MANUALMODE, &cmd[0], 1, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } return 0; } static int himax_FlashMode(struct i2c_client *client, int enter) { uint8_t cmd[2]; cmd[0] = enter; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 1, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } return 0; } static int himax_lock_flash(struct i2c_client *client, int enable) { uint8_t cmd[5]; if (i2c_himax_write(client, 0xAA, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } /* lock sequence start */ cmd[0] = 0x01; cmd[1] = 0x00; cmd[2] = 0x06; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x03; cmd[1] = 0x00; cmd[2] = 0x00; if (i2c_himax_write(client, HX_CMD_FLASH_SET_ADDRESS, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } if (enable != 0) { cmd[0] = 0x63; cmd[1] = 0x02; cmd[2] = 0x70; cmd[3] = 0x03; } else { cmd[0] = 0x63; cmd[1] = 0x02; cmd[2] = 0x30; cmd[3] = 0x00; } if (i2c_himax_write(client, HX_CMD_FLASH_WRITE_REGISTER, &cmd[0], 4, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } if (i2c_himax_write_command(client, HX_CMD_4A, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } msleep(50); if (i2c_himax_write(client, 0xA9, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } return 0; /* lock sequence stop */ } static void himax_changeIref(struct i2c_client *client, int selected_iref) { unsigned char temp_iref[16][2] = { {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00} }; uint8_t cmd[10]; int i = 0; int j = 0; I("%s: start to check iref,iref number = %d\n", __func__, selected_iref); if (i2c_himax_write(client, 0xAA, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } for (i = 0; i < 16; i++) { for (j = 0; j < 2; j++) { if (selected_iref == 1) temp_iref[i][j] = E_IrefTable_1[i][j]; else if (selected_iref == 2) temp_iref[i][j] = E_IrefTable_2[i][j]; else if (selected_iref == 3) temp_iref[i][j] = E_IrefTable_3[i][j]; else if (selected_iref == 4) temp_iref[i][j] = E_IrefTable_4[i][j]; else if (selected_iref == 5) temp_iref[i][j] = E_IrefTable_5[i][j]; else if (selected_iref == 6) temp_iref[i][j] = E_IrefTable_6[i][j]; else if (selected_iref == 7) temp_iref[i][j] = E_IrefTable_7[i][j]; } } if (!iref_found) { /* Read Iref */ /* Register 0x43 */ cmd[0] = 0x01; cmd[1] = 0x00; cmd[2] = 0x0A; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x44 */ cmd[0] = 0x00; cmd[1] = 0x00; cmd[2] = 0x00; if (i2c_himax_write(client, HX_CMD_FLASH_SET_ADDRESS, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x46 */ if (i2c_himax_write(client, 0x46, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x59 */ if (i2c_himax_read(client, 0x59, cmd, 4, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* find iref group , default is iref 3 */ for (i = 0; i < 16; i++) { if ((cmd[0] == temp_iref[i][0]) && (cmd[1] == temp_iref[i][1])) { iref_number = i; iref_found = true; break; } } if (!iref_found) { E("%s: Can't find iref number!\n", __func__); return; } I("%s: iref_number=%d, cmd[0]=0x%x, cmd[1]=0x%x\n", __func__, iref_number, cmd[0], cmd[1]); } msleep(20); /* iref write */ /* Register 0x43 */ cmd[0] = 0x01; cmd[1] = 0x00; cmd[2] = 0x06; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x44 */ cmd[0] = 0x00; cmd[1] = 0x00; cmd[2] = 0x00; if (i2c_himax_write(client, HX_CMD_FLASH_SET_ADDRESS, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x45 */ cmd[0] = temp_iref[iref_number][0]; cmd[1] = temp_iref[iref_number][1]; cmd[2] = 0x17; cmd[3] = 0x28; if (i2c_himax_write(client, HX_CMD_FLASH_WRITE_REGISTER, &cmd[0], 4, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x4A */ if (i2c_himax_write(client, HX_CMD_4A, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Read SFR to check the result */ /* Register 0x43 */ cmd[0] = 0x01; cmd[1] = 0x00; cmd[2] = 0x0A; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x44 */ cmd[0] = 0x00; cmd[1] = 0x00; cmd[2] = 0x00; if (i2c_himax_write(client, HX_CMD_FLASH_SET_ADDRESS, &cmd[0], 3, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x46 */ if (i2c_himax_write(client, 0x46, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } /* Register 0x59 */ if (i2c_himax_read(client, 0x59, cmd, 4, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } I("%s:cmd[0]=%d,cmd[1]=%d,temp_iref_1=%d,temp_iref_2=%d\n", __func__, cmd[0], cmd[1], temp_iref[iref_number][0], temp_iref[iref_number][1]); if (cmd[0] != temp_iref[iref_number][0] || cmd[1] != temp_iref[iref_number][1]) { E("%s: IREF Read Back is not match.\n", __func__); E("%s: Iref [0]=%d,[1]=%d\n", __func__, cmd[0], cmd[1]); } else { I("%s: IREF Pass", __func__); } if (i2c_himax_write(client, 0xA9, &cmd[0], 0, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } } bool himax_calculateChecksum(struct i2c_client *client, bool change_iref) { int iref_flag = 0; uint8_t cmd[10]; memset(cmd, 0x00, sizeof(cmd)); /* Sleep out */ if (i2c_himax_write(client, HX_CMD_TSSLPOUT, &cmd[0], 0, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } msleep(120); while (true) { if (change_iref) { if (iref_flag == 0) himax_changeIref(client, 2); /* iref 2 */ else if (iref_flag == 1) himax_changeIref(client, 5); /* iref 5 */ else if (iref_flag == 2) himax_changeIref(client, 1); /* iref 1 */ else goto CHECK_FAIL; iref_flag++; } cmd[0] = 0x00; cmd[1] = 0x04; cmd[2] = 0x0A; cmd[3] = 0x02; if (i2c_himax_write(client, 0xED, &cmd[0], 4, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } /* Enable Flash */ cmd[0] = 0x01; cmd[1] = 0x00; cmd[2] = 0x02; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 3, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x05; if (i2c_himax_write(client, 0xD2, &cmd[0], 1, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; if (i2c_himax_write(client, 0x53, &cmd[0], 1, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } msleep(200); if (i2c_himax_read(client, 0xAD, cmd, 4, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return -1; } I("%s 0xAD[0,1,2,3] = %d,%d,%d,%d\n", __func__, cmd[0], cmd[1], cmd[2], cmd[3]); if (cmd[0] == 0 && cmd[1] == 0 && cmd[2] == 0 && cmd[3] == 0) { himax_FlashMode(client, 0); goto CHECK_PASS; } else { himax_FlashMode(client, 0); goto CHECK_FAIL; } CHECK_PASS: if (change_iref) { if (iref_flag < 3) continue; else return 0; } else { return 0; } CHECK_FAIL: return 1; } return 1; } bool himax_flash_lastdata_check(struct i2c_client *client) { return 0; } int fts_ctpm_fw_upgrade_with_sys_fs_32k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) { unsigned char *ImageBuffer = fw; int fullFileLength = len; int i; uint8_t cmd[5], last_byte, prePage; int FileLength = 0; uint8_t checksumResult = 0; I("Enter %s", __func__); if (len != 0x8000) { /* 32k */ E("%s: The file size is not 32K bytes, len = %d\n", __func__, fullFileLength); return false; } #ifdef HX_RST_PIN_FUNC himax_ic_reset(false, false); #endif FileLength = fullFileLength; if (i2c_himax_write(client, HX_CMD_TSSLPOUT, &cmd[0], 0, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } msleep(120); himax_lock_flash(client, 0); cmd[0] = 0x05; cmd[1] = 0x00; cmd[2] = 0x02; if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 3, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } if (i2c_himax_write(client, 0x4F, &cmd[0], 0, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } msleep(50); himax_ManualMode(client, 1); himax_FlashMode(client, 1); FileLength = (FileLength + 3) / 4; for (i = 0, prePage = 0; i < FileLength; i++) { last_byte = 0; cmd[0] = i & 0x1F; if (cmd[0] == 0x1F || i == FileLength - 1) last_byte = 1; cmd[1] = (i >> 5) & 0x1F; cmd[2] = (i >> 10) & 0x1F; if (i2c_himax_write(client, HX_CMD_FLASH_SET_ADDRESS, &cmd[0], 3, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } if (prePage != cmd[1] || i == 0) { prePage = cmd[1]; cmd[0] = 0x01; cmd[1] = 0x09; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x0D; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x09; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } } memcpy(&cmd[0], &ImageBuffer[4 * i], 4); if (i2c_himax_write(client, HX_CMD_FLASH_WRITE_REGISTER, &cmd[0], 4, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x0D; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x09; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } if (last_byte == 1) { cmd[0] = 0x01; cmd[1] = 0x01; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x05; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x01; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } cmd[0] = 0x01; cmd[1] = 0x00; /* cmd[2] = 0x02; */ if (i2c_himax_write(client, HX_CMD_FLASH_ENABLE, &cmd[0], 2, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); return 0; } msleep(20); if (i == (FileLength - 1)) { himax_FlashMode(client, 0); himax_ManualMode(client, 0); checksumResult = himax_calculateChecksum( client, change_iref); /* */ /* himax_ManualMode(client,0); */ himax_lock_flash(client, 1); if (!checksumResult) { /* Success */ return 1; } E("%s: checksumResult fail!\n", __func__); return 0; } } } return 0; } int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) { return 0; } int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) { return 0; } int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) { return 0; } int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) { return 0; } void himax_touch_information(struct i2c_client *client) { #ifndef HX_FIX_TOUCH_INFO char data[12] = {0}; I("%s:IC_TYPE =%d\n", __func__, IC_TYPE); if (IC_TYPE == HX_85XX_ES_SERIES_PWON) { data[0] = 0x8C; data[1] = 0x14; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); data[0] = 0x8B; data[1] = 0x00; data[2] = 0x70; i2c_himax_master_write(client, &data[0], 3, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_read(client, 0x5A, data, 12, DEFAULT_RETRY_CNT); ic_data->HX_RX_NUM = data[0]; /* FE(70) */ ic_data->HX_TX_NUM = data[1]; /* FE(71) */ ic_data->HX_MAX_PT = (data[2] & 0xF0) >> 4; /* FE(72) */ #ifdef HX_EN_SEL_BUTTON ic_data->HX_BT_NUM = (data[2] & 0x0F); /* FE(72) */ #endif if ((data[4] & 0x04) == 0x04) { /* FE(74) */ ic_data->HX_XY_REVERSE = true; ic_data->HX_Y_RES = data[6] * 256 + data[7]; /* FE(76),FE(77) */ ic_data->HX_X_RES = data[8] * 256 + data[9]; /* FE(78),FE(79) */ } else { ic_data->HX_XY_REVERSE = false; ic_data->HX_X_RES = data[6] * 256 + data[7]; /* FE(76),FE(77) */ ic_data->HX_Y_RES = data[8] * 256 + data[9]; /* FE(78),FE(79) */ } data[0] = 0x8C; data[1] = 0x00; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); #ifdef HX_EN_MUT_BUTTON data[0] = 0x8C; data[1] = 0x14; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); data[0] = 0x8B; data[1] = 0x00; data[2] = 0x64; i2c_himax_master_write(client, &data[0], 3, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_read(client, 0x5A, data, 4, DEFAULT_RETRY_CNT); ic_data->HX_BT_NUM = (data[0] & 0x03); data[0] = 0x8C; data[1] = 0x00; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); #endif #ifdef HX_TP_PROC_2T2R data[0] = 0x8C; data[1] = 0x14; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); data[0] = 0x8B; data[1] = 0x00; data[2] = HX_2T2R_Addr; i2c_himax_master_write(client, &data[0], 3, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_read(client, 0x5A, data, 10, DEFAULT_RETRY_CNT); ic_data->HX_RX_NUM_2 = data[0]; ic_data->HX_TX_NUM_2 = data[1]; I("%s:Touch Panel Type=%d\n", __func__, data[2]); if ((data[2] & 0x02) == HX_2T2R_en_setting) /* 2T2R type panel */ Is_2T2R = true; else Is_2T2R = false; data[0] = 0x8C; data[1] = 0x00; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); #endif data[0] = 0x8C; data[1] = 0x14; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); data[0] = 0x8B; data[1] = 0x00; data[2] = 0x02; i2c_himax_master_write(client, &data[0], 3, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_read(client, 0x5A, data, 10, DEFAULT_RETRY_CNT); if ((data[1] & 0x01) == 1) { /* FE(02) */ ic_data->HX_INT_IS_EDGE = true; } else { ic_data->HX_INT_IS_EDGE = false; } data[0] = 0x8C; data[1] = 0x00; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n", __func__, ic_data->HX_RX_NUM, ic_data->HX_TX_NUM, ic_data->HX_MAX_PT); if (i2c_himax_read(client, HX_VER_FW_CFG, data, 1, 3) < 0) E("%s: i2c access fail!\n", __func__); ic_data->vendor_config_ver = data[0]; I("config_ver=%x.\n", ic_data->vendor_config_ver); } else { ic_data->HX_RX_NUM = 0; ic_data->HX_TX_NUM = 0; ic_data->HX_BT_NUM = 0; ic_data->HX_X_RES = 0; ic_data->HX_Y_RES = 0; ic_data->HX_MAX_PT = 0; ic_data->HX_XY_REVERSE = false; ic_data->HX_INT_IS_EDGE = false; } #else ic_data->HX_RX_NUM = FIX_HX_RX_NUM; ic_data->HX_TX_NUM = FIX_HX_TX_NUM; ic_data->HX_BT_NUM = FIX_HX_BT_NUM; ic_data->HX_X_RES = FIX_HX_X_RES; ic_data->HX_Y_RES = FIX_HX_Y_RES; ic_data->HX_MAX_PT = FIX_HX_MAX_PT; ic_data->HX_XY_REVERSE = FIX_HX_XY_REVERSE; ic_data->HX_INT_IS_EDGE = FIX_HX_INT_IS_EDGE; #ifdef HX_TP_PROC_2T2R Is_2T2R = true; ic_data->HX_RX_NUM_2 = FIX_HX_RX_NUM_2; ic_data->HX_TX_NUM_2 = FIX_HX_TX_NUM_2; #endif I("%s:RX_NUM =%d,TX_NUM =%d,MAX_PT=%d,X_RES =%d,Y_RES =%d,INT_IS=%d\n", __func__, ic_data->HX_RX_NUM, ic_data->HX_TX_NUM, ic_data->HX_MAX_PT, ic_data->HX_X_RES, ic_data->HX_Y_RES, ic_data->HX_INT_IS_EDGE); #endif } static int himax_read_Sensor_ID(struct i2c_client *client) { uint8_t val_high[1], val_low[1], ID0 = 0, ID1 = 0; char data[3]; const int normalRetry = 10; int sensor_id; data[0] = 0x56; data[1] = 0x02; data[2] = 0x02; /*ID pin PULL High*/ i2c_himax_master_write(client, &data[0], 3, normalRetry); msleep(20); /* read id pin high */ i2c_himax_read(client, 0x57, val_high, 1, normalRetry); data[0] = 0x56; data[1] = 0x01; data[2] = 0x01; /*ID pin PULL Low*/ i2c_himax_master_write(client, &data[0], 3, normalRetry); msleep(20); /* read id pin low */ i2c_himax_read(client, 0x57, val_low, 1, normalRetry); if ((val_high[0] & 0x01) == 0) ID0 = 0x02; /*GND*/ else if ((val_low[0] & 0x01) == 0) ID0 = 0x01; /*Floating*/ else ID0 = 0x04; /*VCC*/ if ((val_high[0] & 0x02) == 0) ID1 = 0x02; /*GND*/ else if ((val_low[0] & 0x02) == 0) ID1 = 0x01; /*Floating*/ else ID1 = 0x04; /*VCC*/ if ((ID0 == 0x04) && (ID1 != 0x04)) { data[0] = 0x56; data[1] = 0x02; data[2] = 0x01; /*ID pin PULL High,Low*/ i2c_himax_master_write(client, &data[0], 3, normalRetry); msleep(20); } else if ((ID0 != 0x04) && (ID1 == 0x04)) { data[0] = 0x56; data[1] = 0x01; data[2] = 0x02; /*ID pin PULL Low,High*/ i2c_himax_master_write(client, &data[0], 3, normalRetry); msleep(20); } else if ((ID0 == 0x04) && (ID1 == 0x04)) { data[0] = 0x56; data[1] = 0x02; data[2] = 0x02; /*ID pin PULL High,High*/ i2c_himax_master_write(client, &data[0], 3, normalRetry); msleep(20); } sensor_id = (ID1 << 4) | ID0; data[0] = 0xE4; data[1] = sensor_id; i2c_himax_master_write(client, &data[0], 2, normalRetry); /*Write to MCU*/ msleep(20); return sensor_id; } int himax_read_i2c_status(struct i2c_client *client) { return i2c_error_count; /* */ } int himax_read_ic_trigger_type(struct i2c_client *client) { char data[12] = {0}; int trigger_type = false; himax_sense_off(client); data[0] = 0x8C; data[1] = 0x14; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); msleep(20); data[0] = 0x8B; data[1] = 0x00; data[2] = 0x02; i2c_himax_master_write(client, &data[0], 3, DEFAULT_RETRY_CNT); msleep(20); i2c_himax_read(client, 0x5A, data, 10, DEFAULT_RETRY_CNT); if ((data[1] & 0x01) == 1) { /* FE(02) */ trigger_type = true; } else { trigger_type = false; } data[0] = 0x8C; data[1] = 0x00; i2c_himax_master_write(client, &data[0], 2, DEFAULT_RETRY_CNT); himax_sense_on(client, 0x01); return trigger_type; } void himax_read_FW_ver(struct i2c_client *client) { uint8_t data[64]; /* read fw version */ if (i2c_himax_read(client, HX_VER_FW_MAJ, data, 1, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } ic_data->vendor_fw_ver = data[0] << 8; if (i2c_himax_read(client, HX_VER_FW_MIN, data, 1, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } ic_data->vendor_fw_ver = data[0] | ic_data->vendor_fw_ver; /* read config version */ if (i2c_himax_read(client, HX_VER_FW_CFG, data, 1, 3) < 0) { E("%s: i2c access fail!\n", __func__); return; } ic_data->vendor_config_ver = data[0]; /* read sensor ID */ ic_data->vendor_sensor_id = himax_read_Sensor_ID(client); I("sensor_id=%x.\n", ic_data->vendor_sensor_id); I("fw_ver=%x.\n", ic_data->vendor_fw_ver); I("config_ver=%x.\n", ic_data->vendor_config_ver); ic_data->vendor_panel_ver = -1; ic_data->vendor_cid_maj_ver = -1; ic_data->vendor_cid_min_ver = -1; } bool himax_ic_package_check(struct i2c_client *client) { uint8_t cmd[3]; memset(cmd, 0x00, sizeof(cmd)); msleep(50); if (i2c_himax_read(client, 0xD1, cmd, 3, DEFAULT_RETRY_CNT) < 0) return false; if (cmd[0] == 0x05 && cmd[1] == 0x85 && (cmd[2] == 0x25 || cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28)) { IC_TYPE = HX_85XX_ES_SERIES_PWON; IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; /* Himax: Set FW and CFG Flash Address */ FW_VER_MAJ_FLASH_ADDR = 133; /* 0x0085 */ FW_VER_MAJ_FLASH_LENG = 1; ; FW_VER_MIN_FLASH_ADDR = 134; /* 0x0086 */ FW_VER_MIN_FLASH_LENG = 1; FW_CFG_VER_FLASH_ADDR = 132; /* 0x0084 */ #ifdef HX_AUTO_UPDATE_FW g_i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR] << 8 | i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; g_i_CFG_VER = i_CTPM_FW[FW_CFG_VER_FLASH_ADDR]; g_i_CID_MAJ = -1; g_i_CID_MIN = -1; #endif I("Himax IC package 852x ES\n"); } else { E("Himax IC package incorrect!!PKG[0]=%x,PKG[1]=%x,PKG[2]=%x\n", cmd[0], cmd[1], cmd[2]); return false; } return true; } void himax_power_on_init(struct i2c_client *client) { I("%s:\n", __func__); himax_sense_on(client, 0x01); himax_sense_off(client); himax_touch_information(client); himax_sense_on(client, 0x01); } void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data) { } void himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte) { } /* ts_work */ int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max) { int RawDataLen; if (raw_cnt_rmd != 0x00) RawDataLen = 128 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1; else RawDataLen = 128 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1; return RawDataLen; } bool himax_read_event_stack(struct i2c_client *client, uint8_t *buf, int length) { uint8_t cmd[4]; if (length > 56) length = 128; /* ===================== */ /* Read event stack */ /* ===================== */ cmd[0] = 0x31; if (i2c_himax_read(client, 0x86, buf, length, DEFAULT_RETRY_CNT) < 0) { E("%s: i2c access fail!\n", __func__); goto err_workqueue_out; } return 1; err_workqueue_out: return 0; } /* return checksum result */ bool diag_check_sum(struct himax_report_data *hx_touch_data) { uint16_t check_sum_cal = 0; int i; /* Check 128th byte CRC */ for (i = 0, check_sum_cal = 0; i < (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); i++) { check_sum_cal += hx_touch_data->hx_rawdata_buf[i]; } if (check_sum_cal % 0x100 != 0) return 0; return 1; } void diag_parse_raw_data(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data) { int index = 0; int temp1, temp2, i; #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) int cnt = 0; uint8_t command_F1h_bank[2] = {0xF1, 0x00}; #endif /* Himax: Check Raw-Data Header */ if (hx_touch_data->hx_rawdata_buf[0] == hx_touch_data->hx_rawdata_buf[1] && hx_touch_data->hx_rawdata_buf[1] == hx_touch_data->hx_rawdata_buf[2] && hx_touch_data->hx_rawdata_buf[2] == hx_touch_data->hx_rawdata_buf[3] && hx_touch_data->hx_rawdata_buf[0] > 0) { index = (hx_touch_data->hx_rawdata_buf[0] - 1) * hx_touch_data->rawdata_size; /* I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", */ /* index, buf[56], buf[57], buf[58], buf[59], mul_num, */ /* self_num); */ for (i = 0; i < hx_touch_data->rawdata_size; i++) { temp1 = index + i; if (temp1 < mul_num) { /* mutual */ mutual_data[index + i] = hx_touch_data->hx_rawdata_buf [i + 4]; /* 4: RawData Header */ #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) if (Selftest_flag == 1) { /* mutual_bank[index + i] = */ /* hx_touch_data->hx_rawdata_buf[i + 4]; */ raw_data_chk_arr [hx_touch_data ->hx_rawdata_buf[0] - 1] = true; } #endif } else { /* self */ temp1 = i + index; temp2 = self_num + mul_num; if (temp1 >= temp2) break; self_data[i + index - mul_num] = hx_touch_data->hx_rawdata_buf [i + 4]; /* 4: RawData Header */ #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) if (Selftest_flag == 1) { /* self_bank[i+index-mul_num] = */ /* hx_touch_data->hx_rawdata_buf[i + 4]; */ raw_data_chk_arr [hx_touch_data ->hx_rawdata_buf[0] - 1] = true; } #endif } } #if defined(HX_TP_SELF_TEST_DRIVER) || \ defined(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) if (Selftest_flag == 1) { cnt = 0; for (i = 0; i < hx_touch_data->rawdata_frame_size; i++) { if (raw_data_chk_arr[i] == true) cnt++; } if (cnt == hx_touch_data->rawdata_frame_size) { I("test_counter = %d\n", test_counter); test_counter++; } if (test_counter == TEST_DATA_TIMES) { memcpy(mutual_bank, mutual_data, mul_num * sizeof(uint16_t)); memcpy(self_bank, self_data, self_num * sizeof(uint16_t)); for (i = 0; i < hx_touch_data->rawdata_frame_size; i++) { raw_data_chk_arr[i] = false; } test_counter = 0; Selftest_flag = 0; g_diag_command = 0; command_F1h_bank[1] = 0x00; i2c_himax_write(private_ts->client, command_F1h_bank[0], &command_F1h_bank[1], 1, DEFAULT_RETRY_CNT); msleep(20); } } #endif } } uint8_t himax_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data) { return -1; } int himax_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr) { return -1; } #ifdef HX_TP_PROC_GUEST_INFO #define HX_GUEST_INFO_SIZE 10 #define HX_GUEST_INFO_LEN_SIZE 4 int g_guest_info_ongoing; /* 0 stop //1 ongoing */ char g_guest_str[10][128]; int himax_guest_info_get_status(void) { return g_guest_info_ongoing; } void himax_guest_info_set_status(int setting) { g_guest_info_ongoing = setting; } void himax_guest_info_read(uint32_t start_addr, uint8_t *flash_tmp_buffer) { } int himax_read_project_id(void) { int custom_info_temp = 0; char *temp_str = "DO NOT support this function!\n"; himax_guest_info_set_status(1); for (custom_info_temp = 0; custom_info_temp < HX_GUEST_INFO_SIZE; custom_info_temp++) { memcpy(&g_guest_str[custom_info_temp], temp_str, 30); } himax_guest_info_set_status(0); return NO_ERR; } #endif #if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || \ defined(HX_USB_DETECT_GLOBAL) void himax_resend_cmd_func(bool suspended) { struct himax_ts_data *ts; ts = private_ts; if (!suspended) { /* if entering resume need to sense off first*/ himax_int_enable(ts->client->irq, 0); #ifdef HX_RESUME_HW_RESET himax_ic_reset(false, false); #else himax_sense_off(ts->client); #endif } #ifdef HX_SMART_WAKEUP himax_set_SMWP_enable(ts->client, ts->SMWP_enable, suspended); #endif #ifdef HX_HIGH_SENSE himax_set_HSEN_enable(ts->client, ts->HSEN_enable, suspended); #endif #ifdef HX_USB_DETECT_GLOBAL himax_cable_detect_func(true); #endif } void himax_rst_cmd_recovery_func(bool suspended) { } #endif void himax_resume_ic_action(struct i2c_client *client) { i2c_himax_write_command(client, HX_CMD_TSSON, DEFAULT_RETRY_CNT); msleep(30); i2c_himax_write_command(client, HX_CMD_TSSLPOUT, DEFAULT_RETRY_CNT); } void himax_suspend_ic_action(struct i2c_client *client) { i2c_himax_write_command(client, HX_CMD_TSSOFF, DEFAULT_RETRY_CNT); msleep(40); i2c_himax_write_command(client, HX_CMD_TSSLPIN, DEFAULT_RETRY_CNT); }