static int prox_reg_init(void) { int retval; unsigned char ctrl_23_offset; unsigned char data_1_offset; struct synaptics_rmi4_f12_query_5 query_5; struct synaptics_rmi4_f12_query_8 query_8; struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; retval = synaptics_rmi4_reg_read(rmi4_data, prox->query_base_addr + 5, query_5.data, sizeof(query_5.data)); if (retval < 0) return retval; ctrl_23_offset = query_5.ctrl0_is_present + query_5.ctrl1_is_present + query_5.ctrl2_is_present + query_5.ctrl3_is_present + query_5.ctrl4_is_present + query_5.ctrl5_is_present + query_5.ctrl6_is_present + query_5.ctrl7_is_present + query_5.ctrl8_is_present + query_5.ctrl9_is_present + query_5.ctrl10_is_present + query_5.ctrl11_is_present + query_5.ctrl12_is_present + query_5.ctrl13_is_present + query_5.ctrl14_is_present + query_5.ctrl15_is_present + query_5.ctrl16_is_present + query_5.ctrl17_is_present + query_5.ctrl18_is_present + query_5.ctrl19_is_present + query_5.ctrl20_is_present + query_5.ctrl21_is_present + query_5.ctrl22_is_present; prox->hover_finger_en_addr = prox->control_base_addr + ctrl_23_offset; retval = synaptics_rmi4_reg_read(rmi4_data, prox->query_base_addr + 8, query_8.data, sizeof(query_8.data)); if (retval < 0) return retval; data_1_offset = query_8.data0_is_present; prox->hover_finger_data_addr = prox->data_base_addr + data_1_offset; return retval; }
static int prox_set_hover_finger_en(void) { int retval; unsigned char object_report_enable; struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; retval = synaptics_rmi4_reg_read(rmi4_data, prox->hover_finger_en_addr, &object_report_enable, sizeof(object_report_enable)); if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to read from object report enable register\n", __func__); return retval; } if (prox->hover_finger_en) object_report_enable |= HOVERING_FINGER_EN; else object_report_enable &= ~HOVERING_FINGER_EN; retval = synaptics_rmi4_reg_write(rmi4_data, prox->hover_finger_en_addr, &object_report_enable, sizeof(object_report_enable)); if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to write to object report enable register\n", __func__); return retval; } return 0; }
static int apen_reg_init(void) { int retval; unsigned char data_offset; unsigned char size_of_query8; struct synaptics_rmi4_f12_query_8 query_8; struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; retval = synaptics_rmi4_reg_read(rmi4_data, apen->query_base_addr + 7, &size_of_query8, sizeof(size_of_query8)); if (retval < 0) return retval; retval = synaptics_rmi4_reg_read(rmi4_data, apen->query_base_addr + 8, query_8.data, sizeof(query_8.data)); if (retval < 0) return retval; if ((size_of_query8 >= 2) && (query_8.data6_is_present)) { data_offset = query_8.data0_is_present + query_8.data1_is_present + query_8.data2_is_present + query_8.data3_is_present + query_8.data4_is_present + query_8.data5_is_present; apen->apen_data_addr = apen->data_base_addr + data_offset; retval = apen_pressure(&query_8); if (retval < 0) return retval; } else { dev_err(rmi4_data->pdev->dev.parent, "%s: Active pen support unavailable\n", __func__); retval = -ENODEV; } return retval; }
static void prox_hover_finger_report(void) { int retval; int x; int y; int z; struct prox_finger_data *data; struct synaptics_rmi4_data *rmi4_data = prox->rmi4_data; data = prox->finger_data; retval = synaptics_rmi4_reg_read(rmi4_data, prox->hover_finger_data_addr, data->proximity_data, sizeof(data->proximity_data)); if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to read hovering finger data\n", __func__); return; } if (data->object_type_and_status != F12_HOVERING_FINGER_STATUS) { if (prox->hover_finger_present) prox_hover_finger_lift(); return; } x = (data->x_msb << 8) | (data->x_lsb); y = (data->y_msb << 8) | (data->y_lsb); z = HOVER_Z_MAX - data->z; input_report_key(prox->prox_dev, BTN_TOUCH, 0); input_report_key(prox->prox_dev, BTN_TOOL_FINGER, 1); input_report_abs(prox->prox_dev, ABS_X, x); input_report_abs(prox->prox_dev, ABS_Y, y); input_report_abs(prox->prox_dev, ABS_DISTANCE, z); input_sync(prox->prox_dev); dev_dbg(rmi4_data->pdev->dev.parent, "%s: x = %d y = %d z = %d\n", __func__, x, y, z); prox->hover_finger_present = true; return; }
static int apen_pressure(struct synaptics_rmi4_f12_query_8 *query_8) { int retval; unsigned char ii; unsigned char data_reg_presence; unsigned char size_of_query_9; unsigned char *query_9; unsigned char *data_desc; struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; data_reg_presence = query_8->data[1]; size_of_query_9 = query_8->size_of_query9; query_9 = kmalloc(size_of_query_9, GFP_KERNEL); retval = synaptics_rmi4_reg_read(rmi4_data, apen->query_base_addr + 9, query_9, size_of_query_9); if (retval < 0) goto exit; data_desc = query_9; for (ii = 0; ii < 6; ii++) { if (!(data_reg_presence & (1 << ii))) continue; /* The data register is not present */ data_desc++; /* Jump over the size entry */ while (*data_desc & (1 << 7)) data_desc++; data_desc++; /* Go to the next descriptor */ } data_desc++; /* Jump over the size entry */ /* Check for the presence of subpackets 1 and 2 */ if ((*data_desc & (3 << 1)) == (3 << 1)) apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_16BIT; else apen->max_pressure = ACTIVE_PEN_MAX_PRESSURE_8BIT; exit: kfree(query_9); return retval; }
static int apen_scan_pdt(void) { int retval; unsigned char ii; unsigned char page; unsigned char intr_count = 0; unsigned char intr_off; unsigned char intr_src; unsigned short addr; struct synaptics_rmi4_fn_desc fd; struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; for (page = 0; page < PAGES_TO_SERVICE; page++) { for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) { addr |= (page << 8); retval = synaptics_rmi4_reg_read(rmi4_data, addr, (unsigned char *)&fd, sizeof(fd)); if (retval < 0) return retval; addr &= ~(MASK_8BIT << 8); if (fd.fn_number) { dev_dbg(rmi4_data->pdev->dev.parent, "%s: Found F%02x\n", __func__, fd.fn_number); switch (fd.fn_number) { case SYNAPTICS_RMI4_F12: goto f12_found; break; } } else { break; } intr_count += fd.intr_src_count; } } dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to find F12\n", __func__); return -EINVAL; f12_found: apen->query_base_addr = fd.query_base_addr | (page << 8); apen->control_base_addr = fd.ctrl_base_addr | (page << 8); apen->data_base_addr = fd.data_base_addr | (page << 8); apen->command_base_addr = fd.cmd_base_addr | (page << 8); retval = apen_reg_init(); if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to initialize active pen registers\n", __func__); return retval; } apen->intr_mask = 0; intr_src = fd.intr_src_count; intr_off = intr_count % 8; for (ii = intr_off; ii < (intr_src + intr_off); ii++) { apen->intr_mask |= 1 << ii; } rmi4_data->intr_mask[0] |= apen->intr_mask; addr = rmi4_data->f01_ctrl_base_addr + 1; retval = synaptics_rmi4_reg_write(rmi4_data, addr, &(rmi4_data->intr_mask[0]), sizeof(rmi4_data->intr_mask[0])); if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to set interrupt enable bit\n", __func__); return retval; } return 0; }
static void apen_report(void) { int retval; int x; int y; int pressure; static int invert = -1; struct apen_data_8b_pressure *apen_data_8b; struct synaptics_rmi4_data *rmi4_data = apen->rmi4_data; retval = synaptics_rmi4_reg_read(rmi4_data, apen->apen_data_addr, apen->apen_data->data, sizeof(apen->apen_data->data)); if (retval < 0) { dev_err(rmi4_data->pdev->dev.parent, "%s: Failed to read active pen data\n", __func__); return; } if (apen->apen_data->status_pen == 0) { if (apen->apen_present) apen_lift(); dev_dbg(rmi4_data->pdev->dev.parent, "%s: No active pen data\n", __func__); return; } x = (apen->apen_data->x_msb << 8) | (apen->apen_data->x_lsb); y = (apen->apen_data->y_msb << 8) | (apen->apen_data->y_lsb); if ((x == -1) && (y == -1)) { if (apen->apen_present) apen_lift(); dev_dbg(rmi4_data->pdev->dev.parent, "%s: Active pen in range but no valid x & y\n", __func__); return; } if (!apen->apen_present) invert = -1; if (invert != -1 && invert != apen->apen_data->status_invert) apen_lift(); invert = apen->apen_data->status_invert; if (apen->max_pressure == ACTIVE_PEN_MAX_PRESSURE_16BIT) { pressure = (apen->apen_data->pressure_msb << 8) | apen->apen_data->pressure_lsb; apen->battery_state = apen->apen_data->battery_state; apen->pen_id = (apen->apen_data->pen_id_24_31 << 24) | (apen->apen_data->pen_id_16_23 << 16) | (apen->apen_data->pen_id_8_15 << 8) | apen->apen_data->pen_id_0_7; } else { apen_data_8b = (struct apen_data_8b_pressure *)apen->apen_data; pressure = apen_data_8b->pressure_msb; apen->battery_state = apen_data_8b->battery_state; apen->pen_id = (apen_data_8b->pen_id_24_31 << 24) | (apen_data_8b->pen_id_16_23 << 16) | (apen_data_8b->pen_id_8_15 << 8) | apen_data_8b->pen_id_0_7; } input_report_key(apen->apen_dev, BTN_TOUCH, pressure > 0 ? 1 : 0); input_report_key(apen->apen_dev, apen->apen_data->status_invert > 0 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN, 1); input_report_key(apen->apen_dev, BTN_STYLUS, apen->apen_data->status_barrel > 0 ? 1 : 0); input_report_abs(apen->apen_dev, ABS_X, x); input_report_abs(apen->apen_dev, ABS_Y, y); input_report_abs(apen->apen_dev, ABS_PRESSURE, pressure); input_sync(apen->apen_dev); dev_dbg(rmi4_data->pdev->dev.parent, "%s: Active pen: status = %d, invert = %d, barrel = %d, x = %d, y = %d, pressure = %d\n", __func__, apen->apen_data->status_pen, apen->apen_data->status_invert, apen->apen_data->status_barrel, x, y, pressure); apen->apen_present = true; return; }