Loading drivers/media/platform/msm/vidc/msm_vdec.c +5 −1 Original line number Diff line number Diff line Loading @@ -717,12 +717,14 @@ int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) int msm_vdec_inst_init(struct msm_vidc_inst *inst) { int rc = 0; struct msm_vidc_core *core; struct msm_vidc_format *fmt = NULL; if (!inst) { if (!inst || !inst->core) { dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); return -EINVAL; } core = inst->core; inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT; inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH; inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT; Loading @@ -740,6 +742,8 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->bufq[CAPTURE_PORT].num_planes = 1; inst->prop.fps = DEFAULT_FPS; inst->clk_data.operating_rate = 0; if (core->resources.decode_batching) inst->batch.size = MAX_DEC_BATCH_SIZE; /* By default, initialize CAPTURE port to UBWC YUV format */ fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats, Loading drivers/media/platform/msm/vidc/msm_vidc.c +136 −24 Original line number Diff line number Diff line Loading @@ -231,16 +231,25 @@ EXPORT_SYMBOL(msm_vidc_query_ctrl); int msm_vidc_s_fmt(void *instance, struct v4l2_format *f) { int rc = 0; struct msm_vidc_inst *inst = instance; if (!inst || !f) return -EINVAL; if (inst->session_type == MSM_VIDC_DECODER) return msm_vdec_s_fmt(instance, f); rc = msm_vdec_s_fmt(instance, f); if (inst->session_type == MSM_VIDC_ENCODER) return msm_venc_s_fmt(instance, f); return -EINVAL; rc = msm_venc_s_fmt(instance, f); dprintk(VIDC_DBG, "s_fmt: %x : type %d wxh %dx%d pixelfmt %#x num_planes %d size[0] %d size[1] %d in_reconfig %d\n", hash32_ptr(inst->session), f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.plane_fmt[0].sizeimage, f->fmt.pix_mp.plane_fmt[1].sizeimage, inst->in_reconfig); return rc; } EXPORT_SYMBOL(msm_vidc_s_fmt); Loading Loading @@ -297,6 +306,13 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f) f->fmt.pix_mp.plane_fmt[0].reserved[0] = VENUS_Y_SCANLINES(color_format, inst->prop.height[port]); dprintk(VIDC_DBG, "g_fmt: %x : type %d wxh %dx%d pixelfmt %#x num_planes %d size[0] %d size[1] %d in_reconfig %d\n", hash32_ptr(inst->session), f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.plane_fmt[0].sizeimage, f->fmt.pix_mp.plane_fmt[1].sizeimage, inst->in_reconfig); exit: return rc; } Loading Loading @@ -837,6 +853,11 @@ static int msm_vidc_queue_setup(struct vb2_queue *q, rc = -EINVAL; break; } dprintk(VIDC_DBG, "queue_setup: %x : type %d num_buffers %d num_planes %d sizes[0] %d sizes[1] %d\n", hash32_ptr(inst->session), q->type, *num_buffers, *num_planes, sizes[0], sizes[1]); return rc; } Loading Loading @@ -983,6 +1004,15 @@ static inline int start_streaming(struct msm_vidc_inst *inst) } } if (is_batching_allowed(inst)) { dprintk(VIDC_DBG, "%s: batching enabled for inst %pK (%#x)\n", __func__, inst, hash32_ptr(inst->session)); inst->batch.enable = true; /* this will disable dcvs as batching enabled */ msm_dcvs_try_enable(inst); } /* * For seq_changed_insufficient, driver should set session_continue * to firmware after the following sequence Loading Loading @@ -1164,43 +1194,112 @@ static void msm_vidc_stop_streaming(struct vb2_queue *q) inst, q->type); } static void msm_vidc_buf_queue(struct vb2_buffer *vb2) static int msm_vidc_queue_buf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc = 0; struct msm_vidc_inst *inst = NULL; struct msm_vidc_buffer *mbuf = NULL; struct msm_vidc_buffer *mbuf; inst = vb2_get_drv_priv(vb2->vb2_queue); if (!inst) { dprintk(VIDC_ERR, "%s: invalid inst\n", __func__); return; if (!inst || !vb2) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } mbuf = msm_comm_get_vidc_buffer(inst, vb2); if (IS_ERR_OR_NULL(mbuf)) { /* * if the buffer has RBR_PENDING flag (-EEXIST) then don't queue * it now, it will be queued via msm_comm_qbuf_rbr() as part of * RBR event processing. */ if (PTR_ERR(mbuf) == -EEXIST) return; print_vb2_buffer(VIDC_ERR, "failed to get vidc-buf", inst, vb2); rc = -EINVAL; goto error; return 0; dprintk(VIDC_ERR, "%s: failed to get vidc-buf\n", __func__); return -EINVAL; } if (!kref_get_mbuf(inst, mbuf)) { dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__); rc = -EINVAL; goto error; return -EINVAL; } rc = msm_comm_qbuf(inst, mbuf); if (rc) print_vidc_buffer(VIDC_ERR, "failed qbuf", inst, mbuf); dprintk(VIDC_ERR, "%s: failed qbuf\n", __func__); kref_put_mbuf(mbuf); error: return rc; } static int msm_vidc_queue_buf_decode_batch(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc; struct msm_vidc_buffer *mbuf; if (!inst || !vb2) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } mbuf = msm_comm_get_vidc_buffer(inst, vb2); if (IS_ERR_OR_NULL(mbuf)) { dprintk(VIDC_ERR, "%s: failed to get vidc-buf\n", __func__); return -EINVAL; } if (!kref_get_mbuf(inst, mbuf)) { dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__); return -EINVAL; } /* * If this buffer has RBR_EPNDING then it will not be queued * but it may trigger full batch queuing in below function. */ rc = msm_comm_qbuf_decode_batch(inst, mbuf); if (rc) dprintk(VIDC_ERR, "%s: failed qbuf\n", __func__); kref_put_mbuf(mbuf); return rc; } static int msm_vidc_queue_buf_batch(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc; if (!inst || !vb2) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } if (inst->session_type == MSM_VIDC_DECODER && vb2->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) rc = msm_vidc_queue_buf_decode_batch(inst, vb2); else rc = msm_vidc_queue_buf(inst, vb2); return rc; } static void msm_vidc_buf_queue(struct vb2_buffer *vb2) { int rc = 0; struct msm_vidc_inst *inst = NULL; inst = vb2_get_drv_priv(vb2->vb2_queue); if (!inst) { dprintk(VIDC_ERR, "%s: invalid inst\n", __func__); return; } if (inst->batch.enable) rc = msm_vidc_queue_buf_batch(inst, vb2); else rc = msm_vidc_queue_buf(inst, vb2); if (rc) { print_vb2_buffer(VIDC_ERR, "failed vb2-qbuf", inst, vb2); msm_comm_generate_session_error(inst); } } static const struct vb2_ops msm_vidc_vb2q_ops = { .queue_setup = msm_vidc_queue_setup, Loading Loading @@ -1402,7 +1501,8 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, ctrl->val = bufreq->buffer_count_min_host; return 0; } if (ctrl->val > bufreq->buffer_count_min_host) { if (ctrl->val > bufreq->buffer_count_min_host && ctrl->val <= MAX_NUM_OUTPUT_BUFFERS) { dprintk(VIDC_DBG, "Buffer count Host changed from %d to %d\n", bufreq->buffer_count_min_host, Loading @@ -1421,6 +1521,12 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, msm_vidc_update_host_buff_counts(inst); ctrl->val = bufreq->buffer_count_min_host; dprintk(VIDC_DBG, "g_count: %x : OUTPUT: min %d min_host %d actual %d\n", hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); return rc; } else if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) { Loading Loading @@ -1452,7 +1558,8 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, bufreq->buffer_count_min_host = ctrl->val; } if (ctrl->val > bufreq->buffer_count_min_host) { if (ctrl->val > bufreq->buffer_count_min_host && ctrl->val <= MAX_NUM_CAPTURE_BUFFERS) { dprintk(VIDC_DBG, "Buffer count Host changed from %d to %d\n", bufreq->buffer_count_min_host, Loading @@ -1471,7 +1578,12 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, msm_vidc_update_host_buff_counts(inst); ctrl->val = bufreq->buffer_count_min_host; dprintk(VIDC_DBG, "g_count: %x : CAPTURE: min %d min_host %d actual %d\n", hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); return rc; } return -EINVAL; Loading drivers/media/platform/msm/vidc/msm_vidc_clocks.c +31 −9 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ static inline unsigned long int get_ubwc_compression_ratio( return compression_ratio; } static inline int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst) int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst) { int height, width; Loading Loading @@ -370,8 +370,9 @@ static int msm_dcvs_scale_clocks(struct msm_vidc_inst *inst) return -EINVAL; } if (!inst->clk_data.dcvs_mode) { dprintk(VIDC_DBG, "DCVS is not enabled\n"); if (!inst->clk_data.dcvs_mode || inst->batch.enable) { dprintk(VIDC_DBG, "Skip DCVS (dcvs %d, batching %d)\n", inst->clk_data.dcvs_mode, inst->batch.enable); return 0; } Loading Loading @@ -871,16 +872,16 @@ int msm_dcvs_try_enable(struct msm_vidc_inst *inst) if (msm_vidc_clock_voting || inst->flags & VIDC_THUMBNAIL || inst->clk_data.low_latency_mode) { dprintk(VIDC_PROF, "This session doesn't need DCVS : %pK\n", inst); inst->clk_data.low_latency_mode || inst->batch.enable) { dprintk(VIDC_PROF, "DCVS disabled: %pK\n", inst); inst->clk_data.extra_capture_buffer_count = 0; inst->clk_data.extra_output_buffer_count = 0; inst->clk_data.dcvs_mode = false; return false; } inst->clk_data.dcvs_mode = true; dprintk(VIDC_PROF, "DCVS enabled: %pK\n", inst); inst->clk_data.extra_capture_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS; Loading Loading @@ -996,14 +997,35 @@ void msm_clock_data_reset(struct msm_vidc_inst *inst) int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { if (!inst) { int count = 0; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s Invalid args\n", __func__); return 0; } /* * no extra buffers for thumbnail session because * neither dcvs nor batching will be enabled */ if (is_thumbnail_session(inst)) return 0; return buffer_type == HAL_BUFFER_INPUT ? count = buffer_type == HAL_BUFFER_INPUT ? inst->clk_data.extra_output_buffer_count : inst->clk_data.extra_capture_buffer_count; /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ if (buffer_type == HAL_BUFFER_OUTPUT) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) count = inst->batch.size; } return count; } int msm_vidc_decide_work_route(struct msm_vidc_inst *inst) Loading drivers/media/platform/msm/vidc/msm_vidc_clocks.h +1 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, int msm_vidc_set_clocks(struct msm_vidc_core *core); int msm_comm_vote_bus(struct msm_vidc_core *core); int msm_dcvs_try_enable(struct msm_vidc_inst *inst); int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst); int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst); int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst); void msm_comm_free_freq_table(struct msm_vidc_inst *inst); Loading drivers/media/platform/msm/vidc/msm_vidc_common.c +151 −44 Original line number Diff line number Diff line Loading @@ -74,36 +74,6 @@ const char *const mpeg_video_vidc_extradata[] = { static void handle_session_error(enum hal_command_response cmd, void *data); static void msm_vidc_print_running_insts(struct msm_vidc_core *core); bool msm_comm_turbo_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_TURBO); } static inline bool is_thumbnail_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_THUMBNAIL); } static inline bool is_low_power_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_LOW_POWER); } static inline bool is_realtime_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_REALTIME); } int msm_comm_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl) { return v4l2_g_ctrl(&inst->ctrl_handler, ctrl); } int msm_comm_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl) { return v4l2_s_ctrl(NULL, &inst->ctrl_handler, ctrl); } int msm_comm_g_ctrl_for_id(struct msm_vidc_inst *inst, int id) { int rc = 0; Loading Loading @@ -795,7 +765,7 @@ int msm_comm_get_inst_load(struct msm_vidc_inst *inst, load = 0; } if (msm_comm_turbo_session(inst)) { if (is_turbo_session(inst)) { if (!(quirks & LOAD_CALC_IGNORE_TURBO_LOAD)) load = inst->core->resources.max_load; } Loading Loading @@ -2773,6 +2743,35 @@ static bool is_thermal_permissible(struct msm_vidc_core *core) return true; } bool is_batching_allowed(struct msm_vidc_inst *inst) { bool allowed = false; if (!inst || !inst->core) return false; /* * Enable decode batching based on below conditions * - decode session * - platform supports batching * - session resolution <= 1080p * - low latency not enabled * - not a thumbnail session * - realtime session * - UBWC color format */ if (is_decode_session(inst) && inst->core->resources.decode_batching && (msm_vidc_get_mbs_per_frame(inst) <= MAX_DEC_BATCH_WIDTH * MAX_DEC_BATCH_HEIGHT) && !inst->clk_data.low_latency_mode && !is_thumbnail_session(inst) && is_realtime_session(inst) && (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_NV12_UBWC || inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_NV12_TP10_UBWC)) allowed = true; return allowed; } static int msm_comm_session_abort(struct msm_vidc_inst *inst) { int rc = 0, abort_completion = 0; Loading Loading @@ -3107,7 +3106,7 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core) if (is_thumbnail_session(temp)) strlcat(properties, "N", sizeof(properties)); if (msm_comm_turbo_session(temp)) if (is_turbo_session(temp)) strlcat(properties, "T", sizeof(properties)); dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n", Loading Loading @@ -3977,6 +3976,30 @@ enum hal_buffer get_hal_buffer_type(unsigned int type, } } static int num_pending_qbufs(struct msm_vidc_inst *inst, u32 type) { int count = 0; struct msm_vidc_buffer *mbuf; if (!inst) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return 0; } mutex_lock(&inst->registeredbufs.lock); list_for_each_entry(mbuf, &inst->registeredbufs.list, list) { if (mbuf->vvb.vb2_buf.type != type) continue; /* Count only deferred buffers */ if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED)) continue; count++; } mutex_unlock(&inst->registeredbufs.lock); return count; } static int msm_comm_qbuf_to_hfi(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf) { Loading Loading @@ -4114,10 +4137,87 @@ int msm_comm_qbufs(struct msm_vidc_inst *inst) return rc; } /* * msm_comm_qbuf_decode_batch - count the buffers which are not queued to * firmware yet (count includes rbr pending buffers too) and * queue the buffers at once if full batch count reached. * Don't queue rbr pending buffers as they would be queued * when rbr event arrived from firmware. */ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf) { int rc = 0; u32 count = 0; struct msm_vidc_buffer *buf; if (!inst || !mbuf) { dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__); return -EINVAL; } if (inst->state == MSM_VIDC_CORE_INVALID) { dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__); return -EINVAL; } if (inst->state != MSM_VIDC_START_DONE) { mbuf->flags |= MSM_VIDC_FLAG_DEFERRED; print_vidc_buffer(VIDC_DBG, "qbuf deferred", inst, mbuf); return 0; } /* * Don't batch for initial few buffers to avoid startup latency increase * due to batching */ if (inst->count.fbd < 30) return msm_comm_qbuf(inst, mbuf); count = num_pending_qbufs(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (count < inst->batch.size) { mbuf->flags |= MSM_VIDC_FLAG_DEFERRED; print_vidc_buffer(VIDC_DBG, "qbuf_batch deferred", inst, mbuf); 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(buf, &inst->registeredbufs.list, list) { /* Don't queue if buffer is not CAPTURE_MPLANE */ if (!(buf->vvb.vb2_buf.type & V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) continue; /* Don't queue if buffer is not a deferred buffer */ if (!(buf->flags & MSM_VIDC_FLAG_DEFERRED)) continue; /* Don't queue if RBR event is pending on this buffer */ if (buf->flags & MSM_VIDC_FLAG_RBR_PENDING) continue; print_vidc_buffer(VIDC_DBG, "qbuf", inst, buf); rc = msm_comm_qbuf_to_hfi(inst, buf); if (rc) { dprintk(VIDC_ERR, "%s: Failed qbuf to hfi: %d\n", __func__, rc); break; } /* Queue pending buffers till the current buffer only */ if (buf == mbuf) break; } mutex_unlock(&inst->registeredbufs.lock); return rc; } int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst) { int extra_buffers; struct hal_buffer_requirements *bufreq; struct hal_buffer_requirements *bufreq_extra; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); Loading @@ -4130,11 +4230,24 @@ int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst) extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); bufreq->buffer_count_min_host = bufreq->buffer_count_min + extra_buffers; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); if (bufreq) { if (bufreq->buffer_count_min) bufreq->buffer_count_min_host = bufreq->buffer_count_min + extra_buffers; /* decode batching needs minimum batch size count of input buffers */ if (is_decode_session(inst) && !is_thumbnail_session(inst) && inst->core->resources.decode_batching && bufreq->buffer_count_min_host < inst->batch.size) bufreq->buffer_count_min_host = inst->batch.size; /* adjust min_host count for VP9 decoder */ if (is_decode_session(inst) && !is_thumbnail_session(inst) && inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9 && bufreq->buffer_count_min_host < MIN_NUM_OUTPUT_BUFFERS_VP9) bufreq->buffer_count_min_host = MIN_NUM_OUTPUT_BUFFERS_VP9; bufreq_extra = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); if (bufreq_extra) { if (bufreq_extra->buffer_count_min) bufreq_extra->buffer_count_min_host = bufreq->buffer_count_min_host; } if (msm_comm_get_stream_output_mode(inst) == Loading Loading @@ -6065,15 +6178,9 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst, if (found_plane0) rc = -EEXIST; } /* * If RBR pending on this buffer then enable RBR_PENDING flag * and clear the DEFERRED flag to avoid this buffer getting * queued to video hardware in msm_comm_qbuf() which tries to * queue all the DEFERRED buffers. */ if (rc == -EEXIST) { /* enable RBR pending */ mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING; mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED; } } Loading Loading
drivers/media/platform/msm/vidc/msm_vdec.c +5 −1 Original line number Diff line number Diff line Loading @@ -717,12 +717,14 @@ int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) int msm_vdec_inst_init(struct msm_vidc_inst *inst) { int rc = 0; struct msm_vidc_core *core; struct msm_vidc_format *fmt = NULL; if (!inst) { if (!inst || !inst->core) { dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); return -EINVAL; } core = inst->core; inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT; inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH; inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT; Loading @@ -740,6 +742,8 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->bufq[CAPTURE_PORT].num_planes = 1; inst->prop.fps = DEFAULT_FPS; inst->clk_data.operating_rate = 0; if (core->resources.decode_batching) inst->batch.size = MAX_DEC_BATCH_SIZE; /* By default, initialize CAPTURE port to UBWC YUV format */ fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats, Loading
drivers/media/platform/msm/vidc/msm_vidc.c +136 −24 Original line number Diff line number Diff line Loading @@ -231,16 +231,25 @@ EXPORT_SYMBOL(msm_vidc_query_ctrl); int msm_vidc_s_fmt(void *instance, struct v4l2_format *f) { int rc = 0; struct msm_vidc_inst *inst = instance; if (!inst || !f) return -EINVAL; if (inst->session_type == MSM_VIDC_DECODER) return msm_vdec_s_fmt(instance, f); rc = msm_vdec_s_fmt(instance, f); if (inst->session_type == MSM_VIDC_ENCODER) return msm_venc_s_fmt(instance, f); return -EINVAL; rc = msm_venc_s_fmt(instance, f); dprintk(VIDC_DBG, "s_fmt: %x : type %d wxh %dx%d pixelfmt %#x num_planes %d size[0] %d size[1] %d in_reconfig %d\n", hash32_ptr(inst->session), f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.plane_fmt[0].sizeimage, f->fmt.pix_mp.plane_fmt[1].sizeimage, inst->in_reconfig); return rc; } EXPORT_SYMBOL(msm_vidc_s_fmt); Loading Loading @@ -297,6 +306,13 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f) f->fmt.pix_mp.plane_fmt[0].reserved[0] = VENUS_Y_SCANLINES(color_format, inst->prop.height[port]); dprintk(VIDC_DBG, "g_fmt: %x : type %d wxh %dx%d pixelfmt %#x num_planes %d size[0] %d size[1] %d in_reconfig %d\n", hash32_ptr(inst->session), f->type, f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.num_planes, f->fmt.pix_mp.plane_fmt[0].sizeimage, f->fmt.pix_mp.plane_fmt[1].sizeimage, inst->in_reconfig); exit: return rc; } Loading Loading @@ -837,6 +853,11 @@ static int msm_vidc_queue_setup(struct vb2_queue *q, rc = -EINVAL; break; } dprintk(VIDC_DBG, "queue_setup: %x : type %d num_buffers %d num_planes %d sizes[0] %d sizes[1] %d\n", hash32_ptr(inst->session), q->type, *num_buffers, *num_planes, sizes[0], sizes[1]); return rc; } Loading Loading @@ -983,6 +1004,15 @@ static inline int start_streaming(struct msm_vidc_inst *inst) } } if (is_batching_allowed(inst)) { dprintk(VIDC_DBG, "%s: batching enabled for inst %pK (%#x)\n", __func__, inst, hash32_ptr(inst->session)); inst->batch.enable = true; /* this will disable dcvs as batching enabled */ msm_dcvs_try_enable(inst); } /* * For seq_changed_insufficient, driver should set session_continue * to firmware after the following sequence Loading Loading @@ -1164,43 +1194,112 @@ static void msm_vidc_stop_streaming(struct vb2_queue *q) inst, q->type); } static void msm_vidc_buf_queue(struct vb2_buffer *vb2) static int msm_vidc_queue_buf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc = 0; struct msm_vidc_inst *inst = NULL; struct msm_vidc_buffer *mbuf = NULL; struct msm_vidc_buffer *mbuf; inst = vb2_get_drv_priv(vb2->vb2_queue); if (!inst) { dprintk(VIDC_ERR, "%s: invalid inst\n", __func__); return; if (!inst || !vb2) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } mbuf = msm_comm_get_vidc_buffer(inst, vb2); if (IS_ERR_OR_NULL(mbuf)) { /* * if the buffer has RBR_PENDING flag (-EEXIST) then don't queue * it now, it will be queued via msm_comm_qbuf_rbr() as part of * RBR event processing. */ if (PTR_ERR(mbuf) == -EEXIST) return; print_vb2_buffer(VIDC_ERR, "failed to get vidc-buf", inst, vb2); rc = -EINVAL; goto error; return 0; dprintk(VIDC_ERR, "%s: failed to get vidc-buf\n", __func__); return -EINVAL; } if (!kref_get_mbuf(inst, mbuf)) { dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__); rc = -EINVAL; goto error; return -EINVAL; } rc = msm_comm_qbuf(inst, mbuf); if (rc) print_vidc_buffer(VIDC_ERR, "failed qbuf", inst, mbuf); dprintk(VIDC_ERR, "%s: failed qbuf\n", __func__); kref_put_mbuf(mbuf); error: return rc; } static int msm_vidc_queue_buf_decode_batch(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc; struct msm_vidc_buffer *mbuf; if (!inst || !vb2) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } mbuf = msm_comm_get_vidc_buffer(inst, vb2); if (IS_ERR_OR_NULL(mbuf)) { dprintk(VIDC_ERR, "%s: failed to get vidc-buf\n", __func__); return -EINVAL; } if (!kref_get_mbuf(inst, mbuf)) { dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__); return -EINVAL; } /* * If this buffer has RBR_EPNDING then it will not be queued * but it may trigger full batch queuing in below function. */ rc = msm_comm_qbuf_decode_batch(inst, mbuf); if (rc) dprintk(VIDC_ERR, "%s: failed qbuf\n", __func__); kref_put_mbuf(mbuf); return rc; } static int msm_vidc_queue_buf_batch(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc; if (!inst || !vb2) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; } if (inst->session_type == MSM_VIDC_DECODER && vb2->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) rc = msm_vidc_queue_buf_decode_batch(inst, vb2); else rc = msm_vidc_queue_buf(inst, vb2); return rc; } static void msm_vidc_buf_queue(struct vb2_buffer *vb2) { int rc = 0; struct msm_vidc_inst *inst = NULL; inst = vb2_get_drv_priv(vb2->vb2_queue); if (!inst) { dprintk(VIDC_ERR, "%s: invalid inst\n", __func__); return; } if (inst->batch.enable) rc = msm_vidc_queue_buf_batch(inst, vb2); else rc = msm_vidc_queue_buf(inst, vb2); if (rc) { print_vb2_buffer(VIDC_ERR, "failed vb2-qbuf", inst, vb2); msm_comm_generate_session_error(inst); } } static const struct vb2_ops msm_vidc_vb2q_ops = { .queue_setup = msm_vidc_queue_setup, Loading Loading @@ -1402,7 +1501,8 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, ctrl->val = bufreq->buffer_count_min_host; return 0; } if (ctrl->val > bufreq->buffer_count_min_host) { if (ctrl->val > bufreq->buffer_count_min_host && ctrl->val <= MAX_NUM_OUTPUT_BUFFERS) { dprintk(VIDC_DBG, "Buffer count Host changed from %d to %d\n", bufreq->buffer_count_min_host, Loading @@ -1421,6 +1521,12 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, msm_vidc_update_host_buff_counts(inst); ctrl->val = bufreq->buffer_count_min_host; dprintk(VIDC_DBG, "g_count: %x : OUTPUT: min %d min_host %d actual %d\n", hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); return rc; } else if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) { Loading Loading @@ -1452,7 +1558,8 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, bufreq->buffer_count_min_host = ctrl->val; } if (ctrl->val > bufreq->buffer_count_min_host) { if (ctrl->val > bufreq->buffer_count_min_host && ctrl->val <= MAX_NUM_CAPTURE_BUFFERS) { dprintk(VIDC_DBG, "Buffer count Host changed from %d to %d\n", bufreq->buffer_count_min_host, Loading @@ -1471,7 +1578,12 @@ static int msm_vidc_get_count(struct msm_vidc_inst *inst, msm_vidc_update_host_buff_counts(inst); ctrl->val = bufreq->buffer_count_min_host; dprintk(VIDC_DBG, "g_count: %x : CAPTURE: min %d min_host %d actual %d\n", hash32_ptr(inst->session), bufreq->buffer_count_min, bufreq->buffer_count_min_host, bufreq->buffer_count_actual); return rc; } return -EINVAL; Loading
drivers/media/platform/msm/vidc/msm_vidc_clocks.c +31 −9 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ static inline unsigned long int get_ubwc_compression_ratio( return compression_ratio; } static inline int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst) int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst) { int height, width; Loading Loading @@ -370,8 +370,9 @@ static int msm_dcvs_scale_clocks(struct msm_vidc_inst *inst) return -EINVAL; } if (!inst->clk_data.dcvs_mode) { dprintk(VIDC_DBG, "DCVS is not enabled\n"); if (!inst->clk_data.dcvs_mode || inst->batch.enable) { dprintk(VIDC_DBG, "Skip DCVS (dcvs %d, batching %d)\n", inst->clk_data.dcvs_mode, inst->batch.enable); return 0; } Loading Loading @@ -871,16 +872,16 @@ int msm_dcvs_try_enable(struct msm_vidc_inst *inst) if (msm_vidc_clock_voting || inst->flags & VIDC_THUMBNAIL || inst->clk_data.low_latency_mode) { dprintk(VIDC_PROF, "This session doesn't need DCVS : %pK\n", inst); inst->clk_data.low_latency_mode || inst->batch.enable) { dprintk(VIDC_PROF, "DCVS disabled: %pK\n", inst); inst->clk_data.extra_capture_buffer_count = 0; inst->clk_data.extra_output_buffer_count = 0; inst->clk_data.dcvs_mode = false; return false; } inst->clk_data.dcvs_mode = true; dprintk(VIDC_PROF, "DCVS enabled: %pK\n", inst); inst->clk_data.extra_capture_buffer_count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS; Loading Loading @@ -996,14 +997,35 @@ void msm_clock_data_reset(struct msm_vidc_inst *inst) int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, enum hal_buffer buffer_type) { if (!inst) { int count = 0; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s Invalid args\n", __func__); return 0; } /* * no extra buffers for thumbnail session because * neither dcvs nor batching will be enabled */ if (is_thumbnail_session(inst)) return 0; return buffer_type == HAL_BUFFER_INPUT ? count = buffer_type == HAL_BUFFER_INPUT ? inst->clk_data.extra_output_buffer_count : inst->clk_data.extra_capture_buffer_count; /* * if platform supports decode batching ensure minimum * batch size count of extra buffers added on output port */ if (buffer_type == HAL_BUFFER_OUTPUT) { if (inst->core->resources.decode_batching && is_decode_session(inst) && count < inst->batch.size) count = inst->batch.size; } return count; } int msm_vidc_decide_work_route(struct msm_vidc_inst *inst) Loading
drivers/media/platform/msm/vidc/msm_vidc_clocks.h +1 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ int msm_vidc_get_extra_buff_count(struct msm_vidc_inst *inst, int msm_vidc_set_clocks(struct msm_vidc_core *core); int msm_comm_vote_bus(struct msm_vidc_core *core); int msm_dcvs_try_enable(struct msm_vidc_inst *inst); int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst); int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst); int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst); void msm_comm_free_freq_table(struct msm_vidc_inst *inst); Loading
drivers/media/platform/msm/vidc/msm_vidc_common.c +151 −44 Original line number Diff line number Diff line Loading @@ -74,36 +74,6 @@ const char *const mpeg_video_vidc_extradata[] = { static void handle_session_error(enum hal_command_response cmd, void *data); static void msm_vidc_print_running_insts(struct msm_vidc_core *core); bool msm_comm_turbo_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_TURBO); } static inline bool is_thumbnail_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_THUMBNAIL); } static inline bool is_low_power_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_LOW_POWER); } static inline bool is_realtime_session(struct msm_vidc_inst *inst) { return !!(inst->flags & VIDC_REALTIME); } int msm_comm_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl) { return v4l2_g_ctrl(&inst->ctrl_handler, ctrl); } int msm_comm_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl) { return v4l2_s_ctrl(NULL, &inst->ctrl_handler, ctrl); } int msm_comm_g_ctrl_for_id(struct msm_vidc_inst *inst, int id) { int rc = 0; Loading Loading @@ -795,7 +765,7 @@ int msm_comm_get_inst_load(struct msm_vidc_inst *inst, load = 0; } if (msm_comm_turbo_session(inst)) { if (is_turbo_session(inst)) { if (!(quirks & LOAD_CALC_IGNORE_TURBO_LOAD)) load = inst->core->resources.max_load; } Loading Loading @@ -2773,6 +2743,35 @@ static bool is_thermal_permissible(struct msm_vidc_core *core) return true; } bool is_batching_allowed(struct msm_vidc_inst *inst) { bool allowed = false; if (!inst || !inst->core) return false; /* * Enable decode batching based on below conditions * - decode session * - platform supports batching * - session resolution <= 1080p * - low latency not enabled * - not a thumbnail session * - realtime session * - UBWC color format */ if (is_decode_session(inst) && inst->core->resources.decode_batching && (msm_vidc_get_mbs_per_frame(inst) <= MAX_DEC_BATCH_WIDTH * MAX_DEC_BATCH_HEIGHT) && !inst->clk_data.low_latency_mode && !is_thumbnail_session(inst) && is_realtime_session(inst) && (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_NV12_UBWC || inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_NV12_TP10_UBWC)) allowed = true; return allowed; } static int msm_comm_session_abort(struct msm_vidc_inst *inst) { int rc = 0, abort_completion = 0; Loading Loading @@ -3107,7 +3106,7 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core) if (is_thumbnail_session(temp)) strlcat(properties, "N", sizeof(properties)); if (msm_comm_turbo_session(temp)) if (is_turbo_session(temp)) strlcat(properties, "T", sizeof(properties)); dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n", Loading Loading @@ -3977,6 +3976,30 @@ enum hal_buffer get_hal_buffer_type(unsigned int type, } } static int num_pending_qbufs(struct msm_vidc_inst *inst, u32 type) { int count = 0; struct msm_vidc_buffer *mbuf; if (!inst) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return 0; } mutex_lock(&inst->registeredbufs.lock); list_for_each_entry(mbuf, &inst->registeredbufs.list, list) { if (mbuf->vvb.vb2_buf.type != type) continue; /* Count only deferred buffers */ if (!(mbuf->flags & MSM_VIDC_FLAG_DEFERRED)) continue; count++; } mutex_unlock(&inst->registeredbufs.lock); return count; } static int msm_comm_qbuf_to_hfi(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf) { Loading Loading @@ -4114,10 +4137,87 @@ int msm_comm_qbufs(struct msm_vidc_inst *inst) return rc; } /* * msm_comm_qbuf_decode_batch - count the buffers which are not queued to * firmware yet (count includes rbr pending buffers too) and * queue the buffers at once if full batch count reached. * Don't queue rbr pending buffers as they would be queued * when rbr event arrived from firmware. */ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf) { int rc = 0; u32 count = 0; struct msm_vidc_buffer *buf; if (!inst || !mbuf) { dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__); return -EINVAL; } if (inst->state == MSM_VIDC_CORE_INVALID) { dprintk(VIDC_ERR, "%s: inst is in bad state\n", __func__); return -EINVAL; } if (inst->state != MSM_VIDC_START_DONE) { mbuf->flags |= MSM_VIDC_FLAG_DEFERRED; print_vidc_buffer(VIDC_DBG, "qbuf deferred", inst, mbuf); return 0; } /* * Don't batch for initial few buffers to avoid startup latency increase * due to batching */ if (inst->count.fbd < 30) return msm_comm_qbuf(inst, mbuf); count = num_pending_qbufs(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); if (count < inst->batch.size) { mbuf->flags |= MSM_VIDC_FLAG_DEFERRED; print_vidc_buffer(VIDC_DBG, "qbuf_batch deferred", inst, mbuf); 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(buf, &inst->registeredbufs.list, list) { /* Don't queue if buffer is not CAPTURE_MPLANE */ if (!(buf->vvb.vb2_buf.type & V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) continue; /* Don't queue if buffer is not a deferred buffer */ if (!(buf->flags & MSM_VIDC_FLAG_DEFERRED)) continue; /* Don't queue if RBR event is pending on this buffer */ if (buf->flags & MSM_VIDC_FLAG_RBR_PENDING) continue; print_vidc_buffer(VIDC_DBG, "qbuf", inst, buf); rc = msm_comm_qbuf_to_hfi(inst, buf); if (rc) { dprintk(VIDC_ERR, "%s: Failed qbuf to hfi: %d\n", __func__, rc); break; } /* Queue pending buffers till the current buffer only */ if (buf == mbuf) break; } mutex_unlock(&inst->registeredbufs.lock); return rc; } int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst) { int extra_buffers; struct hal_buffer_requirements *bufreq; struct hal_buffer_requirements *bufreq_extra; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT); Loading @@ -4130,11 +4230,24 @@ int msm_vidc_update_host_buff_counts(struct msm_vidc_inst *inst) extra_buffers = msm_vidc_get_extra_buff_count(inst, HAL_BUFFER_INPUT); bufreq->buffer_count_min_host = bufreq->buffer_count_min + extra_buffers; bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); if (bufreq) { if (bufreq->buffer_count_min) bufreq->buffer_count_min_host = bufreq->buffer_count_min + extra_buffers; /* decode batching needs minimum batch size count of input buffers */ if (is_decode_session(inst) && !is_thumbnail_session(inst) && inst->core->resources.decode_batching && bufreq->buffer_count_min_host < inst->batch.size) bufreq->buffer_count_min_host = inst->batch.size; /* adjust min_host count for VP9 decoder */ if (is_decode_session(inst) && !is_thumbnail_session(inst) && inst->fmts[OUTPUT_PORT].fourcc == V4L2_PIX_FMT_VP9 && bufreq->buffer_count_min_host < MIN_NUM_OUTPUT_BUFFERS_VP9) bufreq->buffer_count_min_host = MIN_NUM_OUTPUT_BUFFERS_VP9; bufreq_extra = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); if (bufreq_extra) { if (bufreq_extra->buffer_count_min) bufreq_extra->buffer_count_min_host = bufreq->buffer_count_min_host; } if (msm_comm_get_stream_output_mode(inst) == Loading Loading @@ -6065,15 +6178,9 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst, if (found_plane0) rc = -EEXIST; } /* * If RBR pending on this buffer then enable RBR_PENDING flag * and clear the DEFERRED flag to avoid this buffer getting * queued to video hardware in msm_comm_qbuf() which tries to * queue all the DEFERRED buffers. */ if (rc == -EEXIST) { /* enable RBR pending */ mbuf->flags |= MSM_VIDC_FLAG_RBR_PENDING; mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED; } } Loading