kernel-brax3-ubuntu-touch/drivers/media/platform/mtk-isp/mtk-aov/mtk-aov-aee.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

218 lines
4.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*
* Author: ChenHung Yang <chenhung.yang@mediatek.com>
*/
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/module.h>
#include <aee.h>
#include "mtk-aov-drv.h"
#include "mtk-aov-aee.h"
#include "mtk-aov-core.h"
int aov_notify_aee(void)
{
pr_info("%s+\n", __func__);
pr_info("%s-\n", __func__);
return 0;
}
int proc_open(struct inode *inode, struct file *file)
{
struct mtk_aov *aov_dev = aov_core_get_device();
const char *name;
(void)try_module_get(THIS_MODULE);
name = file->f_path.dentry->d_name.name;
if (!strcmp(name, "kernel")) {
file->private_data = &aov_dev->aee_info.buffer;
} else {
module_put(THIS_MODULE);
return -EPERM;
}
pr_debug("%s: %s", __func__, name);
return 0;
}
static ssize_t proc_read(struct file *file, char __user *buf, size_t length,
loff_t *ppos)
{
struct proc_info *info = (struct proc_info *)file->private_data;
int bytes, remain;
remain = info->count - *ppos;
remain = (remain > length) ? length : remain;
if (remain <= 0) {
pr_debug("reach aov kernel node end");
info->count = 0;
return 0;
}
bytes = remain - copy_to_user(buf, info->buffer + *ppos, remain);
*ppos += bytes;
pr_debug("read aov kernel node bytes=%d, pos=%d\n", bytes, (int)*ppos);
return bytes;
}
int proc_close(struct inode *inode, struct file *file)
{
module_put(THIS_MODULE);
return 0;
}
static const struct proc_ops aee_ops = {
.proc_open = proc_open,
.proc_read = proc_read,
.proc_write = NULL,
.proc_release = proc_close
};
int aov_aee_init(struct mtk_aov *aov_dev)
{
struct aov_aee *aee_info = &aov_dev->aee_info;
struct aee_record *record = &aee_info->record;
// aed_set_extra_func(aov_notify_aee);
aee_info->entry = proc_mkdir("mtk_aov_debug", NULL);
if (aee_info->entry) {
aee_info->buffer.count = 0;
aee_info->kernel = proc_create(
"kernel", 0444, aee_info->entry, &aee_ops);
} else {
pr_info("%s: failed to create aov debug node\n", __func__);
}
spin_lock_init(&record->lock);
record->head = 0;
record->tail = 0;
return 0;
}
int aov_aee_record(struct mtk_aov *aov_dev,
int op_seq, enum aov_op op_code)
{
struct aov_aee *aee_info = &aov_dev->aee_info;
struct aee_record *record = &aee_info->record;
unsigned long flag;
struct op_data *data;
dev_dbg(aov_dev->dev, "%s+\n", __func__);
spin_lock_irqsave(&record->lock, flag);
data = &record->data[record->tail++];
if (record->tail >= AOV_AEE_MAX_RECORD_COUNT)
record->tail = 0;
if (record->head == record->tail) {
record->head++;
if (record->head >= AOV_AEE_MAX_RECORD_COUNT)
record->head = 0;
}
spin_unlock_irqrestore(&record->lock, flag);
data->op_time = ktime_get_boottime_ns();
data->op_seq = op_seq;
data->op_code = op_code;
dev_dbg(aov_dev->dev, "%s: record time(%lld), seq(%d), cmd(%d)\n",
__func__, data->op_time, data->op_seq, data->op_code);
dev_dbg(aov_dev->dev, "%s-\n", __func__);
return 0;
}
int aov_aee_flush(struct mtk_aov *aov_dev)
{
struct aov_aee *aee_info = &aov_dev->aee_info;
struct aee_record *record = &aee_info->record;
unsigned long flag;
struct proc_info *node;
int count;
int index;
int offset;
int remain;
int length;
dev_info(aov_dev->dev, "%s+\n", __func__);
spin_lock_irqsave(&record->lock, flag);
index = record->head;
count = record->tail - record->head;
if (count < 0)
count += AOV_AEE_MAX_RECORD_COUNT;
spin_unlock_irqrestore(&record->lock, flag);
dev_info(aov_dev->dev, "%s: flush index(%d), count(%d)\n",
__func__, index, count);
// flush to node buffer
node = &aee_info->buffer;
offset = node->count;
for (; count > 0; index++, count--) {
if (index >= AOV_AEE_MAX_RECORD_COUNT)
index = 0;
remain = AOV_AEE_MAX_BUFFER_SIZE - offset;
dev_dbg(aov_dev->dev, "%s: flush offset(%d), remain(%d)\n",
__func__, offset, remain);
if ((index >= 0) && (index < AOV_AEE_MAX_RECORD_COUNT) &&
(offset >= 0) && (offset < AOV_AEE_MAX_BUFFER_SIZE) &&
(remain > 0)) {
dev_dbg(aov_dev->dev, "%s: flush time(%lld), seq(%d), cmd(%d)\n",
__func__, record->data[index].op_time,
record->data[index].op_seq, record->data[index].op_code);
length = snprintf(&(node->buffer[offset]), remain,
"time(%lld), seq(%d), cmd(%d)\n",
record->data[index].op_time, record->data[index].op_seq,
record->data[index].op_code);
if (length < 0) {
dev_info(aov_dev->dev, "%s: failed to call snprintf(%d)",
__func__, length);
break;
}
offset += length;
} else {
break;
}
}
node->count = ((offset > AOV_AEE_MAX_BUFFER_SIZE) ?
AOV_AEE_MAX_BUFFER_SIZE : offset);
dev_info(aov_dev->dev, "%s-\n", __func__);
return 0;
}
int aov_aee_uninit(struct mtk_aov *aov_dev)
{
struct aov_aee *aee_info = &aov_dev->aee_info;
if (aee_info->kernel)
proc_remove(aee_info->kernel);
if (aee_info->entry)
proc_remove(aee_info->entry);
return 0;
}