diff --git a/msm/vidc/hfi_common.c b/msm/vidc/hfi_common.c index 430d07c82330..1fe54d83381a 100644 --- a/msm/vidc/hfi_common.c +++ b/msm/vidc/hfi_common.c @@ -299,7 +299,7 @@ static int __dsp_send_hfi_queue(struct venus_hfi_device *device) { int rc; - if (!device->res->domain_cvp) + if (!device->res->cvp_internal) return 0; if (!device->dsp_iface_q_table.mem_data.dma_handle) { @@ -333,7 +333,7 @@ static int __dsp_suspend(struct venus_hfi_device *device, bool force, u32 flags) int rc; struct hal_session *temp; - if (!device->res->domain_cvp) + if (!device->res->cvp_internal) return 0; if (!(device->dsp_flags & DSP_INIT)) @@ -374,7 +374,7 @@ static int __dsp_resume(struct venus_hfi_device *device, u32 flags) { int rc; - if (!device->res->domain_cvp) + if (!device->res->cvp_internal) return 0; if (!(device->dsp_flags & DSP_SUSPEND)) { @@ -400,7 +400,7 @@ static int __dsp_shutdown(struct venus_hfi_device *device, u32 flags) { int rc; - if (!device->res->domain_cvp) + if (!device->res->cvp_internal) return 0; if (!(device->dsp_flags & DSP_INIT)) { @@ -1171,7 +1171,7 @@ static inline int __boot_firmware_common(struct venus_hfi_device *device) u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 10000; ctrl_init_val = BIT(0); - if (device->res->domain_cvp) + if (device->res->cvp_internal) ctrl_init_val |= BIT(1); __write_register(device, CTRL_INIT, ctrl_init_val); @@ -1688,7 +1688,7 @@ static void __interface_queues_release(struct venus_hfi_device *device) device->mem_addr.align_virtual_addr = NULL; device->mem_addr.align_device_addr = 0; - if (device->res->domain_cvp) + if (device->res->cvp_internal) __interface_dsp_queues_release(device); } @@ -1901,7 +1901,7 @@ static int __interface_queues_init(struct venus_hfi_device *dev) } - if (dev->res->domain_cvp) { + if (dev->res->cvp_internal) { rc = __interface_dsp_queues_init(dev); if (rc) { dprintk(VIDC_ERR, "dsp_queues_init failed\n"); diff --git a/msm/vidc/hfi_iris1.c b/msm/vidc/hfi_iris1.c index faf1e075691b..5789bd856394 100644 --- a/msm/vidc/hfi_iris1.c +++ b/msm/vidc/hfi_iris1.c @@ -41,7 +41,7 @@ void __setup_ucregion_memory_map_iris1(struct venus_hfi_device *device) __write_register(device, HFI_DSP_UC_REGION_ADDR, (u32)device->iface_q_table.align_device_addr); __write_register(device, HFI_DSP_UC_REGION_SIZE, SHARED_QSIZE); - if (device->res->domain_cvp) { + if (device->res->cvp_internal) { /* initialize DSP QTBL & UCREGION with DSP queues */ __write_register(device, HFI_DSP_QTBL_ADDR, (u32)device->dsp_iface_q_table.align_device_addr); diff --git a/msm/vidc/hfi_iris2.c b/msm/vidc/hfi_iris2.c index 4fd4dc415289..d01ceef45aa7 100644 --- a/msm/vidc/hfi_iris2.c +++ b/msm/vidc/hfi_iris2.c @@ -383,7 +383,7 @@ int __boot_firmware_iris2(struct venus_hfi_device *device) u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 10000; ctrl_init_val = BIT(0); - if (device->res->domain_cvp) + if (device->res->cvp_internal) ctrl_init_val |= BIT(1); __write_register(device, CTRL_INIT_IRIS2, ctrl_init_val); diff --git a/msm/vidc/msm_cvp_external.c b/msm/vidc/msm_cvp_external.c index 717f0bf7efad..1ccb9368aa53 100644 --- a/msm/vidc/msm_cvp_external.c +++ b/msm/vidc/msm_cvp_external.c @@ -171,6 +171,66 @@ error: return rc; } +static int msm_cvp_init_downscale_resolution(struct msm_vidc_inst *inst) +{ + struct msm_cvp_external *cvp; + const u32 width_max = 1920; + u32 width, height, ds_width, ds_height, temp; + + if (!inst || !inst->cvp) { + dprintk(VIDC_ERR, "%s: invalid params\n", __func__); + return -EINVAL; + } + cvp = inst->cvp; + + ds_width = cvp->width; + ds_height = cvp->height; + + if (!cvp->downscale) { + dprintk(VIDC_DBG, "%s: downscaling not enabled\n", __func__); + goto exit; + } + + /* Step 1) make width always the larger number */ + if (cvp->height > cvp->width) { + width = cvp->height; + height = cvp->width; + } else { + width = cvp->width; + height = cvp->height; + } + /* + * Step 2) Downscale width by 4 and round + * make sure width stays between 480 and 1920 + */ + ds_width = (width + 2) >> 2; + if (ds_width < 480) + ds_width = 480; + if (ds_width > width_max) + ds_width = width_max; + ds_height = (height * ds_width) / width; + if (ds_height < 128) + ds_height = 128; + + /* Step 3) do not downscale if width is less than 480 */ + if (width <= 480) + ds_width = width; + if (ds_width == width) + ds_height = height; + + /* Step 4) switch width and height if already switched */ + if (height > width) { + temp = ds_height; + ds_height = ds_width; + ds_width = temp; + } + +exit: + cvp->ds_width = ds_width; + cvp->ds_height = ds_height; + return 0; +} + static void msm_cvp_deinit_downscale_buffers(struct msm_vidc_inst *inst) { struct msm_cvp_external *cvp; @@ -389,15 +449,12 @@ static int msm_cvp_init_internal_buffers(struct msm_vidc_inst *inst) struct cvp_kmd_arg *arg; struct msm_cvp_session_set_persist_buffers_packet persist2_packet; - if (!inst || !inst->cvp) { + if (!inst || !inst->cvp || !inst->cvp->arg) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } - arg = kzalloc(sizeof(struct cvp_kmd_arg), GFP_KERNEL); - if (!arg) - return -ENOMEM; - cvp = inst->cvp; + arg = cvp->arg; dprintk(VIDC_DBG, "%s:\n", __func__); cvp->persist2_buffer.size = HFI_DME_INTERNAL_PERSIST_2_BUFFER_SIZE; @@ -451,35 +508,36 @@ static int msm_cvp_init_internal_buffers(struct msm_vidc_inst *inst) print_cvp_buffer(VIDC_DBG, "alloc: output_buffer", inst, &cvp->output_buffer); - kfree(arg); return rc; error: msm_cvp_deinit_internal_buffers(inst); - kfree(arg); return rc; } static int msm_cvp_prepare_extradata(struct msm_vidc_inst *inst, - struct vb2_buffer *vb) + struct msm_vidc_buffer *mbuf) { int rc = 0; struct msm_cvp_external *cvp; - struct dma_buf *dbuf = NULL; - char *kvaddr = NULL; + struct vb2_buffer *vb; + struct dma_buf *dbuf; + char *kvaddr; struct msm_vidc_extradata_header *e_hdr; bool input_extradata, found_end; - if (!inst || !inst->cvp || !vb) { + if (!inst || !inst->cvp || !mbuf) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } + cvp = inst->cvp; + + vb = &mbuf->vvb.vb2_buf; if (vb->num_planes <= 1) { dprintk(VIDC_ERR, "%s: extradata plane not enabled\n", __func__); return -EINVAL; } - cvp = inst->cvp; dbuf = dma_buf_get(vb->planes[1].m.fd); if (!dbuf) { @@ -539,17 +597,24 @@ static int msm_cvp_prepare_extradata(struct msm_vidc_inst *inst, dbuf->size); goto error; } - /* copy payload */ - e_hdr->version = 0x00000001; - e_hdr->port_index = 1; - e_hdr->type = MSM_VIDC_EXTRADATA_CVP_METADATA; - e_hdr->data_size = sizeof(struct msm_vidc_enc_cvp_metadata_payload); - e_hdr->size = sizeof(struct msm_vidc_extradata_header) + + if (cvp->metadata_available) { + cvp->metadata_available = false; + + /* copy payload */ + e_hdr->version = 0x00000001; + e_hdr->port_index = 1; + e_hdr->type = MSM_VIDC_EXTRADATA_CVP_METADATA; + e_hdr->data_size = + sizeof(struct msm_vidc_enc_cvp_metadata_payload); + e_hdr->size = sizeof(struct msm_vidc_extradata_header) + e_hdr->data_size; - dma_buf_begin_cpu_access(cvp->output_buffer.dbuf, DMA_BIDIRECTIONAL); - memcpy(e_hdr->data, cvp->output_buffer.kvaddr, + dma_buf_begin_cpu_access(cvp->output_buffer.dbuf, + DMA_BIDIRECTIONAL); + memcpy(e_hdr->data, cvp->output_buffer.kvaddr, sizeof(struct msm_vidc_enc_cvp_metadata_payload)); - dma_buf_end_cpu_access(cvp->output_buffer.dbuf, DMA_BIDIRECTIONAL); + dma_buf_end_cpu_access(cvp->output_buffer.dbuf, + DMA_BIDIRECTIONAL); + } /* fill extradata none */ e_hdr = (struct msm_vidc_extradata_header *) ((char *)e_hdr + e_hdr->size); @@ -607,27 +672,52 @@ static int msm_cvp_reference_management(struct msm_vidc_inst *inst) } static int msm_cvp_frame_process(struct msm_vidc_inst *inst, - struct vb2_buffer *vb) + struct msm_vidc_buffer *mbuf) { int rc = 0; struct msm_cvp_external *cvp; + struct vb2_buffer *vb; struct cvp_kmd_arg *arg; struct msm_cvp_dme_frame_packet *frame; + const u32 fps_max = 60; + u32 fps, skip_framecount; + bool skipframe = false; - if (!inst || !inst->cvp) { + if (!inst || !inst->cvp || !inst->cvp->arg || !mbuf) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } - arg = kzalloc(sizeof(struct cvp_kmd_arg), GFP_KERNEL); - if (!arg) - return -ENOMEM; - cvp = inst->cvp; + arg = cvp->arg; + + vb = &mbuf->vvb.vb2_buf; cvp->fullres_buffer.index = vb->index; cvp->fullres_buffer.fd = vb->planes[0].m.fd; cvp->fullres_buffer.size = vb->planes[0].length; cvp->fullres_buffer.offset = vb->planes[0].data_offset; + /* frame skip logic */ + fps = max(inst->clk_data.operating_rate, + inst->clk_data.frame_rate) >> 16; + if (fps > fps_max) { + /* + * fps <= 120: 0, 2, 4, 6 .. are not skipped + * fps <= 180: 0, 3, 6, 9 .. are not skipped + * fps <= 240: 0, 4, 8, 12 .. are not skipped + * fps <= 960: 0, 16, 32, 48 .. are not skipped + */ + fps = ALIGN(fps, fps_max); + skip_framecount = fps / fps_max; + skipframe = !(cvp->framecount % skip_framecount); + } + if (skipframe) { + print_cvp_buffer(VIDC_DBG, "input frame skipped", + inst, &cvp->fullres_buffer); + cvp->framecount++; + cvp->metadata_available = false; + return 0; + } + arg->type = CVP_KMD_SEND_CMD_PKT; frame = (struct msm_cvp_dme_frame_packet *)&arg->data.hfi_pkt.pkt_data; @@ -680,18 +770,19 @@ static int msm_cvp_frame_process(struct msm_vidc_inst *inst, goto error; } cvp->framecount++; + cvp->metadata_available = true; error: - kfree(arg); return rc; } -int msm_vidc_cvp_preprocess(struct msm_vidc_inst *inst, struct vb2_buffer *vb) +int msm_vidc_cvp_preprocess(struct msm_vidc_inst *inst, + struct msm_vidc_buffer *mbuf) { int rc = 0; struct msm_cvp_external *cvp; - if (!inst || !inst->cvp || !vb) { + if (!inst || !inst->cvp || !mbuf) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } @@ -702,13 +793,13 @@ int msm_vidc_cvp_preprocess(struct msm_vidc_inst *inst, struct vb2_buffer *vb) } cvp = inst->cvp; - rc = msm_cvp_frame_process(inst, vb); + rc = msm_cvp_frame_process(inst, mbuf); if (rc) { dprintk(VIDC_ERR, "%s: cvp process failed\n", __func__); return rc; } - rc = msm_cvp_prepare_extradata(inst, vb); + rc = msm_cvp_prepare_extradata(inst, mbuf); if (rc) { dprintk(VIDC_ERR, "%s: prepare extradata failed\n", __func__); return rc; @@ -760,6 +851,8 @@ static int msm_vidc_cvp_close(struct msm_vidc_inst *inst) "%s: cvp close failed with error %d\n", __func__, rc); cvp->priv = NULL; + kfree(cvp->arg); + cvp->arg = NULL; kfree(inst->cvp); inst->cvp = NULL; @@ -792,39 +885,25 @@ static int msm_vidc_cvp_init(struct msm_vidc_inst *inst) struct msm_cvp_dme_basic_config_packet *dmecfg; u32 color_fmt; - if (!inst || !inst->cvp) { + if (!inst || !inst->cvp || !inst->cvp->arg) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } - arg = kzalloc(sizeof(struct cvp_kmd_arg), GFP_KERNEL); - if (!arg) - return -ENOMEM; - - f = &inst->fmts[INPUT_PORT].v4l2_fmt; cvp = inst->cvp; - + arg = cvp->arg; cvp->framecount = 0; + cvp->metadata_available = false; + f = &inst->fmts[INPUT_PORT].v4l2_fmt; cvp->width = f->fmt.pix_mp.width; cvp->height = f->fmt.pix_mp.height; color_fmt = msm_comm_convert_color_fmt(f->fmt.pix_mp.pixelformat); /* enable downscale always */ cvp->downscale = true; - if (cvp->width * cvp->height < 640 * 480) { - cvp->ds_width = cvp->width; - cvp->ds_height = cvp->height; - } else if (cvp->width * cvp->height < 1920 * 1080) { - if (cvp->ds_width >= cvp->ds_height) { - cvp->ds_width = 480; - cvp->ds_height = 270; - } else { - cvp->ds_width = 270; - cvp->ds_height = 480; - } - } else { - cvp->ds_width = cvp->width / 4; - cvp->ds_height = cvp->height / 4; - } + rc = msm_cvp_init_downscale_resolution(inst); + if (rc) + goto error; + dprintk(VIDC_DBG, "%s: pixelformat %#x, wxh %dx%d downscale %d ds_wxh %dx%d\n", __func__, f->fmt.pix_mp.pixelformat, @@ -873,12 +952,10 @@ static int msm_vidc_cvp_init(struct msm_vidc_inst *inst) if (rc) goto error; - kfree(arg); return rc; error: msm_vidc_cvp_deinit(inst); - kfree(arg); return rc; } @@ -892,18 +969,22 @@ static int msm_vidc_cvp_open(struct msm_vidc_inst *inst) dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } - arg = kzalloc(sizeof(struct cvp_kmd_arg), GFP_KERNEL); - if (!arg) - return -ENOMEM; inst->cvp = kzalloc(sizeof(struct msm_cvp_external), GFP_KERNEL); if (!inst->cvp) { dprintk(VIDC_ERR, "%s: failed to allocate\n", __func__); - rc = -ENOMEM; - goto error; + return -ENOMEM; } cvp = inst->cvp; + cvp->arg = kzalloc(sizeof(struct cvp_kmd_arg), GFP_KERNEL); + if (!cvp->arg) { + kfree(inst->cvp); + inst->cvp = NULL; + return -ENOMEM; + } + arg = cvp->arg; + dprintk(VIDC_DBG, "%s: opening cvp\n", __func__); cvp->priv = msm_cvp_open(0, MSM_VIDC_CVP); if (!cvp->priv) { @@ -923,14 +1004,10 @@ static int msm_vidc_cvp_open(struct msm_vidc_inst *inst) dprintk(VIDC_DBG, "%s: cvp session id %#x\n", __func__, cvp->session_id); - kfree(arg); return 0; error: msm_vidc_cvp_close(inst); - kfree(inst->cvp); - inst->cvp = NULL; - kfree(arg); return rc; } diff --git a/msm/vidc/msm_cvp_external.h b/msm/vidc/msm_cvp_external.h index ed98428f78c3..522bf938452d 100644 --- a/msm/vidc/msm_cvp_external.h +++ b/msm/vidc/msm_cvp_external.h @@ -50,11 +50,6 @@ static inline bool is_vidc_cvp_enabled(struct msm_vidc_inst *inst) return !!inst->cvp; } -static inline bool is_vidc_cvp_allowed(struct msm_vidc_inst *inst) -{ - return false; -} - struct msm_cvp_buffer_type { u32 buffer_addr; u32 size; @@ -143,6 +138,7 @@ struct msm_cvp_buf { struct msm_cvp_external { void *priv; + void *arg; u32 session_id; u32 width; u32 height; @@ -151,6 +147,7 @@ struct msm_cvp_external { bool downscale; u32 framecount; u32 buffer_idx; + bool metadata_available; struct msm_cvp_buf fullres_buffer; struct msm_cvp_buf src_buffer; struct msm_cvp_buf ref_buffer; @@ -161,8 +158,7 @@ struct msm_cvp_external { }; int msm_vidc_cvp_preprocess(struct msm_vidc_inst *inst, - struct vb2_buffer *vb); + struct msm_vidc_buffer *mbuf); int msm_vidc_cvp_prepare_preprocess(struct msm_vidc_inst *inst); int msm_vidc_cvp_unprepare_preprocess(struct msm_vidc_inst *inst); - #endif diff --git a/msm/vidc/msm_v4l2_vidc.c b/msm/vidc/msm_v4l2_vidc.c index 1eb74547a8d3..24aaf7c2476f 100644 --- a/msm/vidc/msm_v4l2_vidc.c +++ b/msm/vidc/msm_v4l2_vidc.c @@ -519,7 +519,7 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) } /* setup the cvp device */ - if (core->resources.domain_cvp) { + if (core->resources.cvp_internal) { rc = msm_vidc_register_video_device(MSM_VIDC_CVP, nr + 2, core, dev); if (rc) { @@ -583,7 +583,7 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) err_fail_sub_device_probe: vidc_hfi_deinitialize(core->hfi_type, core->device); err_cores_exceeded: - if (core->resources.domain_cvp) { + if (core->resources.cvp_internal) { device_remove_file(&core->vdev[MSM_VIDC_CVP].vdev.dev, &dev_attr_link_name); video_unregister_device(&core->vdev[MSM_VIDC_CVP].vdev); @@ -663,7 +663,7 @@ static int msm_vidc_remove(struct platform_device *pdev) } vidc_hfi_deinitialize(core->hfi_type, core->device); - if (core->resources.domain_cvp) { + if (core->resources.cvp_internal) { device_remove_file(&core->vdev[MSM_VIDC_CVP].vdev.dev, &dev_attr_link_name); video_unregister_device(&core->vdev[MSM_VIDC_CVP].vdev); diff --git a/msm/vidc/msm_venc.c b/msm/vidc/msm_venc.c index a42802d5267b..df32fa8efe8f 100644 --- a/msm/vidc/msm_venc.c +++ b/msm/vidc/msm_venc.c @@ -3833,7 +3833,6 @@ int msm_venc_set_hdr_info(struct msm_vidc_inst *inst) int msm_venc_set_extradata(struct msm_vidc_inst *inst) { int rc = 0; - struct v4l2_ctrl *cvp_ctrl; u32 value = 0x0; u32 codec; @@ -3872,25 +3871,13 @@ int msm_venc_set_extradata(struct msm_vidc_inst *inst) } } - cvp_ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VENC_CVP_DISABLE); - if (cvp_ctrl->val == V4L2_MPEG_MSM_VIDC_ENABLE) { - if (inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_CVP) { - dprintk(VIDC_ERR, - "%s: invalid params\n", __func__); - return -EINVAL; - } - } else { - /* - * For now, enable CVP metadata only if client provides it. - * Once the kernel-mode CVP metadata implementation - * is completed, this condition should be removed. - */ - if (inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_CVP) - value = 0x1; - - } + if (inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_CVP) + value = 0x1; + dprintk(VIDC_DBG, "%s: CVP extradata %d\n", __func__, value); rc = msm_comm_set_extradata(inst, HFI_PROPERTY_PARAM_VENC_CVP_METADATA_EXTRADATA, value); + if (rc) + dprintk(VIDC_ERR, "%s: set CVP extradata failed\n", __func__); return rc; } diff --git a/msm/vidc/msm_vidc.c b/msm/vidc/msm_vidc.c index 15954723facb..e0a88fbe9f5b 100644 --- a/msm/vidc/msm_vidc.c +++ b/msm/vidc/msm_vidc.c @@ -325,46 +325,6 @@ int msm_vidc_release_buffer(void *instance, int type, unsigned int index) } EXPORT_SYMBOL(msm_vidc_release_buffer); -static int msm_vidc_preprocess(struct msm_vidc_inst *inst, - struct vb2_buffer *vb) -{ - int rc = 0; - struct buf_queue *q; - - if (!inst || !vb) { - dprintk(VIDC_ERR, "%s: invalid params\n", __func__); - return -EINVAL; - } - - if (!is_encode_session(inst) || vb->type != - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) - return 0; - - if (!is_vidc_cvp_enabled(inst)) - return 0; - - q = msm_comm_get_vb2q(inst, vb->type); - if (!q) { - dprintk(VIDC_ERR, "%s: queue not found for type %d\n", - __func__, vb->type); - return -EINVAL; - } - if (!q->vb2_bufq.streaming) { - dprintk(VIDC_ERR, - "%s: enable input port streaming before queuing input buffers\n", - __func__); - return -EINVAL; - } - rc = msm_vidc_cvp_preprocess(inst, vb); - if (rc) { - dprintk(VIDC_ERR, "%s: cvp preprocess failed\n", - __func__); - return rc; - } - - return rc; -} - int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b) { struct msm_vidc_inst *inst = instance; @@ -739,6 +699,51 @@ static int msm_vidc_set_properties(struct msm_vidc_inst *inst) return rc; } +bool is_vidc_cvp_allowed(struct msm_vidc_inst *inst) +{ + bool allowed = false; + struct msm_vidc_core *core; + struct v4l2_ctrl *cvp_disable; + + if (!inst || !inst->core) { + dprintk(VIDC_ERR, "%s: invalid params\n", __func__); + goto exit; + } + core = inst->core; + + /* + * CVP enable if + * - platform support CVP external + * - client did not disable CVP forcefully + * - client may disable forcefully to save power + * - client did not enable CVP extradata + * - if enabled, client will give CVP extradata + * - rate control is not one of below modes + * - RATE_CONTROL_OFF + * - V4L2_MPEG_VIDEO_BITRATE_MODE_CQ + * - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_PLUS + */ + cvp_disable = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VENC_CVP_DISABLE); + + if (core->resources.cvp_external && !cvp_disable->val && + !(inst->prop.extradata_ctrls & EXTRADATA_ENC_INPUT_CVP) && + inst->rc_type != RATE_CONTROL_OFF && + inst->rc_type != V4L2_MPEG_VIDEO_BITRATE_MODE_CQ && + !inst->clk_data.is_cbr_plus) { + dprintk(VIDC_DBG, "%s: cvp allowed\n", __func__); + allowed = true; + } else { + dprintk(VIDC_DBG, + "%s: cvp not allowed, cvp_external %d cvp_disable %d extradata %#x rc_type %d\n", + __func__, core->resources.cvp_external, + cvp_disable->val, inst->prop.extradata_ctrls, + inst->rc_type); + allowed = false; + } +exit: + return allowed; +} + static int msm_vidc_prepare_preprocess(struct msm_vidc_inst *inst) { int rc = 0; @@ -748,6 +753,11 @@ static int msm_vidc_prepare_preprocess(struct msm_vidc_inst *inst) return -EINVAL; } + if (!msm_vidc_cvp_usage) { + dprintk(VIDC_DBG, "%s: cvp usage disabled\n", __func__); + return 0; + } + if (!is_vidc_cvp_allowed(inst)) { dprintk(VIDC_DBG, "%s: cvp not allowed\n", __func__); return 0; @@ -756,12 +766,21 @@ static int msm_vidc_prepare_preprocess(struct msm_vidc_inst *inst) rc = msm_vidc_cvp_prepare_preprocess(inst); if (rc) { dprintk(VIDC_WARN, "%s: no cvp preprocessing\n", __func__); - msm_vidc_cvp_unprepare_preprocess(inst); goto exit; } dprintk(VIDC_DBG, "%s: cvp enabled\n", __func__); + dprintk(VIDC_DBG, "%s: set CVP extradata\n", __func__); + rc = msm_comm_set_extradata(inst, + HFI_PROPERTY_PARAM_VENC_CVP_METADATA_EXTRADATA, 1); + if (rc) { + dprintk(VIDC_WARN, "%s: set CVP extradata failed\n", __func__); + goto exit; + } + exit: + if (rc) + msm_vidc_cvp_unprepare_preprocess(inst); return rc; } @@ -783,6 +802,15 @@ static inline int start_streaming(struct msm_vidc_inst *inst) goto fail_start; } + if (is_encode_session(inst)) { + rc = msm_vidc_prepare_preprocess(inst); + if (rc) { + dprintk(VIDC_WARN, "%s: no preprocessing\n", __func__); + /* ignore error */ + rc = 0; + } + } + b.buffer_type = HFI_BUFFER_OUTPUT; if (inst->session_type == MSM_VIDC_DECODER && is_secondary_output_mode(inst)) @@ -968,16 +996,6 @@ static int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count) goto stream_start_failed; } - if (is_encode_session(inst) && q->type == - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - rc = msm_vidc_prepare_preprocess(inst); - if (rc) { - dprintk(VIDC_WARN, "%s: no preprocessing\n", __func__); - /* ignore error */ - rc = 0; - } - } - rc = msm_comm_qbufs(inst); if (rc) { dprintk(VIDC_ERR, @@ -1027,24 +1045,6 @@ stream_start_failed: return rc; } -static inline int stop_streaming(struct msm_vidc_inst *inst) -{ - int rc = 0; - - dprintk(VIDC_DBG, "%s: %x : inst %pK\n", __func__, - hash32_ptr(inst->session), inst); - - rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); - if (rc) - dprintk(VIDC_ERR, - "Failed to move inst: %pK to state %d\n", - inst, MSM_VIDC_RELEASE_RESOURCES_DONE); - - msm_clock_data_reset(inst); - - return rc; -} - static int msm_vidc_unprepare_preprocess(struct msm_vidc_inst *inst) { int rc = 0; @@ -1066,6 +1066,32 @@ static int msm_vidc_unprepare_preprocess(struct msm_vidc_inst *inst) return rc; } +static inline int stop_streaming(struct msm_vidc_inst *inst) +{ + int rc = 0; + + dprintk(VIDC_DBG, "%s: %x : inst %pK\n", __func__, + hash32_ptr(inst->session), inst); + + rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + if (rc) + dprintk(VIDC_ERR, + "Failed to move inst: %pK to state %d\n", + inst, MSM_VIDC_RELEASE_RESOURCES_DONE); + + if (is_encode_session(inst)) { + rc = msm_vidc_unprepare_preprocess(inst); + if (rc) + dprintk(VIDC_ERR, + "%s: failed to unprepare preprocess\n", + __func__); + } + + msm_clock_data_reset(inst); + + return rc; +} + static void msm_vidc_stop_streaming(struct vb2_queue *q) { struct msm_vidc_inst *inst; @@ -1078,16 +1104,6 @@ static void msm_vidc_stop_streaming(struct vb2_queue *q) inst = q->drv_priv; dprintk(VIDC_DBG, "Streamoff called on: %d capability\n", q->type); - - if (is_encode_session(inst) && q->type == - V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - rc = msm_vidc_unprepare_preprocess(inst); - if (rc) - dprintk(VIDC_ERR, - "%s: failed to unprepare preprocess\n", - __func__); - } - switch (q->type) { case INPUT_MPLANE: if (!inst->bufq[OUTPUT_PORT].vb2_bufq.streaming) @@ -1209,20 +1225,11 @@ static void msm_vidc_buf_queue(struct vb2_buffer *vb2) return; } - /* do preprocessing if any */ - rc = msm_vidc_preprocess(inst, vb2); - if (rc) { - dprintk(VIDC_ERR, "%s: preprocess failed %x\n", - __func__, hash32_ptr(inst->session)); - goto exit; - } - if (inst->batch.enable) rc = msm_vidc_queue_buf_batch(inst, vb2); else rc = msm_vidc_queue_buf(inst, vb2); -exit: if (rc) { print_vb2_buffer(VIDC_ERR, "failed vb2-qbuf", inst, vb2); msm_comm_generate_session_error(inst); diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index 5a633cd0f5df..390f119f9611 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -15,6 +15,7 @@ #include "vidc_hfi.h" #include "msm_vidc_debug.h" #include "msm_vidc_clocks.h" +#include "msm_cvp_external.h" #include "msm_cvp_internal.h" #include "msm_vidc_buffer_calculations.h" @@ -4058,6 +4059,34 @@ int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd) return rc; } +static int msm_comm_preprocess(struct msm_vidc_inst *inst, + struct msm_vidc_buffer *mbuf) +{ + int rc = 0; + + if (!inst || !mbuf) { + dprintk(VIDC_ERR, "%s: invalid params\n", __func__); + return -EINVAL; + } + + /* preprocessing is allowed for encoder input buffer only */ + if (!is_encode_session(inst) || mbuf->vvb.vb2_buf.type != INPUT_MPLANE) + return 0; + + /* preprocessing is done using CVP module only */ + if (!is_vidc_cvp_enabled(inst)) + return 0; + + rc = msm_vidc_cvp_preprocess(inst, mbuf); + if (rc) { + dprintk(VIDC_ERR, "%s: cvp preprocess failed\n", + __func__); + return rc; + } + + return rc; +} + static void populate_frame_data(struct vidc_frame_data *data, struct msm_vidc_buffer *mbuf, struct msm_vidc_inst *inst) { @@ -4264,6 +4293,10 @@ int msm_comm_qbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf) return 0; } + rc = msm_comm_preprocess(inst, mbuf); + if (rc) + return rc; + rc = msm_comm_scale_clocks_and_bus(inst); if (rc) dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__); @@ -4280,6 +4313,7 @@ int msm_comm_qbufs(struct msm_vidc_inst *inst) { int rc = 0; struct msm_vidc_buffer *mbuf; + bool found; if (!inst) { dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__); @@ -4292,24 +4326,36 @@ int msm_comm_qbufs(struct msm_vidc_inst *inst) return 0; } - rc = msm_comm_scale_clocks_and_bus(inst); - if (rc) - dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__); - - mutex_lock(&inst->registeredbufs.lock); - list_for_each_entry(mbuf, &inst->registeredbufs.list, list) { - /* Queue only deferred buffers */ - if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED)) - continue; - print_vidc_buffer(VIDC_DBG, "qbufs", inst, mbuf); - rc = msm_comm_qbuf_to_hfi(inst, mbuf); - if (rc) { - dprintk(VIDC_ERR, "%s: Failed qbuf to hfi: %d\n", - __func__, rc); + do { + mutex_lock(&inst->registeredbufs.lock); + found = false; + list_for_each_entry(mbuf, &inst->registeredbufs.list, list) { + /* Queue only deferred buffers */ + if (mbuf->flags & MSM_VIDC_FLAG_DEFERRED) { + found = true; + break; + } + } + mutex_unlock(&inst->registeredbufs.lock); + if (!found) { + dprintk(VIDC_DBG, + "%s: no more deferred qbufs\n", __func__); break; } - } - mutex_unlock(&inst->registeredbufs.lock); + + /* do not call msm_comm_qbuf() under registerbufs lock */ + if (!kref_get_mbuf(inst, mbuf)) { + dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__); + rc = -EINVAL; + break; + } + rc = msm_comm_qbuf(inst, mbuf); + kref_put_mbuf(mbuf); + if (rc) { + dprintk(VIDC_ERR, "%s: failed qbuf\n", __func__); + break; + } + } while (found); return rc; } diff --git a/msm/vidc/msm_vidc_debug.c b/msm/vidc/msm_vidc_debug.c index 17ff19228c83..abaf11ac117c 100644 --- a/msm/vidc/msm_vidc_debug.c +++ b/msm/vidc/msm_vidc_debug.c @@ -25,6 +25,7 @@ bool msm_vidc_fw_coverage = !true; bool msm_vidc_thermal_mitigation_disabled = !true; int msm_vidc_clock_voting = !1; bool msm_vidc_syscache_disable = !true; +bool msm_vidc_cvp_usage = !true; #define MAX_DBG_BUF_SIZE 4096 @@ -188,6 +189,7 @@ struct dentry *msm_vidc_debugfs_init_drv(void) &msm_vidc_clock_voting) && __debugfs_create(bool, "disable_video_syscache", &msm_vidc_syscache_disable) && + __debugfs_create(bool, "cvp_usage", &msm_vidc_cvp_usage) && __debugfs_create(bool, "lossless_encoding", &msm_vidc_lossless_encode); diff --git a/msm/vidc/msm_vidc_debug.h b/msm/vidc/msm_vidc_debug.h index a06bf2b2f844..58217d5c03d9 100644 --- a/msm/vidc/msm_vidc_debug.h +++ b/msm/vidc/msm_vidc_debug.h @@ -61,6 +61,7 @@ extern bool msm_vidc_thermal_mitigation_disabled; extern int msm_vidc_clock_voting; extern bool msm_vidc_syscache_disable; extern bool msm_vidc_lossless_encode; +extern bool msm_vidc_cvp_usage; #define dprintk(__level, __fmt, ...) \ do { \ diff --git a/msm/vidc/msm_vidc_platform.c b/msm/vidc/msm_vidc_platform.c index 2f5b6a05dac6..6b25adff4afd 100644 --- a/msm/vidc/msm_vidc_platform.c +++ b/msm/vidc/msm_vidc_platform.c @@ -299,7 +299,7 @@ static struct msm_vidc_common_data lito_common_data_v0[] = { .value = 0, }, { - .key = "qcom,domain-cvp", + .key = "qcom,cvp-internal", .value = 1, }, { @@ -370,7 +370,7 @@ static struct msm_vidc_common_data lito_common_data_v1[] = { .value = 0, }, { - .key = "qcom,domain-cvp", + .key = "qcom,cvp-internal", .value = 1, }, { @@ -445,8 +445,8 @@ static struct msm_vidc_common_data kona_common_data[] = { .value = 0, }, { - .key = "qcom,domain-cvp", - .value = 0, + .key = "qcom,cvp-external", + .value = 1, }, { .key = "qcom,decode-batching", @@ -587,7 +587,7 @@ static struct msm_vidc_common_data sm8150_common_data[] = { .value = 0, }, { - .key = "qcom,domain-cvp", + .key = "qcom,cvp-internal", .value = 1, }, { diff --git a/msm/vidc/msm_vidc_res_parse.c b/msm/vidc/msm_vidc_res_parse.c index 855078b9aaf2..de1d60a124b7 100644 --- a/msm/vidc/msm_vidc_res_parse.c +++ b/msm/vidc/msm_vidc_res_parse.c @@ -806,8 +806,10 @@ int read_platform_resources_from_drv_data( "qcom,fw-unload-delay"); res->msm_vidc_hw_rsp_timeout = find_key_value(platform_data, "qcom,hw-resp-timeout"); - res->domain_cvp = find_key_value(platform_data, - "qcom,domain-cvp"); + res->cvp_internal = find_key_value(platform_data, + "qcom,cvp-internal"); + res->cvp_external = find_key_value(platform_data, + "qcom,cvp-external"); res->non_fatal_pagefaults = find_key_value(platform_data, "qcom,domain-attr-non-fatal-faults"); res->cache_pagetables = find_key_value(platform_data, diff --git a/msm/vidc/msm_vidc_resources.h b/msm/vidc/msm_vidc_resources.h index 7043b81d396b..c6ea445d14f3 100644 --- a/msm/vidc/msm_vidc_resources.h +++ b/msm/vidc/msm_vidc_resources.h @@ -188,7 +188,8 @@ struct msm_vidc_platform_resources { int msm_vidc_hw_rsp_timeout; int msm_vidc_firmware_unload_delay; uint32_t msm_vidc_pwr_collapse_delay; - bool domain_cvp; + bool cvp_internal; + bool cvp_external; bool non_fatal_pagefaults; bool cache_pagetables; bool decode_batching;