static int ads7846_probe()

in touchscreen/ads7846.c [1212:1412]


static int ads7846_probe(struct spi_device *spi)
{
	const struct ads7846_platform_data *pdata;
	struct ads7846 *ts;
	struct device *dev = &spi->dev;
	struct ads7846_packet *packet;
	struct input_dev *input_dev;
	unsigned long irq_flags;
	int err;

	if (!spi->irq) {
		dev_dbg(dev, "no IRQ?\n");
		return -EINVAL;
	}

	/* don't exceed max specified sample rate */
	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
		dev_err(dev, "f(sample) %d KHz?\n",
			(spi->max_speed_hz/SAMPLE_BITS)/1000);
		return -EINVAL;
	}

	/*
	 * We'd set TX word size 8 bits and RX word size to 13 bits ... except
	 * that even if the hardware can do that, the SPI controller driver
	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
	 */
	spi->bits_per_word = 8;
	spi->mode &= ~SPI_MODE_X_MASK;
	spi->mode |= SPI_MODE_0;
	err = spi_setup(spi);
	if (err < 0)
		return err;

	ts = devm_kzalloc(dev, sizeof(struct ads7846), GFP_KERNEL);
	if (!ts)
		return -ENOMEM;

	packet = devm_kzalloc(dev, sizeof(struct ads7846_packet), GFP_KERNEL);
	if (!packet)
		return -ENOMEM;

	input_dev = devm_input_allocate_device(dev);
	if (!input_dev)
		return -ENOMEM;

	spi_set_drvdata(spi, ts);

	ts->packet = packet;
	ts->spi = spi;
	ts->input = input_dev;

	mutex_init(&ts->lock);
	init_waitqueue_head(&ts->wait);

	pdata = dev_get_platdata(dev);
	if (!pdata) {
		pdata = ads7846_probe_dt(dev);
		if (IS_ERR(pdata))
			return PTR_ERR(pdata);
	}

	ts->model = pdata->model ? : 7846;
	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
	ts->vref_mv = pdata->vref_mv;

	if (pdata->debounce_max) {
		ts->debounce_max = pdata->debounce_max;
		if (ts->debounce_max < 2)
			ts->debounce_max = 2;
		ts->debounce_tol = pdata->debounce_tol;
		ts->debounce_rep = pdata->debounce_rep;
		ts->filter = ads7846_debounce_filter;
		ts->filter_data = ts;
	} else {
		ts->filter = ads7846_no_filter;
	}

	err = ads7846_setup_pendown(spi, ts, pdata);
	if (err)
		return err;

	if (pdata->penirq_recheck_delay_usecs)
		ts->penirq_recheck_delay_usecs =
				pdata->penirq_recheck_delay_usecs;

	ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;

	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
	snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);

	input_dev->name = ts->name;
	input_dev->phys = ts->phys;

	input_dev->id.bustype = BUS_SPI;
	input_dev->id.product = pdata->model;

	input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
	input_set_abs_params(input_dev, ABS_X,
			pdata->x_min ? : 0,
			pdata->x_max ? : MAX_12BIT,
			0, 0);
	input_set_abs_params(input_dev, ABS_Y,
			pdata->y_min ? : 0,
			pdata->y_max ? : MAX_12BIT,
			0, 0);
	input_set_abs_params(input_dev, ABS_PRESSURE,
			pdata->pressure_min, pdata->pressure_max, 0, 0);

	/*
	 * Parse common framework properties. Must be done here to ensure the
	 * correct behaviour in case of using the legacy vendor bindings. The
	 * general binding value overrides the vendor specific one.
	 */
	touchscreen_parse_properties(ts->input, false, &ts->core_prop);
	ts->pressure_max = input_abs_get_max(input_dev, ABS_PRESSURE) ? : ~0;

	/*
	 * Check if legacy ti,swap-xy binding is used instead of
	 * touchscreen-swapped-x-y
	 */
	if (!ts->core_prop.swap_x_y && pdata->swap_xy) {
		swap(input_dev->absinfo[ABS_X], input_dev->absinfo[ABS_Y]);
		ts->core_prop.swap_x_y = true;
	}

	ads7846_setup_spi_msg(ts, pdata);

	ts->reg = devm_regulator_get(dev, "vcc");
	if (IS_ERR(ts->reg)) {
		err = PTR_ERR(ts->reg);
		dev_err(dev, "unable to get regulator: %d\n", err);
		return err;
	}

	err = regulator_enable(ts->reg);
	if (err) {
		dev_err(dev, "unable to enable regulator: %d\n", err);
		return err;
	}

	err = devm_add_action_or_reset(dev, ads7846_regulator_disable, ts->reg);
	if (err)
		return err;

	irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING;
	irq_flags |= IRQF_ONESHOT;

	err = devm_request_threaded_irq(dev, spi->irq,
					ads7846_hard_irq, ads7846_irq,
					irq_flags, dev->driver->name, ts);
	if (err && err != -EPROBE_DEFER && !pdata->irq_flags) {
		dev_info(dev,
			"trying pin change workaround on irq %d\n", spi->irq);
		irq_flags |= IRQF_TRIGGER_RISING;
		err = devm_request_threaded_irq(dev, spi->irq,
						ads7846_hard_irq, ads7846_irq,
						irq_flags, dev->driver->name,
						ts);
	}

	if (err) {
		dev_dbg(dev, "irq %d busy?\n", spi->irq);
		return err;
	}

	err = ads784x_hwmon_register(spi, ts);
	if (err)
		return err;

	dev_info(dev, "touchscreen, irq %d\n", spi->irq);

	/*
	 * Take a first sample, leaving nPENIRQ active and vREF off; avoid
	 * the touchscreen, in case it's not connected.
	 */
	if (ts->model == 7845)
		ads7845_read12_ser(dev, PWRDOWN);
	else
		(void) ads7846_read12_ser(dev, READ_12BIT_SER(vaux));

	err = devm_device_add_group(dev, &ads784x_attr_group);
	if (err)
		return err;

	err = input_register_device(input_dev);
	if (err)
		return err;

	device_init_wakeup(dev, pdata->wakeup);

	/*
	 * If device does not carry platform data we must have allocated it
	 * when parsing DT data.
	 */
	if (!dev_get_platdata(dev))
		devm_kfree(dev, (void *)pdata);

	return 0;
}