Files
vi-kernel/vvcam/isp/isp_irq_queue.c
2023-03-05 22:30:11 +08:00

256 lines
7.5 KiB
C
Executable File

/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2020 VeriSilicon Holdings Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (c) 2020 VeriSilicon Holdings Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program;
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#ifdef __KERNEL__
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#else
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#endif
#include "isp_irq_queue.h"
#include "isp_ioctl.h"
//enqueue
int isp_irq_enqueue(isp_mis_t *new,isp_mis_t* head)
{
#ifdef __KERNEL__
isp_mis_t* new_node = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL); //create new node
if (new == NULL || head == NULL) {
return -1;
}
new_node->val = new->val;
new_node->irq_src = new->irq_src;
/*printk("%s: new_node %px irq_src %d", __func__, new_node, new->irq_src);*/
INIT_LIST_HEAD(&new_node->list);
list_add_tail(&new_node->list, &head->list); //append to tail
#endif
return 0;
}
//dequeue && release memory
int isp_irq_dequeue(isp_mis_t* data, isp_mis_t* head)
{
#ifdef __KERNEL__
isp_mis_t* entry;
if (data == NULL || head == NULL) {
//printk("%s: input wrong parameter\n", __func__);
return -1;
}
if (list_empty(&head->list)) {
//printk("%s: There is no node\n", __func__);
return -1;
}
entry = list_first_entry(&head->list, isp_mis_t, list);
/*printk("%s: entry %px irq_src %d", __func__, entry, entry->irq_src);*/
data->val = entry->val;
data->irq_src = entry->irq_src;
list_del_init(&entry->list);
kfree(entry);
#endif
return 0;
}
bool isp_irq_is_queue_empty( isp_mis_t* head)
{
#ifdef __KERNEL__
return list_empty(&head->list);
#endif
return 0;
}
int isp_irq_create_circle_queue(isp_mis_list_t* pCList, int number)
{
#ifdef __KERNEL__
int i;
isp_mis_t* pMisNode;
if (pCList == NULL || number <= 0) {
isp_info("%s: create circle queue failed\n", __func__);
return -1;
}
if (pCList->pHead == NULL) {
pCList->pHead = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL);
INIT_LIST_HEAD(&pCList->pHead->list);
pCList->pRead = pCList->pHead;
pCList->pWrite = pCList->pHead;
}
isp_info("%s:pHead %px\n", __func__, pCList->pHead);
for (i = 0; i < number - 1; i++) {
pMisNode = (isp_mis_t*)kmalloc(sizeof(isp_mis_t), GFP_KERNEL);
INIT_LIST_HEAD(&pMisNode->list);
list_add_tail(&pMisNode->list, &pCList->pHead->list);
isp_info("%s:pMisNode %px\n", __func__, pMisNode);
}
#endif
return 0;
}
int isp_irq_destroy_circle_queue(isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
isp_mis_t* pMisNode;
if ((pCList == NULL) || (pCList->pHead == NULL) ) {
isp_err("%s: destroy circle queue failed. pClist %px\n", __func__, pCList);
return -1;
}
while(!list_empty(&pCList->pHead->list)) {
pMisNode = list_first_entry(&pCList->pHead->list, isp_mis_t, list);
isp_info("%s:pMisNode %px\n", __func__, pMisNode);
list_del(&pMisNode->list);
kfree(pMisNode);
pMisNode = NULL;
}
isp_info("%s:pHead %px\n", __func__, pCList->pHead);
kfree(pCList->pHead);
pCList->pHead = NULL;
pCList->pRead = NULL;
pCList->pWrite = NULL;
#endif
return 0;
}
int isp_irq_read_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
//isp_mis_t* pReadEntry;
if (pCList == NULL) {
isp_err("%s: can not read circle queue\n", __func__);
return -1;
}
if (pCList->pRead == pCList->pWrite) {
/*printk("%s: There is no irq mis data\n", __func__);*/
return -1;
}
data->val = pCList->pRead->val;
data->irq_src = pCList->pRead->irq_src;
/*printk("%s: entry %px irq_src %d, msi %08x\n", __func__, pCList->pRead, data->irq_src, data->val);*/
/*Get the next entry that link with read entry list*/
/*Update read pointer to next entry*/
pCList->pRead = list_first_entry(&pCList->pRead->list, isp_mis_t, list);
//pCList->pRead = pReadEntry;
#endif
return 0;
}
int isp_irq_write_circle_queue(isp_mis_t* data, isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
isp_mis_t* pWriteEntry;
if (pCList == NULL) {
isp_err("%s: can not read circle queue\n", __func__);
return -1;
}
pCList->pWrite->val = data->val;
pCList->pWrite->irq_src = data->irq_src;
/*printk("%s: entry %px irq_src %d, msi %08x\n", __func__, pCList->pWrite, data->irq_src, data->val);*/
/*get the next write entry pointer that link with the write entry list*/
pWriteEntry = list_first_entry(&pCList->pWrite->list, isp_mis_t, list);
/*Update write pointer to point next entry*/
pCList->pWrite = pWriteEntry;
#endif
return 0;
}
int isp_irq_reset_circle_queue(isp_mis_list_t* pCList)
{
#ifdef __KERNEL__
if (pCList == NULL) {
isp_err("%s: can not reset circle queue\n", __func__);
return -1;
}
pCList->pRead = pCList->pHead;
pCList->pWrite = pCList->pHead;
#endif
return 0;
}