0001
0002
0003
0004
0005
0006
0007 #include <linux/err.h>
0008 #include <linux/export.h>
0009 #include <linux/slab.h>
0010 #include <linux/module.h>
0011
0012 #include <linux/iio/iio.h>
0013 #include <linux/iio/consumer.h>
0014 #include <linux/iio/hw-consumer.h>
0015 #include <linux/iio/buffer_impl.h>
0016
0017
0018
0019
0020
0021
0022 struct iio_hw_consumer {
0023 struct list_head buffers;
0024 struct iio_channel *channels;
0025 };
0026
0027 struct hw_consumer_buffer {
0028 struct list_head head;
0029 struct iio_dev *indio_dev;
0030 struct iio_buffer buffer;
0031 long scan_mask[];
0032 };
0033
0034 static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer(
0035 struct iio_buffer *buffer)
0036 {
0037 return container_of(buffer, struct hw_consumer_buffer, buffer);
0038 }
0039
0040 static void iio_hw_buf_release(struct iio_buffer *buffer)
0041 {
0042 struct hw_consumer_buffer *hw_buf =
0043 iio_buffer_to_hw_consumer_buffer(buffer);
0044 kfree(hw_buf);
0045 }
0046
0047 static const struct iio_buffer_access_funcs iio_hw_buf_access = {
0048 .release = &iio_hw_buf_release,
0049 .modes = INDIO_BUFFER_HARDWARE,
0050 };
0051
0052 static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
0053 struct iio_hw_consumer *hwc, struct iio_dev *indio_dev)
0054 {
0055 struct hw_consumer_buffer *buf;
0056
0057 list_for_each_entry(buf, &hwc->buffers, head) {
0058 if (buf->indio_dev == indio_dev)
0059 return buf;
0060 }
0061
0062 buf = kzalloc(struct_size(buf, scan_mask, BITS_TO_LONGS(indio_dev->masklength)),
0063 GFP_KERNEL);
0064 if (!buf)
0065 return NULL;
0066
0067 buf->buffer.access = &iio_hw_buf_access;
0068 buf->indio_dev = indio_dev;
0069 buf->buffer.scan_mask = buf->scan_mask;
0070
0071 iio_buffer_init(&buf->buffer);
0072 list_add_tail(&buf->head, &hwc->buffers);
0073
0074 return buf;
0075 }
0076
0077
0078
0079
0080
0081
0082
0083 struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
0084 {
0085 struct hw_consumer_buffer *buf;
0086 struct iio_hw_consumer *hwc;
0087 struct iio_channel *chan;
0088 int ret;
0089
0090 hwc = kzalloc(sizeof(*hwc), GFP_KERNEL);
0091 if (!hwc)
0092 return ERR_PTR(-ENOMEM);
0093
0094 INIT_LIST_HEAD(&hwc->buffers);
0095
0096 hwc->channels = iio_channel_get_all(dev);
0097 if (IS_ERR(hwc->channels)) {
0098 ret = PTR_ERR(hwc->channels);
0099 goto err_free_hwc;
0100 }
0101
0102 chan = &hwc->channels[0];
0103 while (chan->indio_dev) {
0104 buf = iio_hw_consumer_get_buffer(hwc, chan->indio_dev);
0105 if (!buf) {
0106 ret = -ENOMEM;
0107 goto err_put_buffers;
0108 }
0109 set_bit(chan->channel->scan_index, buf->buffer.scan_mask);
0110 chan++;
0111 }
0112
0113 return hwc;
0114
0115 err_put_buffers:
0116 list_for_each_entry(buf, &hwc->buffers, head)
0117 iio_buffer_put(&buf->buffer);
0118 iio_channel_release_all(hwc->channels);
0119 err_free_hwc:
0120 kfree(hwc);
0121 return ERR_PTR(ret);
0122 }
0123 EXPORT_SYMBOL_GPL(iio_hw_consumer_alloc);
0124
0125
0126
0127
0128
0129 void iio_hw_consumer_free(struct iio_hw_consumer *hwc)
0130 {
0131 struct hw_consumer_buffer *buf, *n;
0132
0133 iio_channel_release_all(hwc->channels);
0134 list_for_each_entry_safe(buf, n, &hwc->buffers, head)
0135 iio_buffer_put(&buf->buffer);
0136 kfree(hwc);
0137 }
0138 EXPORT_SYMBOL_GPL(iio_hw_consumer_free);
0139
0140 static void devm_iio_hw_consumer_release(void *iio_hwc)
0141 {
0142 iio_hw_consumer_free(iio_hwc);
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev)
0155 {
0156 struct iio_hw_consumer *iio_hwc;
0157 int ret;
0158
0159 iio_hwc = iio_hw_consumer_alloc(dev);
0160 if (IS_ERR(iio_hwc))
0161 return iio_hwc;
0162
0163 ret = devm_add_action_or_reset(dev, devm_iio_hw_consumer_release,
0164 iio_hwc);
0165 if (ret)
0166 return ERR_PTR(ret);
0167
0168 return iio_hwc;
0169 }
0170 EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc);
0171
0172
0173
0174
0175
0176
0177
0178 int iio_hw_consumer_enable(struct iio_hw_consumer *hwc)
0179 {
0180 struct hw_consumer_buffer *buf;
0181 int ret;
0182
0183 list_for_each_entry(buf, &hwc->buffers, head) {
0184 ret = iio_update_buffers(buf->indio_dev, &buf->buffer, NULL);
0185 if (ret)
0186 goto err_disable_buffers;
0187 }
0188
0189 return 0;
0190
0191 err_disable_buffers:
0192 list_for_each_entry_continue_reverse(buf, &hwc->buffers, head)
0193 iio_update_buffers(buf->indio_dev, NULL, &buf->buffer);
0194 return ret;
0195 }
0196 EXPORT_SYMBOL_GPL(iio_hw_consumer_enable);
0197
0198
0199
0200
0201
0202 void iio_hw_consumer_disable(struct iio_hw_consumer *hwc)
0203 {
0204 struct hw_consumer_buffer *buf;
0205
0206 list_for_each_entry(buf, &hwc->buffers, head)
0207 iio_update_buffers(buf->indio_dev, NULL, &buf->buffer);
0208 }
0209 EXPORT_SYMBOL_GPL(iio_hw_consumer_disable);
0210
0211 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
0212 MODULE_DESCRIPTION("Hardware consumer buffer the IIO framework");
0213 MODULE_LICENSE("GPL v2");