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