linux/drivers/staging/media/atomisp/pci/runtime/queue/src/queue.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Support for Intel Camera Imaging ISP subsystem.
   4 * Copyright (c) 2015, Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 */
  15
  16#include "ia_css_queue.h"
  17#include <math_support.h>
  18#include <ia_css_circbuf.h>
  19#include <ia_css_circbuf_desc.h>
  20#include "queue_access.h"
  21
  22/*****************************************************************************
  23 * Queue Public APIs
  24 *****************************************************************************/
  25int ia_css_queue_local_init(ia_css_queue_t *qhandle, ia_css_queue_local_t *desc)
  26{
  27        if (NULL == qhandle || NULL == desc
  28            || NULL == desc->cb_elems || NULL == desc->cb_desc) {
  29                /* Invalid parameters, return error*/
  30                return -EINVAL;
  31        }
  32
  33        /* Mark the queue as Local */
  34        qhandle->type = IA_CSS_QUEUE_TYPE_LOCAL;
  35
  36        /* Create a local circular buffer queue*/
  37        ia_css_circbuf_create(&qhandle->desc.cb_local,
  38                              desc->cb_elems,
  39                              desc->cb_desc);
  40
  41        return 0;
  42}
  43
  44int ia_css_queue_remote_init(ia_css_queue_t *qhandle, ia_css_queue_remote_t *desc)
  45{
  46        if (NULL == qhandle || NULL == desc) {
  47                /* Invalid parameters, return error*/
  48                return -EINVAL;
  49        }
  50
  51        /* Mark the queue as remote*/
  52        qhandle->type = IA_CSS_QUEUE_TYPE_REMOTE;
  53
  54        /* Copy over the local queue descriptor*/
  55        qhandle->location = desc->location;
  56        qhandle->proc_id = desc->proc_id;
  57        qhandle->desc.remote.cb_desc_addr = desc->cb_desc_addr;
  58        qhandle->desc.remote.cb_elems_addr = desc->cb_elems_addr;
  59
  60        /* If queue is remote, we let the local processor
  61         * do its init, before using it. This is just to get us
  62         * started, we can remove this restriction as we go ahead
  63         */
  64
  65        return 0;
  66}
  67
  68int ia_css_queue_uninit(ia_css_queue_t *qhandle)
  69{
  70        if (!qhandle)
  71                return -EINVAL;
  72
  73        /* Load the required queue object */
  74        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
  75                /* Local queues are created. Destroy it*/
  76                ia_css_circbuf_destroy(&qhandle->desc.cb_local);
  77        }
  78
  79        return 0;
  80}
  81
  82int ia_css_queue_enqueue(ia_css_queue_t *qhandle, uint32_t item)
  83{
  84        int error = 0;
  85
  86        if (!qhandle)
  87                return -EINVAL;
  88
  89        /* 1. Load the required queue object */
  90        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
  91                /* Directly de-ref the object and
  92                 * operate on the queue
  93                 */
  94                if (ia_css_circbuf_is_full(&qhandle->desc.cb_local)) {
  95                        /* Cannot push the element. Return*/
  96                        return -ENOBUFS;
  97                }
  98
  99                /* Push the element*/
 100                ia_css_circbuf_push(&qhandle->desc.cb_local, item);
 101        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 102                ia_css_circbuf_desc_t cb_desc;
 103                ia_css_circbuf_elem_t cb_elem;
 104                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 105
 106                /* a. Load the queue cb_desc from remote */
 107                QUEUE_CB_DESC_INIT(&cb_desc);
 108                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 109                if (error != 0)
 110                        return error;
 111
 112                /* b. Operate on the queue */
 113                if (ia_css_circbuf_desc_is_full(&cb_desc))
 114                        return -ENOBUFS;
 115
 116                cb_elem.val = item;
 117
 118                error = ia_css_queue_item_store(qhandle, cb_desc.end, &cb_elem);
 119                if (error != 0)
 120                        return error;
 121
 122                cb_desc.end = (cb_desc.end + 1) % cb_desc.size;
 123
 124                /* c. Store the queue object */
 125                /* Set only fields requiring update with
 126                 * valid value. Avoids uncessary calls
 127                 * to load/store functions
 128                 */
 129                ignore_desc_flags = QUEUE_IGNORE_SIZE_START_STEP_FLAGS;
 130
 131                error = ia_css_queue_store(qhandle, &cb_desc, ignore_desc_flags);
 132                if (error != 0)
 133                        return error;
 134        }
 135
 136        return 0;
 137}
 138
 139int ia_css_queue_dequeue(ia_css_queue_t *qhandle, uint32_t *item)
 140{
 141        int error = 0;
 142
 143        if (!qhandle || NULL == item)
 144                return -EINVAL;
 145
 146        /* 1. Load the required queue object */
 147        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 148                /* Directly de-ref the object and
 149                 * operate on the queue
 150                 */
 151                if (ia_css_circbuf_is_empty(&qhandle->desc.cb_local)) {
 152                        /* Nothing to pop. Return empty queue*/
 153                        return -ENODATA;
 154                }
 155
 156                *item = ia_css_circbuf_pop(&qhandle->desc.cb_local);
 157        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 158                /* a. Load the queue from remote */
 159                ia_css_circbuf_desc_t cb_desc;
 160                ia_css_circbuf_elem_t cb_elem;
 161                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 162
 163                QUEUE_CB_DESC_INIT(&cb_desc);
 164
 165                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 166                if (error != 0)
 167                        return error;
 168
 169                /* b. Operate on the queue */
 170                if (ia_css_circbuf_desc_is_empty(&cb_desc))
 171                        return -ENODATA;
 172
 173                error = ia_css_queue_item_load(qhandle, cb_desc.start, &cb_elem);
 174                if (error != 0)
 175                        return error;
 176
 177                *item = cb_elem.val;
 178
 179                cb_desc.start = OP_std_modadd(cb_desc.start, 1, cb_desc.size);
 180
 181                /* c. Store the queue object */
 182                /* Set only fields requiring update with
 183                 * valid value. Avoids uncessary calls
 184                 * to load/store functions
 185                 */
 186                ignore_desc_flags = QUEUE_IGNORE_SIZE_END_STEP_FLAGS;
 187                error = ia_css_queue_store(qhandle, &cb_desc, ignore_desc_flags);
 188                if (error != 0)
 189                        return error;
 190        }
 191        return 0;
 192}
 193
 194int ia_css_queue_is_full(ia_css_queue_t *qhandle, bool *is_full)
 195{
 196        int error = 0;
 197
 198        if ((!qhandle) || (!is_full))
 199                return -EINVAL;
 200
 201        /* 1. Load the required queue object */
 202        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 203                /* Directly de-ref the object and
 204                 * operate on the queue
 205                 */
 206                *is_full = ia_css_circbuf_is_full(&qhandle->desc.cb_local);
 207                return 0;
 208        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 209                /* a. Load the queue from remote */
 210                ia_css_circbuf_desc_t cb_desc;
 211                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 212
 213                QUEUE_CB_DESC_INIT(&cb_desc);
 214                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 215                if (error != 0)
 216                        return error;
 217
 218                /* b. Operate on the queue */
 219                *is_full = ia_css_circbuf_desc_is_full(&cb_desc);
 220                return 0;
 221        }
 222
 223        return -EINVAL;
 224}
 225
 226int ia_css_queue_get_free_space(ia_css_queue_t *qhandle, uint32_t *size)
 227{
 228        int error = 0;
 229
 230        if ((!qhandle) || (!size))
 231                return -EINVAL;
 232
 233        /* 1. Load the required queue object */
 234        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 235                /* Directly de-ref the object and
 236                 * operate on the queue
 237                 */
 238                *size = ia_css_circbuf_get_free_elems(&qhandle->desc.cb_local);
 239                return 0;
 240        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 241                /* a. Load the queue from remote */
 242                ia_css_circbuf_desc_t cb_desc;
 243                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 244
 245                QUEUE_CB_DESC_INIT(&cb_desc);
 246                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 247                if (error != 0)
 248                        return error;
 249
 250                /* b. Operate on the queue */
 251                *size = ia_css_circbuf_desc_get_free_elems(&cb_desc);
 252                return 0;
 253        }
 254
 255        return -EINVAL;
 256}
 257
 258int ia_css_queue_get_used_space(ia_css_queue_t *qhandle, uint32_t *size)
 259{
 260        int error = 0;
 261
 262        if ((!qhandle) || (!size))
 263                return -EINVAL;
 264
 265        /* 1. Load the required queue object */
 266        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 267                /* Directly de-ref the object and
 268                 * operate on the queue
 269                 */
 270                *size = ia_css_circbuf_get_num_elems(&qhandle->desc.cb_local);
 271                return 0;
 272        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 273                /* a. Load the queue from remote */
 274                ia_css_circbuf_desc_t cb_desc;
 275                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 276
 277                QUEUE_CB_DESC_INIT(&cb_desc);
 278                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 279                if (error != 0)
 280                        return error;
 281
 282                /* b. Operate on the queue */
 283                *size = ia_css_circbuf_desc_get_num_elems(&cb_desc);
 284                return 0;
 285        }
 286
 287        return -EINVAL;
 288}
 289
 290int ia_css_queue_peek(ia_css_queue_t *qhandle, u32 offset, uint32_t *element)
 291{
 292        u32 num_elems = 0;
 293        int error = 0;
 294
 295        if ((!qhandle) || (!element))
 296                return -EINVAL;
 297
 298        /* 1. Load the required queue object */
 299        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 300                /* Directly de-ref the object and
 301                 * operate on the queue
 302                 */
 303                /* Check if offset is valid */
 304                num_elems = ia_css_circbuf_get_num_elems(&qhandle->desc.cb_local);
 305                if (offset > num_elems)
 306                        return -EINVAL;
 307
 308                *element = ia_css_circbuf_peek_from_start(&qhandle->desc.cb_local, (int)offset);
 309                return 0;
 310        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 311                /* a. Load the queue from remote */
 312                ia_css_circbuf_desc_t cb_desc;
 313                ia_css_circbuf_elem_t cb_elem;
 314                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 315
 316                QUEUE_CB_DESC_INIT(&cb_desc);
 317
 318                error =  ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 319                if (error != 0)
 320                        return error;
 321
 322                /* Check if offset is valid */
 323                num_elems = ia_css_circbuf_desc_get_num_elems(&cb_desc);
 324                if (offset > num_elems)
 325                        return -EINVAL;
 326
 327                offset = OP_std_modadd(cb_desc.start, offset, cb_desc.size);
 328                error = ia_css_queue_item_load(qhandle, (uint8_t)offset, &cb_elem);
 329                if (error != 0)
 330                        return error;
 331
 332                *element = cb_elem.val;
 333                return 0;
 334        }
 335
 336        return -EINVAL;
 337}
 338
 339int ia_css_queue_is_empty(ia_css_queue_t *qhandle, bool *is_empty)
 340{
 341        int error = 0;
 342
 343        if ((!qhandle) || (!is_empty))
 344                return -EINVAL;
 345
 346        /* 1. Load the required queue object */
 347        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 348                /* Directly de-ref the object and
 349                 * operate on the queue
 350                 */
 351                *is_empty = ia_css_circbuf_is_empty(&qhandle->desc.cb_local);
 352                return 0;
 353        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 354                /* a. Load the queue from remote */
 355                ia_css_circbuf_desc_t cb_desc;
 356                u32 ignore_desc_flags = QUEUE_IGNORE_STEP_FLAG;
 357
 358                QUEUE_CB_DESC_INIT(&cb_desc);
 359                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 360                if (error != 0)
 361                        return error;
 362
 363                /* b. Operate on the queue */
 364                *is_empty = ia_css_circbuf_desc_is_empty(&cb_desc);
 365                return 0;
 366        }
 367
 368        return -EINVAL;
 369}
 370
 371int ia_css_queue_get_size(ia_css_queue_t *qhandle, uint32_t *size)
 372{
 373        int error = 0;
 374
 375        if ((!qhandle) || (!size))
 376                return -EINVAL;
 377
 378        /* 1. Load the required queue object */
 379        if (qhandle->type == IA_CSS_QUEUE_TYPE_LOCAL) {
 380                /* Directly de-ref the object and
 381                 * operate on the queue
 382                 */
 383                /* Return maximum usable capacity */
 384                *size = ia_css_circbuf_get_size(&qhandle->desc.cb_local);
 385        } else if (qhandle->type == IA_CSS_QUEUE_TYPE_REMOTE) {
 386                /* a. Load the queue from remote */
 387                ia_css_circbuf_desc_t cb_desc;
 388                u32 ignore_desc_flags = QUEUE_IGNORE_START_END_STEP_FLAGS;
 389
 390                QUEUE_CB_DESC_INIT(&cb_desc);
 391
 392                error = ia_css_queue_load(qhandle, &cb_desc, ignore_desc_flags);
 393                if (error != 0)
 394                        return error;
 395
 396                /* Return maximum usable capacity */
 397                *size = cb_desc.size;
 398        }
 399
 400        return 0;
 401}
 402