1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2 /* 3 * Wave5 series multi-standard codec IP - decoder interface 4 * 5 * Copyright (C) 2021-2023 CHIPS&MEDIA INC 6 */ 7 8 #include "wave5-helper.h" 9 10 const char *state_to_str(enum vpu_instance_state state) 11 { 12 switch (state) { 13 case VPU_INST_STATE_NONE: 14 return "NONE"; 15 case VPU_INST_STATE_OPEN: 16 return "OPEN"; 17 case VPU_INST_STATE_INIT_SEQ: 18 return "INIT_SEQ"; 19 case VPU_INST_STATE_PIC_RUN: 20 return "PIC_RUN"; 21 case VPU_INST_STATE_STOP: 22 return "STOP"; 23 default: 24 return "UNKNOWN"; 25 } 26 } 27 28 void wave5_cleanup_instance(struct vpu_instance *inst) 29 { 30 int i; 31 32 if (list_is_singular(&inst->list)) 33 wave5_vdi_free_sram(inst->dev); 34 35 for (i = 0; i < inst->fbc_buf_count; i++) 36 wave5_vpu_dec_reset_framebuffer(inst, i); 37 38 wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf); 39 v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl); 40 if (inst->v4l2_fh.vdev) { 41 v4l2_fh_del(&inst->v4l2_fh); 42 v4l2_fh_exit(&inst->v4l2_fh); 43 } 44 list_del_init(&inst->list); 45 ida_free(&inst->dev->inst_ida, inst->id); 46 kfree(inst->codec_info); 47 kfree(inst); 48 } 49 50 int wave5_vpu_release_device(struct file *filp, 51 int (*close_func)(struct vpu_instance *inst, u32 *fail_res), 52 char *name) 53 { 54 struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data); 55 56 v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx); 57 if (inst->state != VPU_INST_STATE_NONE) { 58 u32 fail_res; 59 int ret; 60 61 ret = close_func(inst, &fail_res); 62 if (fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) { 63 dev_err(inst->dev->dev, "%s close failed, device is still running\n", 64 name); 65 return -EBUSY; 66 } 67 if (ret && ret != -EIO) { 68 dev_err(inst->dev->dev, "%s close, fail: %d\n", name, ret); 69 return ret; 70 } 71 } 72 73 wave5_cleanup_instance(inst); 74 75 return 0; 76 } 77 78 int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq, 79 const struct vb2_ops *ops) 80 { 81 struct vpu_instance *inst = priv; 82 int ret; 83 84 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 85 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 86 src_vq->mem_ops = &vb2_dma_contig_memops; 87 src_vq->ops = ops; 88 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 89 src_vq->buf_struct_size = sizeof(struct vpu_src_buffer); 90 src_vq->drv_priv = inst; 91 src_vq->lock = &inst->dev->dev_lock; 92 src_vq->dev = inst->dev->v4l2_dev.dev; 93 ret = vb2_queue_init(src_vq); 94 if (ret) 95 return ret; 96 97 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 98 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 99 dst_vq->mem_ops = &vb2_dma_contig_memops; 100 dst_vq->ops = ops; 101 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 102 dst_vq->buf_struct_size = sizeof(struct vpu_src_buffer); 103 dst_vq->drv_priv = inst; 104 dst_vq->lock = &inst->dev->dev_lock; 105 dst_vq->dev = inst->dev->v4l2_dev.dev; 106 ret = vb2_queue_init(dst_vq); 107 if (ret) 108 return ret; 109 110 return 0; 111 } 112 113 int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) 114 { 115 struct vpu_instance *inst = wave5_to_vpu_inst(fh); 116 bool is_decoder = inst->type == VPU_INST_TYPE_DEC; 117 118 dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__, 119 is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags); 120 121 switch (sub->type) { 122 case V4L2_EVENT_EOS: 123 return v4l2_event_subscribe(fh, sub, 0, NULL); 124 case V4L2_EVENT_SOURCE_CHANGE: 125 if (is_decoder) 126 return v4l2_src_change_event_subscribe(fh, sub); 127 return -EINVAL; 128 case V4L2_EVENT_CTRL: 129 return v4l2_ctrl_subscribe_event(fh, sub); 130 default: 131 return -EINVAL; 132 } 133 } 134 135 int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f) 136 { 137 struct vpu_instance *inst = wave5_to_vpu_inst(fh); 138 int i; 139 140 f->fmt.pix_mp.width = inst->src_fmt.width; 141 f->fmt.pix_mp.height = inst->src_fmt.height; 142 f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat; 143 f->fmt.pix_mp.field = inst->src_fmt.field; 144 f->fmt.pix_mp.flags = inst->src_fmt.flags; 145 f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes; 146 for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { 147 f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->src_fmt.plane_fmt[i].bytesperline; 148 f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->src_fmt.plane_fmt[i].sizeimage; 149 } 150 151 f->fmt.pix_mp.colorspace = inst->colorspace; 152 f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; 153 f->fmt.pix_mp.quantization = inst->quantization; 154 f->fmt.pix_mp.xfer_func = inst->xfer_func; 155 156 return 0; 157 } 158 159 const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt, 160 const struct vpu_format fmt_list[MAX_FMTS]) 161 { 162 unsigned int index; 163 164 for (index = 0; index < MAX_FMTS; index++) { 165 if (fmt_list[index].v4l2_pix_fmt == v4l2_pix_fmt) 166 return &fmt_list[index]; 167 } 168 169 return NULL; 170 } 171 172 const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx, 173 const struct vpu_format fmt_list[MAX_FMTS]) 174 { 175 if (idx >= MAX_FMTS) 176 return NULL; 177 178 if (!fmt_list[idx].v4l2_pix_fmt) 179 return NULL; 180 181 return &fmt_list[idx]; 182 } 183 184 enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type) 185 { 186 switch (v4l2_pix_fmt) { 187 case V4L2_PIX_FMT_H264: 188 return type == VPU_INST_TYPE_DEC ? W_AVC_DEC : W_AVC_ENC; 189 case V4L2_PIX_FMT_HEVC: 190 return type == VPU_INST_TYPE_DEC ? W_HEVC_DEC : W_HEVC_ENC; 191 default: 192 return STD_UNKNOWN; 193 } 194 } 195 196 void wave5_return_bufs(struct vb2_queue *q, u32 state) 197 { 198 struct vpu_instance *inst = vb2_get_drv_priv(q); 199 struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; 200 struct v4l2_ctrl_handler v4l2_ctrl_hdl = inst->v4l2_ctrl_hdl; 201 struct vb2_v4l2_buffer *vbuf; 202 203 for (;;) { 204 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 205 vbuf = v4l2_m2m_src_buf_remove(m2m_ctx); 206 else 207 vbuf = v4l2_m2m_dst_buf_remove(m2m_ctx); 208 if (!vbuf) 209 return; 210 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, &v4l2_ctrl_hdl); 211 v4l2_m2m_buf_done(vbuf, state); 212 } 213 } 214