static int rmi_f11_initialize()

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;
}