brintos

brintos / linux-shallow public Read only

0
0
Text · 5.3 KiB · 923650d Raw
209 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2021-2023 Digiteq Automotive4 *     author: Martin Tuma <martin.tuma@digiteqautomotive.com>5 *6 * This module handles the IIO trigger device. The card has two signal inputs7 * for event triggers that can be used to record events related to the video8 * stream. A standard linux IIO device with triggered buffer capability is9 * created and configured that can be used to fetch the events with the same10 * clock source as the video frames.11 */12 13#include <linux/iio/iio.h>14#include <linux/iio/buffer.h>15#include <linux/iio/trigger.h>16#include <linux/iio/trigger_consumer.h>17#include <linux/iio/triggered_buffer.h>18#include <linux/pci.h>19#include <linux/dma/amd_xdma.h>20#include "mgb4_core.h"21#include "mgb4_trigger.h"22 23struct trigger_data {24	struct mgb4_dev *mgbdev;25	struct iio_trigger *trig;26};27 28static int trigger_read_raw(struct iio_dev *indio_dev,29			    struct iio_chan_spec const *chan, int *val,30			    int *val2, long mask)31{32	struct trigger_data *st = iio_priv(indio_dev);33 34	switch (mask) {35	case IIO_CHAN_INFO_RAW:36		if (iio_buffer_enabled(indio_dev))37			return -EBUSY;38		*val = mgb4_read_reg(&st->mgbdev->video, 0xA0);39 40		return IIO_VAL_INT;41	}42 43	return -EINVAL;44}45 46static int trigger_set_state(struct iio_trigger *trig, bool state)47{48	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);49	struct trigger_data *st = iio_priv(indio_dev);50	int irq = xdma_get_user_irq(st->mgbdev->xdev, 11);51 52	if (state)53		xdma_enable_user_irq(st->mgbdev->xdev, irq);54	else55		xdma_disable_user_irq(st->mgbdev->xdev, irq);56 57	return 0;58}59 60static const struct iio_trigger_ops trigger_ops = {61	.set_trigger_state = &trigger_set_state,62};63 64static const struct iio_info trigger_info = {65	.read_raw         = trigger_read_raw,66};67 68#define TRIGGER_CHANNEL(_si) {                    \69	.type = IIO_ACTIVITY,                         \70	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \71	.scan_index = _si,                            \72	.scan_type = {                                \73		.sign = 'u',                              \74		.realbits = 32,                           \75		.storagebits = 32,                        \76		.shift = 0,                               \77		.endianness = IIO_CPU                     \78	},                                            \79}80 81static const struct iio_chan_spec trigger_channels[] = {82	TRIGGER_CHANNEL(0),83	IIO_CHAN_SOFT_TIMESTAMP(1),84};85 86static irqreturn_t trigger_handler(int irq, void *p)87{88	struct iio_poll_func *pf = p;89	struct iio_dev *indio_dev = pf->indio_dev;90	struct trigger_data *st = iio_priv(indio_dev);91	struct {92		u32 data;93		s64 ts __aligned(8);94	} scan;95 96	scan.data = mgb4_read_reg(&st->mgbdev->video, 0xA0);97	mgb4_write_reg(&st->mgbdev->video, 0xA0, scan.data);98 99	iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);100	iio_trigger_notify_done(indio_dev->trig);101 102	mgb4_write_reg(&st->mgbdev->video, 0xB4, 1U << 11);103 104	return IRQ_HANDLED;105}106 107static int probe_trigger(struct iio_dev *indio_dev, int irq)108{109	int ret;110	struct trigger_data *st = iio_priv(indio_dev);111 112	st->trig = iio_trigger_alloc(&st->mgbdev->pdev->dev, "%s-dev%d",113				     indio_dev->name, iio_device_id(indio_dev));114	if (!st->trig)115		return -ENOMEM;116 117	ret = request_irq(irq, &iio_trigger_generic_data_rdy_poll, 0,118			  "mgb4-trigger", st->trig);119	if (ret)120		goto error_free_trig;121 122	st->trig->ops = &trigger_ops;123	iio_trigger_set_drvdata(st->trig, indio_dev);124	ret = iio_trigger_register(st->trig);125	if (ret)126		goto error_free_irq;127 128	indio_dev->trig = iio_trigger_get(st->trig);129 130	return 0;131 132error_free_irq:133	free_irq(irq, st->trig);134error_free_trig:135	iio_trigger_free(st->trig);136 137	return ret;138}139 140static void remove_trigger(struct iio_dev *indio_dev, int irq)141{142	struct trigger_data *st = iio_priv(indio_dev);143 144	iio_trigger_unregister(st->trig);145	free_irq(irq, st->trig);146	iio_trigger_free(st->trig);147}148 149struct iio_dev *mgb4_trigger_create(struct mgb4_dev *mgbdev)150{151	struct iio_dev *indio_dev;152	struct trigger_data *data;153	struct pci_dev *pdev = mgbdev->pdev;154	struct device *dev = &pdev->dev;155	int rv, irq;156 157	indio_dev = iio_device_alloc(dev, sizeof(*data));158	if (!indio_dev)159		return NULL;160 161	indio_dev->info = &trigger_info;162	indio_dev->name = "mgb4";163	indio_dev->modes = INDIO_DIRECT_MODE;164	indio_dev->channels = trigger_channels;165	indio_dev->num_channels = ARRAY_SIZE(trigger_channels);166 167	data = iio_priv(indio_dev);168	data->mgbdev = mgbdev;169 170	irq = xdma_get_user_irq(mgbdev->xdev, 11);171	rv = probe_trigger(indio_dev, irq);172	if (rv < 0) {173		dev_err(dev, "iio triggered setup failed\n");174		goto error_alloc;175	}176	rv = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,177					trigger_handler, NULL);178	if (rv < 0) {179		dev_err(dev, "iio triggered buffer setup failed\n");180		goto error_trigger;181	}182	rv = iio_device_register(indio_dev);183	if (rv < 0) {184		dev_err(dev, "iio device register failed\n");185		goto error_buffer;186	}187 188	return indio_dev;189 190error_buffer:191	iio_triggered_buffer_cleanup(indio_dev);192error_trigger:193	remove_trigger(indio_dev, irq);194error_alloc:195	iio_device_free(indio_dev);196 197	return NULL;198}199 200void mgb4_trigger_free(struct iio_dev *indio_dev)201{202	struct trigger_data *st = iio_priv(indio_dev);203 204	iio_device_unregister(indio_dev);205	iio_triggered_buffer_cleanup(indio_dev);206	remove_trigger(indio_dev, xdma_get_user_irq(st->mgbdev->xdev, 11));207	iio_device_free(indio_dev);208}209