Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.14.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2021-2023 Digiteq Automotive
  4 *     author: Martin Tuma <martin.tuma@digiteqautomotive.com>
  5 *
  6 * This module handles the IIO trigger device. The card has two signal inputs
  7 * for event triggers that can be used to record events related to the video
  8 * stream. A standard linux IIO device with triggered buffer capability is
  9 * created and configured that can be used to fetch the events with the same
 10 * 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	else
 55		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}