blob: d4053719929288eca3ece0e5f432411edee14232 [file] [log] [blame]
Kyle Swensoncc33c242022-05-16 10:38:04 -06001/*
2 * ./kernel_modules/qcom-adc/adc-averaging.c
3 *
4 * This file does some basic FIR averaging on a fifo; it is intended to be used
5 * with the ADS7924 device driver
6 *
7 * Author: Cradlepoint Technology, Inc. <source@cradlepoint.com>
8 * Kyle Swenson <kswenson@cradlepoint.com>
9 *
10 * Copyright 2017 Cradlepoint Technology, Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 */
Kyle Swenson89648b22022-05-16 10:56:50 -060022#include <linux/device.h>
Kyle Swensoncc33c242022-05-16 10:38:04 -060023#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/err.h>
26#include <linux/slab.h>
27#include "adc-averaging.h"
28
29
30void free_adc_channel(struct adc_channel *ch)
31{
Kyle Swenson89648b22022-05-16 10:56:50 -060032 mutex_lock(&ch->lock);
Kyle Swensoncc33c242022-05-16 10:38:04 -060033 if (ch->samples) {
Kyle Swenson89648b22022-05-16 10:56:50 -060034 devm_kfree(ch->parent, ch->samples);
35 ch->samples = NULL;
Kyle Swensoncc33c242022-05-16 10:38:04 -060036 }
Kyle Swenson89648b22022-05-16 10:56:50 -060037 mutex_unlock(&ch->lock);
38 mutex_destroy(&ch->lock);
39 devm_kfree(ch->parent, ch);
Kyle Swensoncc33c242022-05-16 10:38:04 -060040}
41
Kyle Swenson89648b22022-05-16 10:56:50 -060042struct adc_channel *create_adc_channel(struct device * dev, uint16_t fifo_length)
Kyle Swensoncc33c242022-05-16 10:38:04 -060043{
44 struct adc_channel *ch;
45 if (fifo_length >= MAX_SAMPLE_LENGTH) {
46 printk(KERN_ALERT "Requested a ADC buffer length (%u) exceedes max (%u)\n", fifo_length, MAX_SAMPLE_LENGTH);
47 return NULL;
48
49 }
Kyle Swenson89648b22022-05-16 10:56:50 -060050 ch = devm_kzalloc(dev, sizeof(struct adc_channel), GFP_KERNEL);
51 if (!ch)
Kyle Swensoncc33c242022-05-16 10:38:04 -060052 return NULL;
Kyle Swenson89648b22022-05-16 10:56:50 -060053
54 ch->samples = devm_kzalloc(dev, sizeof(uint16_t) * fifo_length, GFP_KERNEL);
55 if (!ch->samples)
Kyle Swensoncc33c242022-05-16 10:38:04 -060056 return NULL;
Kyle Swenson89648b22022-05-16 10:56:50 -060057
Kyle Swensoncc33c242022-05-16 10:38:04 -060058 ch->total_length = fifo_length;
59 ch->index = 0;
60 mutex_init(&ch->lock);
Kyle Swenson89648b22022-05-16 10:56:50 -060061 ch->parent = dev;
Kyle Swensoncc33c242022-05-16 10:38:04 -060062 return ch;
63}
64
65uint16_t compute_average(struct adc_channel *ch)
66{
67 uint32_t sum=0;
68 uint16_t average;
69 int i = 0;
70 mutex_lock(&ch->lock);
71 for (i = 0; i < ch->total_length; i++) {
72 sum += ch->samples[i];
73 }
74 average = DIV_ROUND_CLOSEST(sum, ch->total_length);
75 mutex_unlock(&ch->lock);
76 return average;
77}
78
79void add_sample(struct adc_channel *ch, uint16_t sample)
80{
81 mutex_lock(&ch->lock);
82 ch->samples[ch->index++] = sample;
83 if (ch->index >= ch->total_length)
84 ch->index = 0;
85 mutex_unlock(&ch->lock);
86}