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 struct vpu_device *dev = inst->dev; 56 int ret = 0; 57 58 v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx); 59 if (inst->state != VPU_INST_STATE_NONE) { 60 u32 fail_res; 61 62 ret = close_func(inst, &fail_res); 63 if (fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) { 64 dev_err(inst->dev->dev, "%s close failed, device is still running\n", 65 name); 66 return -EBUSY; 67 } 68 if (ret && ret != -EIO) { 69 dev_err(inst->dev->dev, "%s close, fail: %d\n", name, ret); 70 return ret; 71 } 72 } 73 74 wave5_cleanup_instance(inst); 75 if (dev->irq < 0) { 76 ret = mutex_lock_interruptible(&dev->dev_lock); 77 if (ret) 78 return ret; 79 80 if (list_empty(&dev->instances)) { 81 dev_dbg(dev->dev, "Disabling the hrtimer\n"); 82 hrtimer_cancel(&dev->hrtimer); 83 } 84 85 mutex_unlock(&dev->dev_lock); 86 } 87 88 return ret; 89 } 90 91 int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq, 92 const struct vb2_ops *ops) 93 { 94 struct vpu_instance *inst = priv; 95 int ret; 96 97 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 98 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 99 src_vq->mem_ops = &vb2_dma_contig_memops; 100 src_vq->ops = ops; 101 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 102 src_vq->buf_struct_size = sizeof(struct vpu_src_buffer); 103 src_vq->drv_priv = inst; 104 src_vq->lock = &inst->dev->dev_lock; 105 src_vq->dev = inst->dev->v4l2_dev.dev; 106 ret = vb2_queue_init(src_vq); 107 if (ret) 108 return ret; 109 110 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 111 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 112 dst_vq->mem_ops = &vb2_dma_contig_memops; 113 dst_vq->ops = ops; 114 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 115 dst_vq->buf_struct_size = sizeof(struct vpu_src_buffer); 116 dst_vq->drv_priv = inst; 117 dst_vq->lock = &inst->dev->dev_lock; 118 dst_vq->dev = inst->dev->v4l2_dev.dev; 119 ret = vb2_queue_init(dst_vq); 120 if (ret) 121 return ret; 122 123 return 0; 124 } 125 126 int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) 127 { 128 struct vpu_instance *inst = wave5_to_vpu_inst(fh); 129 bool is_decoder = inst->type == VPU_INST_TYPE_DEC; 130 131 dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__, 132 is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags); 133 134 switch (sub->type) { 135 case V4L2_EVENT_EOS: 136 return v4l2_event_subscribe(fh, sub, 0, NULL); 137 case V4L2_EVENT_SOURCE_CHANGE: 138 if (is_decoder) 139 return v4l2_src_change_event_subscribe(fh, sub); 140 return -EINVAL; 141 case V4L2_EVENT_CTRL: 142 return v4l2_ctrl_subscribe_event(fh, sub); 143 default: 144 return -EINVAL; 145 } 146 } 147 148 int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f) 149 { 150 struct vpu_instance *inst = wave5_to_vpu_inst(fh); 151 int i; 152 153 f->fmt.pix_mp.width = inst->src_fmt.width; 154 f->fmt.pix_mp.height = inst->src_fmt.height; 155 f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat; 156 f->fmt.pix_mp.field = inst->src_fmt.field; 157 f->fmt.pix_mp.flags = inst->src_fmt.flags; 158 f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes; 159 for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { 160 f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->src_fmt.plane_fmt[i].bytesperline; 161 f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->src_fmt.plane_fmt[i].sizeimage; 162 } 163 164 f->fmt.pix_mp.colorspace = inst->colorspace; 165 f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; 166 f->fmt.pix_mp.quantization = inst->quantization; 167 f->fmt.pix_mp.xfer_func = inst->xfer_func; 168 169 return 0; 170 } 171 172 const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt, 173 const struct vpu_format fmt_list[MAX_FMTS]) 174 { 175 unsigned int index; 176 177 for (index = 0; index < MAX_FMTS; index++) { 178 if (fmt_list[index].v4l2_pix_fmt == v4l2_pix_fmt) 179 return &fmt_list[index]; 180 } 181 182 return NULL; 183 } 184 185 const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx, 186 const struct vpu_format fmt_list[MAX_FMTS]) 187 { 188 if (idx >= MAX_FMTS) 189 return NULL; 190 191 if (!fmt_list[idx].v4l2_pix_fmt) 192 return NULL; 193 194 return &fmt_list[idx]; 195 } 196 197 enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type) 198 { 199 switch (v4l2_pix_fmt) { 200 case V4L2_PIX_FMT_H264: 201 return type == VPU_INST_TYPE_DEC ? W_AVC_DEC : W_AVC_ENC; 202 case V4L2_PIX_FMT_HEVC: 203 return type == VPU_INST_TYPE_DEC ? W_HEVC_DEC : W_HEVC_ENC; 204 default: 205 return STD_UNKNOWN; 206 } 207 } 208 209 void wave5_return_bufs(struct vb2_queue *q, u32 state) 210 { 211 struct vpu_instance *inst = vb2_get_drv_priv(q); 212 struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; 213 struct v4l2_ctrl_handler v4l2_ctrl_hdl = inst->v4l2_ctrl_hdl; 214 struct vb2_v4l2_buffer *vbuf; 215 216 for (;;) { 217 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 218 vbuf = v4l2_m2m_src_buf_remove(m2m_ctx); 219 else 220 vbuf = v4l2_m2m_dst_buf_remove(m2m_ctx); 221 if (!vbuf) 222 return; 223 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, &v4l2_ctrl_hdl); 224 v4l2_m2m_buf_done(vbuf, state); 225 } 226 } 227