root/drivers/media/platform/qcom/venus/hfi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_codec_type
  2. hfi_core_init
  3. hfi_core_deinit
  4. hfi_core_suspend
  5. hfi_core_resume
  6. hfi_core_trigger_ssr
  7. hfi_core_ping
  8. wait_session_msg
  9. hfi_session_create
  10. hfi_session_init
  11. hfi_session_destroy
  12. hfi_session_deinit
  13. hfi_session_start
  14. hfi_session_stop
  15. hfi_session_continue
  16. hfi_session_abort
  17. hfi_session_load_res
  18. hfi_session_unload_res
  19. hfi_session_flush
  20. hfi_session_set_buffers
  21. hfi_session_unset_buffers
  22. hfi_session_get_property
  23. hfi_session_set_property
  24. hfi_session_process_buf
  25. hfi_isr_thread
  26. hfi_isr
  27. hfi_create
  28. hfi_destroy

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
   4  * Copyright (C) 2017 Linaro Ltd.
   5  */
   6 #include <linux/slab.h>
   7 #include <linux/mutex.h>
   8 #include <linux/list.h>
   9 #include <linux/completion.h>
  10 #include <linux/platform_device.h>
  11 #include <linux/videodev2.h>
  12 
  13 #include "core.h"
  14 #include "hfi.h"
  15 #include "hfi_cmds.h"
  16 #include "hfi_venus.h"
  17 
  18 #define TIMEOUT         msecs_to_jiffies(1000)
  19 
  20 static u32 to_codec_type(u32 pixfmt)
  21 {
  22         switch (pixfmt) {
  23         case V4L2_PIX_FMT_H264:
  24         case V4L2_PIX_FMT_H264_NO_SC:
  25                 return HFI_VIDEO_CODEC_H264;
  26         case V4L2_PIX_FMT_H263:
  27                 return HFI_VIDEO_CODEC_H263;
  28         case V4L2_PIX_FMT_MPEG1:
  29                 return HFI_VIDEO_CODEC_MPEG1;
  30         case V4L2_PIX_FMT_MPEG2:
  31                 return HFI_VIDEO_CODEC_MPEG2;
  32         case V4L2_PIX_FMT_MPEG4:
  33                 return HFI_VIDEO_CODEC_MPEG4;
  34         case V4L2_PIX_FMT_VC1_ANNEX_G:
  35         case V4L2_PIX_FMT_VC1_ANNEX_L:
  36                 return HFI_VIDEO_CODEC_VC1;
  37         case V4L2_PIX_FMT_VP8:
  38                 return HFI_VIDEO_CODEC_VP8;
  39         case V4L2_PIX_FMT_VP9:
  40                 return HFI_VIDEO_CODEC_VP9;
  41         case V4L2_PIX_FMT_XVID:
  42                 return HFI_VIDEO_CODEC_DIVX;
  43         case V4L2_PIX_FMT_HEVC:
  44                 return HFI_VIDEO_CODEC_HEVC;
  45         default:
  46                 return 0;
  47         }
  48 }
  49 
  50 int hfi_core_init(struct venus_core *core)
  51 {
  52         int ret = 0;
  53 
  54         mutex_lock(&core->lock);
  55 
  56         if (core->state >= CORE_INIT)
  57                 goto unlock;
  58 
  59         reinit_completion(&core->done);
  60 
  61         ret = core->ops->core_init(core);
  62         if (ret)
  63                 goto unlock;
  64 
  65         ret = wait_for_completion_timeout(&core->done, TIMEOUT);
  66         if (!ret) {
  67                 ret = -ETIMEDOUT;
  68                 goto unlock;
  69         }
  70 
  71         ret = 0;
  72 
  73         if (core->error != HFI_ERR_NONE) {
  74                 ret = -EIO;
  75                 goto unlock;
  76         }
  77 
  78         core->state = CORE_INIT;
  79 unlock:
  80         mutex_unlock(&core->lock);
  81         return ret;
  82 }
  83 
  84 int hfi_core_deinit(struct venus_core *core, bool blocking)
  85 {
  86         int ret = 0, empty;
  87 
  88         mutex_lock(&core->lock);
  89 
  90         if (core->state == CORE_UNINIT)
  91                 goto unlock;
  92 
  93         empty = list_empty(&core->instances);
  94 
  95         if (!empty && !blocking) {
  96                 ret = -EBUSY;
  97                 goto unlock;
  98         }
  99 
 100         if (!empty) {
 101                 mutex_unlock(&core->lock);
 102                 wait_var_event(&core->insts_count,
 103                                !atomic_read(&core->insts_count));
 104                 mutex_lock(&core->lock);
 105         }
 106 
 107         ret = core->ops->core_deinit(core);
 108 
 109         if (!ret)
 110                 core->state = CORE_UNINIT;
 111 
 112 unlock:
 113         mutex_unlock(&core->lock);
 114         return ret;
 115 }
 116 
 117 int hfi_core_suspend(struct venus_core *core)
 118 {
 119         if (core->state != CORE_INIT)
 120                 return 0;
 121 
 122         return core->ops->suspend(core);
 123 }
 124 
 125 int hfi_core_resume(struct venus_core *core, bool force)
 126 {
 127         if (!force && core->state != CORE_INIT)
 128                 return 0;
 129 
 130         return core->ops->resume(core);
 131 }
 132 
 133 int hfi_core_trigger_ssr(struct venus_core *core, u32 type)
 134 {
 135         return core->ops->core_trigger_ssr(core, type);
 136 }
 137 
 138 int hfi_core_ping(struct venus_core *core)
 139 {
 140         int ret;
 141 
 142         mutex_lock(&core->lock);
 143 
 144         ret = core->ops->core_ping(core, 0xbeef);
 145         if (ret)
 146                 goto unlock;
 147 
 148         ret = wait_for_completion_timeout(&core->done, TIMEOUT);
 149         if (!ret) {
 150                 ret = -ETIMEDOUT;
 151                 goto unlock;
 152         }
 153         ret = 0;
 154         if (core->error != HFI_ERR_NONE)
 155                 ret = -ENODEV;
 156 unlock:
 157         mutex_unlock(&core->lock);
 158         return ret;
 159 }
 160 
 161 static int wait_session_msg(struct venus_inst *inst)
 162 {
 163         int ret;
 164 
 165         ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
 166         if (!ret)
 167                 return -ETIMEDOUT;
 168 
 169         if (inst->error != HFI_ERR_NONE)
 170                 return -EIO;
 171 
 172         return 0;
 173 }
 174 
 175 int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops)
 176 {
 177         struct venus_core *core = inst->core;
 178 
 179         if (!ops)
 180                 return -EINVAL;
 181 
 182         inst->state = INST_UNINIT;
 183         init_completion(&inst->done);
 184         inst->ops = ops;
 185 
 186         mutex_lock(&core->lock);
 187         list_add_tail(&inst->list, &core->instances);
 188         atomic_inc(&core->insts_count);
 189         mutex_unlock(&core->lock);
 190 
 191         return 0;
 192 }
 193 EXPORT_SYMBOL_GPL(hfi_session_create);
 194 
 195 int hfi_session_init(struct venus_inst *inst, u32 pixfmt)
 196 {
 197         struct venus_core *core = inst->core;
 198         const struct hfi_ops *ops = core->ops;
 199         int ret;
 200 
 201         if (inst->state != INST_UNINIT)
 202                 return -EINVAL;
 203 
 204         inst->hfi_codec = to_codec_type(pixfmt);
 205         reinit_completion(&inst->done);
 206 
 207         ret = ops->session_init(inst, inst->session_type, inst->hfi_codec);
 208         if (ret)
 209                 return ret;
 210 
 211         ret = wait_session_msg(inst);
 212         if (ret)
 213                 return ret;
 214 
 215         inst->state = INST_INIT;
 216 
 217         return 0;
 218 }
 219 EXPORT_SYMBOL_GPL(hfi_session_init);
 220 
 221 void hfi_session_destroy(struct venus_inst *inst)
 222 {
 223         struct venus_core *core = inst->core;
 224 
 225         mutex_lock(&core->lock);
 226         list_del_init(&inst->list);
 227         if (atomic_dec_and_test(&core->insts_count))
 228                 wake_up_var(&core->insts_count);
 229         mutex_unlock(&core->lock);
 230 }
 231 EXPORT_SYMBOL_GPL(hfi_session_destroy);
 232 
 233 int hfi_session_deinit(struct venus_inst *inst)
 234 {
 235         const struct hfi_ops *ops = inst->core->ops;
 236         int ret;
 237 
 238         if (inst->state == INST_UNINIT)
 239                 return 0;
 240 
 241         if (inst->state < INST_INIT)
 242                 return -EINVAL;
 243 
 244         reinit_completion(&inst->done);
 245 
 246         ret = ops->session_end(inst);
 247         if (ret)
 248                 return ret;
 249 
 250         ret = wait_session_msg(inst);
 251         if (ret)
 252                 return ret;
 253 
 254         inst->state = INST_UNINIT;
 255 
 256         return 0;
 257 }
 258 EXPORT_SYMBOL_GPL(hfi_session_deinit);
 259 
 260 int hfi_session_start(struct venus_inst *inst)
 261 {
 262         const struct hfi_ops *ops = inst->core->ops;
 263         int ret;
 264 
 265         if (inst->state != INST_LOAD_RESOURCES)
 266                 return -EINVAL;
 267 
 268         reinit_completion(&inst->done);
 269 
 270         ret = ops->session_start(inst);
 271         if (ret)
 272                 return ret;
 273 
 274         ret = wait_session_msg(inst);
 275         if (ret)
 276                 return ret;
 277 
 278         inst->state = INST_START;
 279 
 280         return 0;
 281 }
 282 EXPORT_SYMBOL_GPL(hfi_session_start);
 283 
 284 int hfi_session_stop(struct venus_inst *inst)
 285 {
 286         const struct hfi_ops *ops = inst->core->ops;
 287         int ret;
 288 
 289         if (inst->state != INST_START)
 290                 return -EINVAL;
 291 
 292         reinit_completion(&inst->done);
 293 
 294         ret = ops->session_stop(inst);
 295         if (ret)
 296                 return ret;
 297 
 298         ret = wait_session_msg(inst);
 299         if (ret)
 300                 return ret;
 301 
 302         inst->state = INST_STOP;
 303 
 304         return 0;
 305 }
 306 EXPORT_SYMBOL_GPL(hfi_session_stop);
 307 
 308 int hfi_session_continue(struct venus_inst *inst)
 309 {
 310         struct venus_core *core = inst->core;
 311 
 312         if (core->res->hfi_version == HFI_VERSION_1XX)
 313                 return 0;
 314 
 315         return core->ops->session_continue(inst);
 316 }
 317 EXPORT_SYMBOL_GPL(hfi_session_continue);
 318 
 319 int hfi_session_abort(struct venus_inst *inst)
 320 {
 321         const struct hfi_ops *ops = inst->core->ops;
 322         int ret;
 323 
 324         reinit_completion(&inst->done);
 325 
 326         ret = ops->session_abort(inst);
 327         if (ret)
 328                 return ret;
 329 
 330         ret = wait_session_msg(inst);
 331         if (ret)
 332                 return ret;
 333 
 334         return 0;
 335 }
 336 EXPORT_SYMBOL_GPL(hfi_session_abort);
 337 
 338 int hfi_session_load_res(struct venus_inst *inst)
 339 {
 340         const struct hfi_ops *ops = inst->core->ops;
 341         int ret;
 342 
 343         if (inst->state != INST_INIT)
 344                 return -EINVAL;
 345 
 346         reinit_completion(&inst->done);
 347 
 348         ret = ops->session_load_res(inst);
 349         if (ret)
 350                 return ret;
 351 
 352         ret = wait_session_msg(inst);
 353         if (ret)
 354                 return ret;
 355 
 356         inst->state = INST_LOAD_RESOURCES;
 357 
 358         return 0;
 359 }
 360 
 361 int hfi_session_unload_res(struct venus_inst *inst)
 362 {
 363         const struct hfi_ops *ops = inst->core->ops;
 364         int ret;
 365 
 366         if (inst->state != INST_STOP)
 367                 return -EINVAL;
 368 
 369         reinit_completion(&inst->done);
 370 
 371         ret = ops->session_release_res(inst);
 372         if (ret)
 373                 return ret;
 374 
 375         ret = wait_session_msg(inst);
 376         if (ret)
 377                 return ret;
 378 
 379         inst->state = INST_RELEASE_RESOURCES;
 380 
 381         return 0;
 382 }
 383 EXPORT_SYMBOL_GPL(hfi_session_unload_res);
 384 
 385 int hfi_session_flush(struct venus_inst *inst, u32 type)
 386 {
 387         const struct hfi_ops *ops = inst->core->ops;
 388         int ret;
 389 
 390         reinit_completion(&inst->done);
 391 
 392         ret = ops->session_flush(inst, type);
 393         if (ret)
 394                 return ret;
 395 
 396         ret = wait_session_msg(inst);
 397         if (ret)
 398                 return ret;
 399 
 400         return 0;
 401 }
 402 EXPORT_SYMBOL_GPL(hfi_session_flush);
 403 
 404 int hfi_session_set_buffers(struct venus_inst *inst, struct hfi_buffer_desc *bd)
 405 {
 406         const struct hfi_ops *ops = inst->core->ops;
 407 
 408         return ops->session_set_buffers(inst, bd);
 409 }
 410 
 411 int hfi_session_unset_buffers(struct venus_inst *inst,
 412                               struct hfi_buffer_desc *bd)
 413 {
 414         const struct hfi_ops *ops = inst->core->ops;
 415         int ret;
 416 
 417         reinit_completion(&inst->done);
 418 
 419         ret = ops->session_unset_buffers(inst, bd);
 420         if (ret)
 421                 return ret;
 422 
 423         if (!bd->response_required)
 424                 return 0;
 425 
 426         ret = wait_session_msg(inst);
 427         if (ret)
 428                 return ret;
 429 
 430         return 0;
 431 }
 432 
 433 int hfi_session_get_property(struct venus_inst *inst, u32 ptype,
 434                              union hfi_get_property *hprop)
 435 {
 436         const struct hfi_ops *ops = inst->core->ops;
 437         int ret;
 438 
 439         if (inst->state < INST_INIT || inst->state >= INST_STOP)
 440                 return -EINVAL;
 441 
 442         reinit_completion(&inst->done);
 443 
 444         ret = ops->session_get_property(inst, ptype);
 445         if (ret)
 446                 return ret;
 447 
 448         ret = wait_session_msg(inst);
 449         if (ret)
 450                 return ret;
 451 
 452         *hprop = inst->hprop;
 453 
 454         return 0;
 455 }
 456 EXPORT_SYMBOL_GPL(hfi_session_get_property);
 457 
 458 int hfi_session_set_property(struct venus_inst *inst, u32 ptype, void *pdata)
 459 {
 460         const struct hfi_ops *ops = inst->core->ops;
 461 
 462         if (inst->state < INST_INIT || inst->state >= INST_STOP)
 463                 return -EINVAL;
 464 
 465         return ops->session_set_property(inst, ptype, pdata);
 466 }
 467 EXPORT_SYMBOL_GPL(hfi_session_set_property);
 468 
 469 int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd)
 470 {
 471         const struct hfi_ops *ops = inst->core->ops;
 472 
 473         if (fd->buffer_type == HFI_BUFFER_INPUT)
 474                 return ops->session_etb(inst, fd);
 475         else if (fd->buffer_type == HFI_BUFFER_OUTPUT ||
 476                  fd->buffer_type == HFI_BUFFER_OUTPUT2)
 477                 return ops->session_ftb(inst, fd);
 478 
 479         return -EINVAL;
 480 }
 481 EXPORT_SYMBOL_GPL(hfi_session_process_buf);
 482 
 483 irqreturn_t hfi_isr_thread(int irq, void *dev_id)
 484 {
 485         struct venus_core *core = dev_id;
 486 
 487         return core->ops->isr_thread(core);
 488 }
 489 
 490 irqreturn_t hfi_isr(int irq, void *dev)
 491 {
 492         struct venus_core *core = dev;
 493 
 494         return core->ops->isr(core);
 495 }
 496 
 497 int hfi_create(struct venus_core *core, const struct hfi_core_ops *ops)
 498 {
 499         int ret;
 500 
 501         if (!ops)
 502                 return -EINVAL;
 503 
 504         atomic_set(&core->insts_count, 0);
 505         core->core_ops = ops;
 506         core->state = CORE_UNINIT;
 507         init_completion(&core->done);
 508         pkt_set_version(core->res->hfi_version);
 509         ret = venus_hfi_create(core);
 510 
 511         return ret;
 512 }
 513 
 514 void hfi_destroy(struct venus_core *core)
 515 {
 516         venus_hfi_destroy(core);
 517 }

/* [<][>][^][v][top][bottom][index][help] */