in rmi4/rmi_f11.c [1061:1272]
static int rmi_f11_initialize(struct rmi_function *fn)
{
struct rmi_device *rmi_dev = fn->rmi_dev;
struct f11_data *f11;
struct f11_2d_ctrl *ctrl;
u8 query_offset;
u16 query_base_addr;
u16 control_base_addr;
u16 max_x_pos, max_y_pos;
int rc;
const struct rmi_device_platform_data *pdata =
rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct rmi_2d_sensor *sensor;
u8 buf;
int mask_size;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Initializing F11 values.\n");
mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long);
/*
** init instance data, fill in values and create any sysfs files
*/
f11 = devm_kzalloc(&fn->dev, sizeof(struct f11_data) + mask_size * 2,
GFP_KERNEL);
if (!f11)
return -ENOMEM;
if (fn->dev.of_node) {
rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata);
if (rc)
return rc;
} else {
f11->sensor_pdata = pdata->sensor_pdata;
}
f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait;
f11->abs_mask = (unsigned long *)((char *)f11
+ sizeof(struct f11_data));
f11->rel_mask = (unsigned long *)((char *)f11
+ sizeof(struct f11_data) + mask_size);
set_bit(fn->irq_pos, f11->abs_mask);
set_bit(fn->irq_pos + 1, f11->rel_mask);
query_base_addr = fn->fd.query_base_addr;
control_base_addr = fn->fd.control_base_addr;
rc = rmi_read(rmi_dev, query_base_addr, &buf);
if (rc < 0)
return rc;
f11->has_query9 = !!(buf & RMI_F11_HAS_QUERY9);
f11->has_query11 = !!(buf & RMI_F11_HAS_QUERY11);
f11->has_query12 = !!(buf & RMI_F11_HAS_QUERY12);
f11->has_query27 = !!(buf & RMI_F11_HAS_QUERY27);
f11->has_query28 = !!(buf & RMI_F11_HAS_QUERY28);
query_offset = (query_base_addr + 1);
sensor = &f11->sensor;
sensor->fn = fn;
rc = rmi_f11_get_query_parameters(rmi_dev, f11,
&f11->sens_query, query_offset);
if (rc < 0)
return rc;
query_offset += rc;
rc = f11_read_control_regs(fn, &f11->dev_controls,
control_base_addr);
if (rc < 0) {
dev_err(&fn->dev,
"Failed to read F11 control params.\n");
return rc;
}
if (f11->sens_query.has_info2) {
if (f11->sens_query.is_clear)
f11->sensor.sensor_type = rmi_sensor_touchscreen;
else
f11->sensor.sensor_type = rmi_sensor_touchpad;
}
sensor->report_abs = f11->sens_query.has_abs;
sensor->axis_align =
f11->sensor_pdata.axis_align;
sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad;
sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking;
sensor->dmax = f11->sensor_pdata.dmax;
sensor->dribble = f11->sensor_pdata.dribble;
sensor->palm_detect = f11->sensor_pdata.palm_detect;
if (f11->sens_query.has_physical_props) {
sensor->x_mm = f11->sens_query.x_sensor_size_mm;
sensor->y_mm = f11->sens_query.y_sensor_size_mm;
} else {
sensor->x_mm = f11->sensor_pdata.x_mm;
sensor->y_mm = f11->sensor_pdata.y_mm;
}
if (sensor->sensor_type == rmi_sensor_default)
sensor->sensor_type =
f11->sensor_pdata.sensor_type;
sensor->report_abs = sensor->report_abs
&& !(f11->sensor_pdata.disable_report_mask
& RMI_F11_DISABLE_ABS_REPORT);
if (!sensor->report_abs)
/*
* If device doesn't have abs or if it has been disables
* fallback to reporting rel data.
*/
sensor->report_rel = f11->sens_query.has_rel;
rc = rmi_read_block(rmi_dev,
control_base_addr + F11_CTRL_SENSOR_MAX_X_POS_OFFSET,
(u8 *)&max_x_pos, sizeof(max_x_pos));
if (rc < 0)
return rc;
rc = rmi_read_block(rmi_dev,
control_base_addr + F11_CTRL_SENSOR_MAX_Y_POS_OFFSET,
(u8 *)&max_y_pos, sizeof(max_y_pos));
if (rc < 0)
return rc;
sensor->max_x = max_x_pos;
sensor->max_y = max_y_pos;
rc = f11_2d_construct_data(f11);
if (rc < 0)
return rc;
if (f11->has_acm)
f11->sensor.attn_size += f11->sensor.nbr_fingers * 2;
/* allocate the in-kernel tracking buffers */
sensor->tracking_pos = devm_kcalloc(&fn->dev,
sensor->nbr_fingers, sizeof(struct input_mt_pos),
GFP_KERNEL);
sensor->tracking_slots = devm_kcalloc(&fn->dev,
sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
sensor->objs = devm_kcalloc(&fn->dev,
sensor->nbr_fingers,
sizeof(struct rmi_2d_sensor_abs_object),
GFP_KERNEL);
if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
return -ENOMEM;
ctrl = &f11->dev_controls;
if (sensor->axis_align.delta_x_threshold)
ctrl->ctrl0_11[RMI_F11_DELTA_X_THRESHOLD] =
sensor->axis_align.delta_x_threshold;
if (sensor->axis_align.delta_y_threshold)
ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] =
sensor->axis_align.delta_y_threshold;
/*
* If distance threshold values are set, switch to reduced reporting
* mode so they actually get used by the controller.
*/
if (sensor->axis_align.delta_x_threshold ||
sensor->axis_align.delta_y_threshold) {
ctrl->ctrl0_11[0] &= ~RMI_F11_REPORT_MODE_MASK;
ctrl->ctrl0_11[0] |= RMI_F11_REPORT_MODE_REDUCED;
}
if (f11->sens_query.has_dribble) {
switch (sensor->dribble) {
case RMI_REG_STATE_OFF:
ctrl->ctrl0_11[0] &= ~BIT(6);
break;
case RMI_REG_STATE_ON:
ctrl->ctrl0_11[0] |= BIT(6);
break;
case RMI_REG_STATE_DEFAULT:
default:
break;
}
}
if (f11->sens_query.has_palm_det) {
switch (sensor->palm_detect) {
case RMI_REG_STATE_OFF:
ctrl->ctrl0_11[11] &= ~BIT(0);
break;
case RMI_REG_STATE_ON:
ctrl->ctrl0_11[11] |= BIT(0);
break;
case RMI_REG_STATE_DEFAULT:
default:
break;
}
}
rc = f11_write_control_regs(fn, &f11->sens_query,
&f11->dev_controls, fn->fd.control_base_addr);
if (rc)
dev_warn(&fn->dev, "Failed to write control registers\n");
mutex_init(&f11->dev_controls_mutex);
dev_set_drvdata(&fn->dev, f11);
return 0;
}