| // SPDX-License-Identifier: GPL-2.0 | 
| /* | 
|  * Copyright (c) 2016 MediaTek Inc. | 
|  * Author: Daniel Hsiao <daniel.hsiao@mediatek.com> | 
|  *    Jungchang Tsao <jungchang.tsao@mediatek.com> | 
|  *    Tiffany Lin <tiffany.lin@mediatek.com> | 
|  */ | 
|   | 
| #include <linux/interrupt.h> | 
| #include <linux/kernel.h> | 
| #include <linux/slab.h> | 
|   | 
| #include "venc_drv_base.h" | 
| #include "venc_drv_if.h" | 
|   | 
| #include "mtk_vcodec_enc.h" | 
| #include "mtk_vcodec_enc_pm.h" | 
|   | 
| int venc_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) | 
| { | 
|     int ret = 0; | 
|   | 
|     switch (fourcc) { | 
|     case V4L2_PIX_FMT_VP8: | 
|         ctx->enc_if = &venc_vp8_if; | 
|         break; | 
|     case V4L2_PIX_FMT_H264: | 
|         ctx->enc_if = &venc_h264_if; | 
|         break; | 
|     default: | 
|         return -EINVAL; | 
|     } | 
|   | 
|     mtk_venc_lock(ctx); | 
|     mtk_vcodec_enc_clock_on(&ctx->dev->pm); | 
|     ret = ctx->enc_if->init(ctx); | 
|     mtk_vcodec_enc_clock_off(&ctx->dev->pm); | 
|     mtk_venc_unlock(ctx); | 
|   | 
|     return ret; | 
| } | 
|   | 
| int venc_if_set_param(struct mtk_vcodec_ctx *ctx, | 
|         enum venc_set_param_type type, struct venc_enc_param *in) | 
| { | 
|     int ret = 0; | 
|   | 
|     mtk_venc_lock(ctx); | 
|     mtk_vcodec_enc_clock_on(&ctx->dev->pm); | 
|     ret = ctx->enc_if->set_param(ctx->drv_handle, type, in); | 
|     mtk_vcodec_enc_clock_off(&ctx->dev->pm); | 
|     mtk_venc_unlock(ctx); | 
|   | 
|     return ret; | 
| } | 
|   | 
| int venc_if_encode(struct mtk_vcodec_ctx *ctx, | 
|            enum venc_start_opt opt, struct venc_frm_buf *frm_buf, | 
|            struct mtk_vcodec_mem *bs_buf, | 
|            struct venc_done_result *result) | 
| { | 
|     int ret = 0; | 
|     unsigned long flags; | 
|   | 
|     mtk_venc_lock(ctx); | 
|   | 
|     spin_lock_irqsave(&ctx->dev->irqlock, flags); | 
|     ctx->dev->curr_ctx = ctx; | 
|     spin_unlock_irqrestore(&ctx->dev->irqlock, flags); | 
|   | 
|     mtk_vcodec_enc_clock_on(&ctx->dev->pm); | 
|     ret = ctx->enc_if->encode(ctx->drv_handle, opt, frm_buf, | 
|                   bs_buf, result); | 
|     mtk_vcodec_enc_clock_off(&ctx->dev->pm); | 
|   | 
|     spin_lock_irqsave(&ctx->dev->irqlock, flags); | 
|     ctx->dev->curr_ctx = NULL; | 
|     spin_unlock_irqrestore(&ctx->dev->irqlock, flags); | 
|   | 
|     mtk_venc_unlock(ctx); | 
|     return ret; | 
| } | 
|   | 
| int venc_if_deinit(struct mtk_vcodec_ctx *ctx) | 
| { | 
|     int ret = 0; | 
|   | 
|     if (!ctx->drv_handle) | 
|         return 0; | 
|   | 
|     mtk_venc_lock(ctx); | 
|     mtk_vcodec_enc_clock_on(&ctx->dev->pm); | 
|     ret = ctx->enc_if->deinit(ctx->drv_handle); | 
|     mtk_vcodec_enc_clock_off(&ctx->dev->pm); | 
|     mtk_venc_unlock(ctx); | 
|   | 
|     ctx->drv_handle = NULL; | 
|   | 
|     return ret; | 
| } |