diff options
Diffstat (limited to 'drivers/media/platform/amphion')
-rw-r--r-- | drivers/media/platform/amphion/vdec.c | 50 | ||||
-rw-r--r-- | drivers/media/platform/amphion/venc.c | 3 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_cmds.c | 3 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_core.c | 18 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_dbg.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_malone.c | 20 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_malone.h | 1 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_msgs.c | 7 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_rpc.c | 2 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_rpc.h | 7 | ||||
-rw-r--r-- | drivers/media/platform/amphion/vpu_v4l2.c | 6 |
12 files changed, 85 insertions, 35 deletions
diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c index 3c02aa2a54aa..9e64041cc1c1 100644 --- a/drivers/media/platform/amphion/vdec.c +++ b/drivers/media/platform/amphion/vdec.c @@ -63,6 +63,7 @@ struct vdec_t { bool is_source_changed; u32 source_change; u32 drain; + bool aborting; }; static const struct vpu_format vdec_formats[] = { @@ -104,7 +105,6 @@ static const struct vpu_format vdec_formats[] = { .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION }, { .pixfmt = V4L2_PIX_FMT_MPEG2, @@ -178,16 +178,6 @@ static int vdec_ctrl_init(struct vpu_inst *inst) return 0; } -static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst) -{ - struct vdec_t *vdec = inst->priv; - - if (vdec->eos_received) { - if (!vpu_set_last_buffer_dequeued(inst)) - vdec->eos_received--; - } -} - static void vdec_handle_resolution_change(struct vpu_inst *inst) { struct vdec_t *vdec = inst->priv; @@ -234,6 +224,21 @@ static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, return 0; } +static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst) +{ + struct vdec_t *vdec = inst->priv; + + if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) + return; + + if (vdec->eos_received) { + if (!vpu_set_last_buffer_dequeued(inst)) { + vdec->eos_received--; + vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0); + } + } +} + static int vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { strscpy(cap->driver, "amphion-vpu", sizeof(cap->driver)); @@ -493,6 +498,8 @@ static int vdec_drain(struct vpu_inst *inst) static int vdec_cmd_start(struct vpu_inst *inst) { + struct vdec_t *vdec = inst->priv; + switch (inst->state) { case VPU_CODEC_STATE_STARTED: case VPU_CODEC_STATE_DRAIN: @@ -503,6 +510,8 @@ static int vdec_cmd_start(struct vpu_inst *inst) break; } vpu_process_capture_buffer(inst); + if (vdec->eos_received) + vdec_set_last_buffer_dequeued(inst); return 0; } @@ -731,6 +740,7 @@ static void vdec_stop_done(struct vpu_inst *inst) vdec->eos_received = 0; vdec->is_source_changed = false; vdec->source_change = 0; + inst->total_input_count = 0; vpu_inst_unlock(inst); } @@ -939,6 +949,9 @@ static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vb if (inst->state != VPU_CODEC_STATE_ACTIVE) return -EINVAL; + if (vdec->aborting) + return -EINVAL; + if (!vdec->req_frame_count) return -EINVAL; @@ -1048,6 +1061,8 @@ static void vdec_clear_slots(struct vpu_inst *inst) vpu_buf = vdec->slots[i]; vbuf = &vpu_buf->m2m_buf.vb; + vpu_trace(inst->dev, "clear slot %d\n", i); + vdec_response_fs_release(inst, i, vpu_buf->tag); vdec_recycle_buffer(inst, vbuf); vdec->slots[i]->state = VPU_BUF_STATE_IDLE; vdec->slots[i] = NULL; @@ -1203,7 +1218,6 @@ static void vdec_event_eos(struct vpu_inst *inst) vdec->eos_received++; vdec->fixed_fmt = false; inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP; - vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0); vdec_set_last_buffer_dequeued(inst); vpu_inst_unlock(inst); } @@ -1310,6 +1324,8 @@ static void vdec_abort(struct vpu_inst *inst) int ret; vpu_trace(inst->dev, "[%d] state = %d\n", inst->id, inst->state); + + vdec->aborting = true; vpu_iface_add_scode(inst, SCODE_PADDING_ABORT); vdec->params.end_flag = 1; vpu_iface_set_decode_params(inst, &vdec->params, 1); @@ -1333,6 +1349,7 @@ static void vdec_abort(struct vpu_inst *inst) vdec->decoded_frame_count = 0; vdec->display_frame_count = 0; vdec->sequence = 0; + vdec->aborting = false; } static void vdec_stop(struct vpu_inst *inst, bool free) @@ -1369,8 +1386,7 @@ static void vdec_cleanup(struct vpu_inst *inst) return; vdec = inst->priv; - if (vdec) - vfree(vdec); + vfree(vdec); inst->priv = NULL; vfree(inst); } @@ -1480,10 +1496,10 @@ static int vdec_stop_session(struct vpu_inst *inst, u32 type) vdec_update_state(inst, VPU_CODEC_STATE_SEEK, 0); vdec->drain = 0; } else { - if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) + if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) { vdec_abort(inst); - - vdec->eos_received = 0; + vdec->eos_received = 0; + } vdec_clear_slots(inst); } diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c index 43d61d82f58c..461524dd1e44 100644 --- a/drivers/media/platform/amphion/venc.c +++ b/drivers/media/platform/amphion/venc.c @@ -919,8 +919,7 @@ static void venc_cleanup(struct vpu_inst *inst) return; venc = inst->priv; - if (venc) - vfree(venc); + vfree(venc); inst->priv = NULL; vfree(inst); } diff --git a/drivers/media/platform/amphion/vpu.h b/drivers/media/platform/amphion/vpu.h index e56b96a7e5d3..f914de6ed81e 100644 --- a/drivers/media/platform/amphion/vpu.h +++ b/drivers/media/platform/amphion/vpu.h @@ -258,6 +258,7 @@ struct vpu_inst { struct vpu_format cap_format; u32 min_buffer_cap; u32 min_buffer_out; + u32 total_input_count; struct v4l2_rect crop; u32 colorspace; diff --git a/drivers/media/platform/amphion/vpu_cmds.c b/drivers/media/platform/amphion/vpu_cmds.c index 9b39d77a178d..f4d7ca78a621 100644 --- a/drivers/media/platform/amphion/vpu_cmds.c +++ b/drivers/media/platform/amphion/vpu_cmds.c @@ -117,8 +117,7 @@ static void vpu_free_cmd(struct vpu_cmd_t *cmd) { if (!cmd) return; - if (cmd->pkt) - vfree(cmd->pkt); + vfree(cmd->pkt); vfree(cmd); } diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c index 68ad183925fd..73faa50d2865 100644 --- a/drivers/media/platform/amphion/vpu_core.c +++ b/drivers/media/platform/amphion/vpu_core.c @@ -257,14 +257,8 @@ static int vpu_core_register(struct device *dev, struct vpu_core *core) } list_add_tail(&core->list, &vpu->cores); - vpu_core_get_vpu(core); - if (vpu_iface_get_power_state(core)) - ret = vpu_core_restore(core); - if (ret) - goto error; - return 0; error: if (core->msg_buffer) { @@ -362,7 +356,10 @@ struct vpu_core *vpu_request_core(struct vpu_dev *vpu, enum vpu_core_type type) pm_runtime_resume_and_get(core->dev); if (core->state == VPU_CORE_DEINIT) { - ret = vpu_core_boot(core, true); + if (vpu_iface_get_power_state(core)) + ret = vpu_core_restore(core); + else + ret = vpu_core_boot(core, true); if (ret) { pm_runtime_put_sync(core->dev); mutex_unlock(&core->lock); @@ -455,8 +452,13 @@ int vpu_inst_unregister(struct vpu_inst *inst) } vpu_core_check_hang(core); if (core->state == VPU_CORE_HANG && !core->instance_mask) { + int err; + dev_info(core->dev, "reset hang core\n"); - if (!vpu_core_sw_reset(core)) { + mutex_unlock(&core->lock); + err = vpu_core_sw_reset(core); + mutex_lock(&core->lock); + if (!err) { core->state = VPU_CORE_ACTIVE; core->hang_mask = 0; } diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c index da62bd718fb8..f72c8a506b22 100644 --- a/drivers/media/platform/amphion/vpu_dbg.c +++ b/drivers/media/platform/amphion/vpu_dbg.c @@ -27,7 +27,7 @@ struct print_buf_desc { u32 bytes; u32 read; u32 write; - char buffer[0]; + char buffer[]; }; static char *vb2_stat_name[] = { diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c index f29c223eefce..f4a488bf9880 100644 --- a/drivers/media/platform/amphion/vpu_malone.c +++ b/drivers/media/platform/amphion/vpu_malone.c @@ -309,6 +309,7 @@ struct malone_padding_scode { struct malone_fmt_mapping { u32 pixelformat; enum vpu_malone_format malone_format; + u32 is_disabled; }; struct malone_scode_t { @@ -568,6 +569,8 @@ static enum vpu_malone_format vpu_malone_format_remap(u32 pixelformat) u32 i; for (i = 0; i < ARRAY_SIZE(fmt_mappings); i++) { + if (fmt_mappings[i].is_disabled) + continue; if (pixelformat == fmt_mappings[i].pixelformat) return fmt_mappings[i].malone_format; } @@ -575,6 +578,19 @@ static enum vpu_malone_format vpu_malone_format_remap(u32 pixelformat) return MALONE_FMT_NULL; } +bool vpu_malone_check_fmt(enum vpu_core_type type, u32 pixelfmt) +{ + if (!vpu_imx8q_check_fmt(type, pixelfmt)) + return false; + + if (pixelfmt == V4L2_PIX_FMT_NV12M_8L128 || pixelfmt == V4L2_PIX_FMT_NV12M_10BE_8L128) + return true; + if (vpu_malone_format_remap(pixelfmt) == MALONE_FMT_NULL) + return false; + + return true; +} + static void vpu_malone_set_stream_cfg(struct vpu_shared_addr *shared, u32 instance, enum vpu_malone_format malone_format) @@ -610,6 +626,8 @@ static int vpu_malone_set_params(struct vpu_shared_addr *shared, enum vpu_malone_format malone_format; malone_format = vpu_malone_format_remap(params->codec_format); + if (WARN_ON(malone_format == MALONE_FMT_NULL)) + return -EINVAL; iface->udata_buffer[instance].base = params->udata.base; iface->udata_buffer[instance].slot_size = params->udata.size; @@ -1296,6 +1314,8 @@ static int vpu_malone_insert_scode_vc1_l_seq(struct malone_scode_t *scode) int size = 0; u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN]; + if (scode->inst->total_input_count) + return 0; scode->need_data = 0; ret = vpu_malone_insert_scode_seq(scode, MALONE_CODEC_ID_VC1_SIMPLE, sizeof(rcv_seqhdr)); diff --git a/drivers/media/platform/amphion/vpu_malone.h b/drivers/media/platform/amphion/vpu_malone.h index e5a5cbe9843e..02a9d9530970 100644 --- a/drivers/media/platform/amphion/vpu_malone.h +++ b/drivers/media/platform/amphion/vpu_malone.h @@ -40,5 +40,6 @@ int vpu_malone_pre_cmd(struct vpu_shared_addr *shared, u32 instance); int vpu_malone_post_cmd(struct vpu_shared_addr *shared, u32 instance); int vpu_malone_init_instance(struct vpu_shared_addr *shared, u32 instance); u32 vpu_malone_get_max_instance_count(struct vpu_shared_addr *shared); +bool vpu_malone_check_fmt(enum vpu_core_type type, u32 pixelfmt); #endif diff --git a/drivers/media/platform/amphion/vpu_msgs.c b/drivers/media/platform/amphion/vpu_msgs.c index d5850df8f1d5..d8247f36d84b 100644 --- a/drivers/media/platform/amphion/vpu_msgs.c +++ b/drivers/media/platform/amphion/vpu_msgs.c @@ -150,7 +150,12 @@ static void vpu_session_handle_eos(struct vpu_inst *inst, struct vpu_rpc_event * static void vpu_session_handle_error(struct vpu_inst *inst, struct vpu_rpc_event *pkt) { - dev_err(inst->dev, "unsupported stream\n"); + char *str = (char *)pkt->data; + + if (strlen(str)) + dev_err(inst->dev, "instance %d firmware error : %s\n", inst->id, str); + else + dev_err(inst->dev, "instance %d is unsupported stream\n", inst->id); call_void_vop(inst, event_notify, VPU_MSG_ID_UNSUPPORTED, NULL); vpu_v4l2_set_error(inst); } diff --git a/drivers/media/platform/amphion/vpu_rpc.c b/drivers/media/platform/amphion/vpu_rpc.c index 18a164766409..676f7da041bd 100644 --- a/drivers/media/platform/amphion/vpu_rpc.c +++ b/drivers/media/platform/amphion/vpu_rpc.c @@ -195,7 +195,7 @@ static struct vpu_iface_ops imx8q_rpc_ops[] = { }, [VPU_CORE_TYPE_DEC] = { .check_codec = vpu_imx8q_check_codec, - .check_fmt = vpu_imx8q_check_fmt, + .check_fmt = vpu_malone_check_fmt, .boot_core = vpu_imx8q_boot_core, .get_power_state = vpu_imx8q_get_power_state, .on_firmware_loaded = vpu_imx8q_on_firmware_loaded, diff --git a/drivers/media/platform/amphion/vpu_rpc.h b/drivers/media/platform/amphion/vpu_rpc.h index 25119e5e807e..7eb6f01e6ab5 100644 --- a/drivers/media/platform/amphion/vpu_rpc.h +++ b/drivers/media/platform/amphion/vpu_rpc.h @@ -312,11 +312,16 @@ static inline int vpu_iface_input_frame(struct vpu_inst *inst, struct vb2_buffer *vb) { struct vpu_iface_ops *ops = vpu_core_get_iface(inst->core); + int ret; if (!ops || !ops->input_frame) return -EINVAL; - return ops->input_frame(inst->core->iface, inst, vb); + ret = ops->input_frame(inst->core->iface, inst, vb); + if (ret < 0) + return ret; + inst->total_input_count++; + return ret; } static inline int vpu_iface_config_memory_resource(struct vpu_inst *inst, diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 446f07d09d0b..8a3eed957ae6 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -500,10 +500,12 @@ static int vpu_vb2_start_streaming(struct vb2_queue *q, unsigned int count) fmt->sizeimage[1], fmt->bytesperline[1], fmt->sizeimage[2], fmt->bytesperline[2], q->num_buffers); - call_void_vop(inst, start, q->type); vb2_clear_last_buffer_dequeued(q); + ret = call_vop(inst, start, q->type); + if (ret) + vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_QUEUED); - return 0; + return ret; } static void vpu_vb2_stop_streaming(struct vb2_queue *q) |