diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/runtime/queue')
5 files changed, 911 insertions, 0 deletions
diff --git a/drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue.h b/drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue.h new file mode 100644 index 000000000000..6daeb060daf9 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue.h @@ -0,0 +1,175 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#ifndef __IA_CSS_QUEUE_H +#define __IA_CSS_QUEUE_H + +#include <platform_support.h> +#include <type_support.h> + +#include "ia_css_queue_comm.h" +#include "../src/queue_access.h" + +/* Local Queue object descriptor */ +struct ia_css_queue_local { + ia_css_circbuf_desc_t *cb_desc; /*Circbuf desc for local queues*/ + ia_css_circbuf_elem_t *cb_elems; /*Circbuf elements*/ +}; + +typedef struct ia_css_queue_local ia_css_queue_local_t; + +/* Handle for queue object*/ +typedef struct ia_css_queue ia_css_queue_t; + +/***************************************************************************** + * Queue Public APIs + *****************************************************************************/ +/* @brief Initialize a local queue instance. + * + * @param[out] qhandle. Handle to queue instance for use with API + * @param[in] desc. Descriptor with queue properties filled-in + * @return 0 - Successful init of local queue instance. + * @return EINVAL - Invalid argument. + * + */ +int ia_css_queue_local_init( + ia_css_queue_t *qhandle, + ia_css_queue_local_t *desc); + +/* @brief Initialize a remote queue instance + * + * @param[out] qhandle. Handle to queue instance for use with API + * @param[in] desc. Descriptor with queue properties filled-in + * @return 0 - Successful init of remote queue instance. + * @return EINVAL - Invalid argument. + */ +int ia_css_queue_remote_init( + ia_css_queue_t *qhandle, + ia_css_queue_remote_t *desc); + +/* @brief Uninitialize a queue instance + * + * @param[in] qhandle. Handle to queue instance + * @return 0 - Successful uninit. + * + */ +int ia_css_queue_uninit( + ia_css_queue_t *qhandle); + +/* @brief Enqueue an item in the queue instance + * + * @param[in] qhandle. Handle to queue instance + * @param[in] item. Object to be enqueued. + * @return 0 - Successful enqueue. + * @return EINVAL - Invalid argument. + * @return ENOBUFS - Queue is full. + * + */ +int ia_css_queue_enqueue( + ia_css_queue_t *qhandle, + uint32_t item); + +/* @brief Dequeue an item from the queue instance + * + * @param[in] qhandle. Handle to queue instance + * @param[out] item. Object to be dequeued into this item. + + * @return 0 - Successful dequeue. + * @return EINVAL - Invalid argument. + * @return ENODATA - Queue is empty. + * + */ +int ia_css_queue_dequeue( + ia_css_queue_t *qhandle, + uint32_t *item); + +/* @brief Check if the queue is empty + * + * @param[in] qhandle. Handle to queue instance + * @param[in] is_empty True if empty, False if not. + * @return 0 - Successful access state. + * @return EINVAL - Invalid argument. + * @return ENOSYS - Function not implemented. + * + */ +int ia_css_queue_is_empty( + ia_css_queue_t *qhandle, + bool *is_empty); + +/* @brief Check if the queue is full + * + * @param[in] qhandle. Handle to queue instance + * @param[in] is_full True if Full, False if not. + * @return 0 - Successfully access state. + * @return EINVAL - Invalid argument. + * @return ENOSYS - Function not implemented. + * + */ +int ia_css_queue_is_full( + ia_css_queue_t *qhandle, + bool *is_full); + +/* @brief Get used space in the queue + * + * @param[in] qhandle. Handle to queue instance + * @param[in] size Number of available elements in the queue + * @return 0 - Successfully access state. + * @return EINVAL - Invalid argument. + * + */ +int ia_css_queue_get_used_space( + ia_css_queue_t *qhandle, + uint32_t *size); + +/* @brief Get free space in the queue + * + * @param[in] qhandle. Handle to queue instance + * @param[in] size Number of free elements in the queue + * @return 0 - Successfully access state. + * @return EINVAL - Invalid argument. + * + */ +int ia_css_queue_get_free_space( + ia_css_queue_t *qhandle, + uint32_t *size); + +/* @brief Peek at an element in the queue + * + * @param[in] qhandle. Handle to queue instance + * @param[in] offset Offset of element to peek, + * starting from head of queue + * @param[in] element Value of element returned + * @return 0 - Successfully access state. + * @return EINVAL - Invalid argument. + * + */ +int ia_css_queue_peek( + ia_css_queue_t *qhandle, + u32 offset, + uint32_t *element); + +/* @brief Get the usable size for the queue + * + * @param[in] qhandle. Handle to queue instance + * @param[out] size Size value to be returned here. + * @return 0 - Successful get size. + * @return EINVAL - Invalid argument. + * @return ENOSYS - Function not implemented. + * + */ +int ia_css_queue_get_size( + ia_css_queue_t *qhandle, + uint32_t *size); + +#endif /* __IA_CSS_QUEUE_H */ diff --git a/drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue_comm.h b/drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue_comm.h new file mode 100644 index 000000000000..87fa4288d9a6 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/queue/interface/ia_css_queue_comm.h @@ -0,0 +1,53 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#ifndef __IA_CSS_QUEUE_COMM_H +#define __IA_CSS_QUEUE_COMM_H + +#include "type_support.h" +#include "ia_css_circbuf.h" +/***************************************************************************** + * Queue Public Data Structures + *****************************************************************************/ + +/* Queue location specifier */ +/* Avoiding enums to save space */ +#define IA_CSS_QUEUE_LOC_HOST 0 +#define IA_CSS_QUEUE_LOC_SP 1 +#define IA_CSS_QUEUE_LOC_ISP 2 + +/* Queue type specifier */ +/* Avoiding enums to save space */ +#define IA_CSS_QUEUE_TYPE_LOCAL 0 +#define IA_CSS_QUEUE_TYPE_REMOTE 1 + +/* for DDR Allocated queues, +allocate minimum these many elements. +DDR->SP' DMEM DMA transfer needs 32byte aligned address. +Since each element size is 4 bytes, 8 elements need to be +DMAed to access single element.*/ +#define IA_CSS_MIN_ELEM_COUNT 8 +#define IA_CSS_DMA_XFER_MASK (IA_CSS_MIN_ELEM_COUNT - 1) + +/* Remote Queue object descriptor */ +struct ia_css_queue_remote { + u32 cb_desc_addr; /*Circbuf desc address for remote queues*/ + u32 cb_elems_addr; /*Circbuf elements addr for remote queue*/ + u8 location; /* Cell location for queue */ + u8 proc_id; /* Processor id for queue access */ +}; + +typedef struct ia_css_queue_remote ia_css_queue_remote_t; + +#endif /* __IA_CSS_QUEUE_COMM_H */ diff --git a/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c new file mode 100644 index 000000000000..dd79c6f180af --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c @@ -0,0 +1,422 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include "ia_css_queue.h" +#include <math_support.h> +#include <ia_css_circbuf.h> +#include <ia_css_circbuf_desc.h> +#include "queue_access.h" + +/***************************************************************************** + * Queue Public APIs + *****************************************************************************/ +int ia_css_queue_local_init( + ia_css_queue_t *qhandle, + ia_css_queue_local_t *desc) +{ + if (NULL == qhandle || NULL == desc + || NULL == desc->cb_elems || NULL == desc->cb_desc) { + /* Invalid parameters, return error*/ + return EINVAL; + } + + /* Mark the queue as Local */ + qhandle->type = IA_CSS_QUEUE_TYPE_LOCAL; + + /* Create a local circular buffer queue*/ + ia_css_circbuf_create(&qhandle->desc.cb_local, + desc->cb_elems, + desc->cb_desc); + + return 0; +} + +int ia_css_queue_remote_init( + ia_css_queue_t *qhandle, + ia_css_queue_remote_t *desc) +{ + if (NULL == qhandle || NULL == desc) { + /* Invalid parameters, return error*/ + return EINVAL; + } + + /* Mark the queue as remote*/ + qhandle->type = IA_CSS_QUEUE_TYPE_REMOTE; + + /* Copy over the local queue descriptor*/ + qhandle->location = desc->location; + qhandle->proc_id = desc->proc_id; + qhandle->desc.remote.cb_desc_addr = desc->cb_desc_addr; + qhandle->desc.remote.cb_elems_addr = desc->cb_elems_addr; + + /* If queue is remote, we let the local processor + * do its init, before using it. This is just to get us + * started, we can remove this restriction as we go ahead + */ + + return 0; +} + +int ia_css_queue_uninit( + ia_css_queue_t *qhandle) +{ + if (!qhandle) + return EINVAL; + + /* Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Local queues are created. Destroy it*/ + ia_css_circbuf_destroy(&qhandle->desc.cb_local); + } + + return 0; +} + +int ia_css_queue_enqueue( + ia_css_queue_t *qhandle, + uint32_t item) +{ + int error = 0; + + if (!qhandle) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + if (ia_css_circbuf_is_full(&qhandle->desc.cb_local)) { + /* Cannot push the element. Return*/ + return ENOBUFS; + } + + /* Push the element*/ + ia_css_circbuf_push(&qhandle->desc.cb_local, item); + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + ia_css_circbuf_desc_t cb_desc; + ia_css_circbuf_elem_t cb_elem; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + /* a. Load the queue cb_desc from remote */ + QUEUE_CB_DESC_INIT(&cb_desc); + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* b. Operate on the queue */ + if (ia_css_circbuf_desc_is_full(&cb_desc)) + return ENOBUFS; + + cb_elem.val = item; + + error = ia_css_queue_item_store(qhandle, cb_desc.end, &cb_elem); + if (error != 0) + return error; + + cb_desc.end = (cb_desc.end + 1) % cb_desc.size; + + /* c. Store the queue object */ + /* Set only fields requiring update with + * valid value. Avoids uncessary calls + * to load/store functions + */ + ignore_desc_flags = QUEUE_IGNORE_SIZE_START_STEP_FLAGS; + + error = ia_css_queue_store(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + } + + return 0; +} + +int ia_css_queue_dequeue( + ia_css_queue_t *qhandle, + uint32_t *item) +{ + int error = 0; + + if (!qhandle || NULL == item) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + if (ia_css_circbuf_is_empty(&qhandle->desc.cb_local)) { + /* Nothing to pop. Return empty queue*/ + return ENODATA; + } + + *item = ia_css_circbuf_pop(&qhandle->desc.cb_local); + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + ia_css_circbuf_elem_t cb_elem; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + QUEUE_CB_DESC_INIT(&cb_desc); + + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* b. Operate on the queue */ + if (ia_css_circbuf_desc_is_empty(&cb_desc)) + return ENODATA; + + error = ia_css_queue_item_load(qhandle, cb_desc.start, &cb_elem); + if (error != 0) + return error; + + *item = cb_elem.val; + + cb_desc.start = OP_std_modadd(cb_desc.start, 1, cb_desc.size); + + /* c. Store the queue object */ + /* Set only fields requiring update with + * valid value. Avoids uncessary calls + * to load/store functions + */ + ignore_desc_flags = QUEUE_IGNORE_SIZE_END_STEP_FLAGS; + error = ia_css_queue_store(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + } + return 0; +} + +int ia_css_queue_is_full( + ia_css_queue_t *qhandle, + bool *is_full) +{ + int error = 0; + + if ((!qhandle) || (!is_full)) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + *is_full = ia_css_circbuf_is_full(&qhandle->desc.cb_local); + return 0; + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + QUEUE_CB_DESC_INIT(&cb_desc); + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* b. Operate on the queue */ + *is_full = ia_css_circbuf_desc_is_full(&cb_desc); + return 0; + } + + return EINVAL; +} + +int ia_css_queue_get_free_space( + ia_css_queue_t *qhandle, + uint32_t *size) +{ + int error = 0; + + if ((!qhandle) || (!size)) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + *size = ia_css_circbuf_get_free_elems(&qhandle->desc.cb_local); + return 0; + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + QUEUE_CB_DESC_INIT(&cb_desc); + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* b. Operate on the queue */ + *size = ia_css_circbuf_desc_get_free_elems(&cb_desc); + return 0; + } + + return EINVAL; +} + +int ia_css_queue_get_used_space( + ia_css_queue_t *qhandle, + uint32_t *size) +{ + int error = 0; + + if ((!qhandle) || (!size)) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + *size = ia_css_circbuf_get_num_elems(&qhandle->desc.cb_local); + return 0; + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + QUEUE_CB_DESC_INIT(&cb_desc); + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* b. Operate on the queue */ + *size = ia_css_circbuf_desc_get_num_elems(&cb_desc); + return 0; + } + + return EINVAL; +} + +int ia_css_queue_peek( + ia_css_queue_t *qhandle, + u32 offset, + uint32_t *element) +{ + u32 num_elems = 0; + int error = 0; + + if ((!qhandle) || (!element)) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + /* Check if offset is valid */ + num_elems = ia_css_circbuf_get_num_elems(&qhandle->desc.cb_local); + if (offset > num_elems) + return EINVAL; + + *element = ia_css_circbuf_peek_from_start(&qhandle->desc.cb_local, (int)offset); + return 0; + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + ia_css_circbuf_elem_t cb_elem; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + QUEUE_CB_DESC_INIT(&cb_desc); + + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* Check if offset is valid */ + num_elems = ia_css_circbuf_desc_get_num_elems(&cb_desc); + if (offset > num_elems) + return EINVAL; + + offset = OP_std_modadd(cb_desc.start, offset, cb_desc.size); + error = ia_css_queue_item_load(qhandle, (uint8_t)offset, &cb_elem); + if (error != 0) + return error; + + *element = cb_elem.val; + return 0; + } + + return EINVAL; +} + +int ia_css_queue_is_empty( + ia_css_queue_t *qhandle, + bool *is_empty) +{ + int error = 0; + + if ((!qhandle) || (!is_empty)) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + *is_empty = ia_css_circbuf_is_empty(&qhandle->desc.cb_local); + return 0; + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG; + + QUEUE_CB_DESC_INIT(&cb_desc); + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* b. Operate on the queue */ + *is_empty = ia_css_circbuf_desc_is_empty(&cb_desc); + return 0; + } + + return EINVAL; +} + +int ia_css_queue_get_size( + ia_css_queue_t *qhandle, + uint32_t *size) +{ + int error = 0; + + if ((!qhandle) || (!size)) + return EINVAL; + + /* 1. Load the required queue object */ + if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) { + /* Directly de-ref the object and + * operate on the queue + */ + /* Return maximum usable capacity */ + *size = ia_css_circbuf_get_size(&qhandle->desc.cb_local); + } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) { + /* a. Load the queue from remote */ + ia_css_circbuf_desc_t cb_desc; + u32 ignore_desc_flags = QUEUE_IGNORE_START_END_STEP_FLAGS; + + QUEUE_CB_DESC_INIT(&cb_desc); + + error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags); + if (error != 0) + return error; + + /* Return maximum usable capacity */ + *size = cb_desc.size; + } + + return 0; +} diff --git a/drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.c b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.c new file mode 100644 index 000000000000..1e8d3eb82eab --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.c @@ -0,0 +1,176 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include "type_support.h" +#include "queue_access.h" +#include "ia_css_circbuf.h" +#include "sp.h" +#include "memory_access.h" +#include "assert_support.h" + +int ia_css_queue_load( + struct ia_css_queue *rdesc, + ia_css_circbuf_desc_t *cb_desc, + uint32_t ignore_desc_flags) +{ + if (!rdesc || !cb_desc) + return EINVAL; + + if (rdesc->location == IA_CSS_QUEUE_LOC_SP) { + assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG)) { + cb_desc->size = sp_dmem_load_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, size)); + + if (cb_desc->size == 0) { + /* Adding back the workaround which was removed + while refactoring queues. When reading size + through sp_dmem_load_*, sometimes we get back + the value as zero. This causes division by 0 + exception as the size is used in a modular + division operation. */ + return EDOM; + } + } + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG)) + cb_desc->start = sp_dmem_load_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, start)); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG)) + cb_desc->end = sp_dmem_load_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, end)); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG)) + cb_desc->step = sp_dmem_load_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, step)); + + } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) { + /* doing DMA transfer of entire structure */ + mmgr_load(rdesc->desc.remote.cb_desc_addr, + (void *)cb_desc, + sizeof(ia_css_circbuf_desc_t)); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) { + /* Not supported yet */ + return ENOTSUP; + } + + return 0; +} + +int ia_css_queue_store( + struct ia_css_queue *rdesc, + ia_css_circbuf_desc_t *cb_desc, + uint32_t ignore_desc_flags) +{ + if (!rdesc || !cb_desc) + return EINVAL; + + if (rdesc->location == IA_CSS_QUEUE_LOC_SP) { + assert(ignore_desc_flags <= QUEUE_IGNORE_DESC_FLAGS_MAX); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_SIZE_FLAG)) + sp_dmem_store_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, size), + cb_desc->size); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_START_FLAG)) + sp_dmem_store_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, start), + cb_desc->start); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_END_FLAG)) + sp_dmem_store_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, end), + cb_desc->end); + + if (0 == (ignore_desc_flags & QUEUE_IGNORE_STEP_FLAG)) + sp_dmem_store_uint8(rdesc->proc_id, + rdesc->desc.remote.cb_desc_addr + + offsetof(ia_css_circbuf_desc_t, step), + cb_desc->step); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) { + /* doing DMA transfer of entire structure */ + mmgr_store(rdesc->desc.remote.cb_desc_addr, + (void *)cb_desc, + sizeof(ia_css_circbuf_desc_t)); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) { + /* Not supported yet */ + return ENOTSUP; + } + + return 0; +} + +int ia_css_queue_item_load( + struct ia_css_queue *rdesc, + u8 position, + ia_css_circbuf_elem_t *item) +{ + if (!rdesc || !item) + return EINVAL; + + if (rdesc->location == IA_CSS_QUEUE_LOC_SP) { + sp_dmem_load(rdesc->proc_id, + rdesc->desc.remote.cb_elems_addr + + position * sizeof(ia_css_circbuf_elem_t), + item, + sizeof(ia_css_circbuf_elem_t)); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) { + mmgr_load(rdesc->desc.remote.cb_elems_addr + + position * sizeof(ia_css_circbuf_elem_t), + (void *)item, + sizeof(ia_css_circbuf_elem_t)); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) { + /* Not supported yet */ + return ENOTSUP; + } + + return 0; +} + +int ia_css_queue_item_store( + struct ia_css_queue *rdesc, + u8 position, + ia_css_circbuf_elem_t *item) +{ + if (!rdesc || !item) + return EINVAL; + + if (rdesc->location == IA_CSS_QUEUE_LOC_SP) { + sp_dmem_store(rdesc->proc_id, + rdesc->desc.remote.cb_elems_addr + + position * sizeof(ia_css_circbuf_elem_t), + item, + sizeof(ia_css_circbuf_elem_t)); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_HOST) { + mmgr_store(rdesc->desc.remote.cb_elems_addr + + position * sizeof(ia_css_circbuf_elem_t), + (void *)item, + sizeof(ia_css_circbuf_elem_t)); + } else if (rdesc->location == IA_CSS_QUEUE_LOC_ISP) { + /* Not supported yet */ + return ENOTSUP; + } + + return 0; +} diff --git a/drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.h b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.h new file mode 100644 index 000000000000..884c55a754d1 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/queue/src/queue_access.h @@ -0,0 +1,85 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#ifndef __QUEUE_ACCESS_H +#define __QUEUE_ACCESS_H + +#include <type_support.h> +#include <ia_css_queue_comm.h> +#include <ia_css_circbuf.h> +#include <error_support.h> + +#define QUEUE_IGNORE_START_FLAG 0x0001 +#define QUEUE_IGNORE_END_FLAG 0x0002 +#define QUEUE_IGNORE_SIZE_FLAG 0x0004 +#define QUEUE_IGNORE_STEP_FLAG 0x0008 +#define QUEUE_IGNORE_DESC_FLAGS_MAX 0x000f + +#define QUEUE_IGNORE_SIZE_START_STEP_FLAGS \ + (QUEUE_IGNORE_SIZE_FLAG | \ + QUEUE_IGNORE_START_FLAG | \ + QUEUE_IGNORE_STEP_FLAG) + +#define QUEUE_IGNORE_SIZE_END_STEP_FLAGS \ + (QUEUE_IGNORE_SIZE_FLAG | \ + QUEUE_IGNORE_END_FLAG | \ + QUEUE_IGNORE_STEP_FLAG) + +#define QUEUE_IGNORE_START_END_STEP_FLAGS \ + (QUEUE_IGNORE_START_FLAG | \ + QUEUE_IGNORE_END_FLAG | \ + QUEUE_IGNORE_STEP_FLAG) + +#define QUEUE_CB_DESC_INIT(cb_desc) \ + do { \ + (cb_desc)->size = 0; \ + (cb_desc)->step = 0; \ + (cb_desc)->start = 0; \ + (cb_desc)->end = 0; \ + } while (0) + +struct ia_css_queue { + u8 type; /* Specify remote/local type of access */ + u8 location; /* Cell location for queue */ + u8 proc_id; /* Processor id for queue access */ + union { + ia_css_circbuf_t cb_local; + struct { + u32 cb_desc_addr; /*Circbuf desc address for remote queues*/ + u32 cb_elems_addr; /*Circbuf elements addr for remote queue*/ + } remote; + } desc; +}; + +int ia_css_queue_load( + struct ia_css_queue *rdesc, + ia_css_circbuf_desc_t *cb_desc, + uint32_t ignore_desc_flags); + +int ia_css_queue_store( + struct ia_css_queue *rdesc, + ia_css_circbuf_desc_t *cb_desc, + uint32_t ignore_desc_flags); + +int ia_css_queue_item_load( + struct ia_css_queue *rdesc, + u8 position, + ia_css_circbuf_elem_t *item); + +int ia_css_queue_item_store( + struct ia_css_queue *rdesc, + u8 position, + ia_css_circbuf_elem_t *item); + +#endif /* __QUEUE_ACCESS_H */ |