From: Ayoung Sim Date: Wed, 20 Mar 2019 07:47:16 +0000 (+0900) Subject: [COMMON] media: mfc: consider the bitrate for the QoS X-Git-Tag: MMI-QSAS30.62-33-3~886 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c66793225e808126ae8921f4764866528d06f2a0;p=GitHub%2FMotorolaMobilityLLC%2Fkernel-slsi.git [COMMON] media: mfc: consider the bitrate for the QoS Change-Id: Ibc09e0fc5e517ce34d540c3a47e2694930ab9e46 Signed-off-by: Ayoung Sim --- diff --git a/drivers/media/platform/exynos/mfc/mfc.c b/drivers/media/platform/exynos/mfc/mfc.c index 77200400f614..66a77c402c06 100644 --- a/drivers/media/platform/exynos/mfc/mfc.c +++ b/drivers/media/platform/exynos/mfc/mfc.c @@ -150,6 +150,7 @@ static int __mfc_init_dec_ctx(struct mfc_ctx *ctx) #ifdef CONFIG_MFC_USE_BUS_DEVFREQ INIT_LIST_HEAD(&ctx->qos_list); #endif + INIT_LIST_HEAD(&ctx->bitrate_list); INIT_LIST_HEAD(&ctx->ts_list); dec->display_delay = -1; @@ -1075,6 +1076,9 @@ static void __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc) of_property_read_u32(np, "qos_weight_num_of_tile", &pdata->qos_weight.weight_num_of_tile); of_property_read_u32(np, "qos_weight_super64_bframe", &pdata->qos_weight.weight_super64_bframe); #endif + /* Bitrate control for QoS */ + of_property_read_u32_array(np, "max_Kbps", pdata->max_Kbps, MAX_NUM_MFC_BPS); + dev->bps_ratio = pdata->max_Kbps[0] / dev->pdata->max_Kbps[1]; } static void *__mfc_get_drv_data(struct platform_device *pdev); diff --git a/drivers/media/platform/exynos/mfc/mfc_common.h b/drivers/media/platform/exynos/mfc/mfc_common.h index 0e7c28c29862..3badb63a5574 100644 --- a/drivers/media/platform/exynos/mfc/mfc_common.h +++ b/drivers/media/platform/exynos/mfc/mfc_common.h @@ -145,6 +145,7 @@ #define CODEC_422FORMAT(ctx) (IS_HEVC_DEC(ctx) || IS_HEVC_ENC(ctx) || \ IS_VP9_DEC(ctx) || IS_VP9_ENC(ctx) || \ IS_BPG_DEC(ctx) || IS_BPG_ENC(ctx)) +#define CODEC_HIGH_PERF(ctx) (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx)) #define ON_RES_CHANGE(ctx) (((ctx)->state >= MFCINST_RES_CHANGE_INIT) && \ ((ctx)->state <= MFCINST_RES_CHANGE_END)) diff --git a/drivers/media/platform/exynos/mfc/mfc_data_struct.h b/drivers/media/platform/exynos/mfc/mfc_data_struct.h index 0f6e0dc793d1..a069cfed8dcb 100644 --- a/drivers/media/platform/exynos/mfc/mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/mfc_data_struct.h @@ -59,7 +59,9 @@ #define MAX_NUM_IMAGES_IN_VB 8 #define MAX_NUM_BUFCON_BUFS 32 + #define MAX_NUM_CLUSTER 3 +#define MAX_NUM_MFC_BPS 2 /* * MFC region id for smc @@ -483,6 +485,7 @@ struct mfc_platdata { struct mfc_qos *qos_table; struct mfc_qos_boost *qos_boost_table; #endif + unsigned int max_Kbps[MAX_NUM_MFC_BPS]; /* NAL-Q size */ unsigned int nal_q_entry_size; unsigned int nal_q_dump_size; @@ -851,6 +854,8 @@ struct mfc_dev { int qos_has_enc_ctx; struct mutex qos_mutex; #endif + int bps_ratio; + int id; atomic_t clk_ref; @@ -1347,6 +1352,11 @@ struct mfc_timestamp { int interval; }; +struct mfc_bitrate { + struct list_head list; + int bytesused; +}; + struct mfc_dec { int total_dpb_count; @@ -1554,6 +1564,12 @@ struct mfc_ctx { int ts_count; int ts_is_full; + struct mfc_bitrate bitrate_array[MFC_TIME_INDEX]; + struct list_head bitrate_list; + int bitrate_index; + int bitrate_is_full; + int Kbps; + int buf_process_type; unsigned long raw_protect_flag; diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c index 3e7a596099b6..87a5e7c1dc56 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c @@ -726,7 +726,7 @@ static int mfc_dec_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) return -EIO; } - mfc_qos_update_framerate(ctx); + mfc_qos_update_framerate(ctx, buf->m.planes[0].bytesused); if (!buf->m.planes[0].bytesused) { buf->m.planes[0].bytesused = buf->m.planes[0].length; diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_param.c b/drivers/media/platform/exynos/mfc/mfc_enc_param.c index b409811d2c2b..95374998cc91 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_param.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_param.c @@ -226,6 +226,7 @@ static void __mfc_set_enc_params(struct mfc_ctx *ctx) MFC_RAW_WRITEL(reg, MFC_REG_E_RC_CONFIG); /* bit rate */ + ctx->Kbps = p->rc_bitrate / 1024; MFC_RAW_WRITEL(p->rc_bitrate, MFC_REG_E_RC_BIT_RATE); reg = MFC_RAW_READL(MFC_REG_E_RC_MODE); diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c index 4849e9b55a7b..fd6e811eb8f8 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c @@ -442,7 +442,7 @@ static void mfc_enc_buf_queue(struct vb2_buffer *vb) ctx->framerate, buf->vb.vb2_buf.timestamp); mfc_qos_update_last_framerate(ctx, buf->vb.vb2_buf.timestamp); - mfc_qos_update_framerate(ctx); + mfc_qos_update_framerate(ctx, 0); } else { mfc_err_ctx("unsupported buffer type (%d)\n", vq->type); } diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.c b/drivers/media/platform/exynos/mfc/mfc_isr.c index 95a90f798663..0d9682f6bb1a 100644 --- a/drivers/media/platform/exynos/mfc/mfc_isr.c +++ b/drivers/media/platform/exynos/mfc/mfc_isr.c @@ -676,6 +676,7 @@ static void __mfc_handle_frame(struct mfc_ctx *ctx, if (dst_frame_status == MFC_REG_DEC_STATUS_DECODING_EMPTY) { if (ctx->state == MFCINST_RES_CHANGE_FLUSH) { struct mfc_timestamp *temp_ts = NULL; + struct mfc_bitrate *temp_bitrate = NULL; mfc_debug(2, "[DRC] Last frame received after resolution change\n"); __mfc_handle_frame_all_extracted(ctx); @@ -697,6 +698,15 @@ static void __mfc_handle_frame(struct mfc_ctx *ctx, mfc_qos_reset_last_framerate(ctx); mfc_qos_set_framerate(ctx, DEC_DEFAULT_FPS); + /* empty the bitrate queue */ + while (!list_empty(&ctx->bitrate_list)) { + temp_bitrate = list_entry((&ctx->bitrate_list)->next, + struct mfc_bitrate, list); + list_del(&temp_bitrate->list); + } + ctx->bitrate_index = 0; + ctx->bitrate_is_full = 0; + goto leave_handle_frame; } else { __mfc_handle_frame_all_extracted(ctx); diff --git a/drivers/media/platform/exynos/mfc/mfc_otf.c b/drivers/media/platform/exynos/mfc/mfc_otf.c index e2c2915dbc95..584fb580d164 100644 --- a/drivers/media/platform/exynos/mfc/mfc_otf.c +++ b/drivers/media/platform/exynos/mfc/mfc_otf.c @@ -476,7 +476,7 @@ int mfc_otf_run_enc_frame(struct mfc_ctx *ctx) /* Change timestamp usec -> nsec */ mfc_qos_update_last_framerate(ctx, handle->otf_time_stamp * 1000); - mfc_qos_update_framerate(ctx); + mfc_qos_update_framerate(ctx, 0); /* Set stream buffer size to handle buffer full */ mfc_clean_ctx_int_flags(ctx); diff --git a/drivers/media/platform/exynos/mfc/mfc_qos.c b/drivers/media/platform/exynos/mfc/mfc_qos.c index 8b5460a53185..a208fd338e69 100644 --- a/drivers/media/platform/exynos/mfc/mfc_qos.c +++ b/drivers/media/platform/exynos/mfc/mfc_qos.c @@ -847,8 +847,48 @@ static unsigned long __mfc_qos_get_fps_by_timestamp(struct mfc_ctx *ctx, struct return max_framerate; } -void mfc_qos_update_framerate(struct mfc_ctx *ctx) +static void __mfc_qos_get_bps(struct mfc_ctx *ctx, u32 bytesused) { + struct mfc_dev *dev = ctx->dev; + struct list_head *head = &ctx->bitrate_list; + struct mfc_bitrate *temp_bitrate; + struct mfc_bitrate *new_bitrate = &ctx->bitrate_array[ctx->bitrate_index]; + unsigned long sum_size = 0, avg_Kbits; + int count = 0; + + if (ctx->bitrate_is_full) { + temp_bitrate = list_entry(head->next, struct mfc_bitrate, list); + list_del(&temp_bitrate->list); + } + + new_bitrate->bytesused = bytesused; + list_add_tail(&new_bitrate->list, head); + + list_for_each_entry(temp_bitrate, head, list) { + mfc_debug(4, "[QoS][%d] strm_size %d\n", count, temp_bitrate->bytesused); + sum_size += temp_bitrate->bytesused; + count++; + } + + avg_Kbits = ((sum_size * BITS_PER_BYTE) / count) / 1024; + ctx->Kbps = (int)(avg_Kbits * (ctx->last_framerate / 1000)); + /* Standardization to high bitrate spec */ + if (!CODEC_HIGH_PERF(ctx)) + ctx->Kbps = dev->bps_ratio * ctx->Kbps; + mfc_debug(3, "[QoS] %d Kbps, average %lld Kbits per frame\n", ctx->Kbps, avg_Kbits); + + ctx->bitrate_index++; + if (ctx->bitrate_index == MFC_TIME_INDEX) { + ctx->bitrate_is_full = 1; + ctx->bitrate_index %= MFC_TIME_INDEX; + } +} + +void mfc_qos_update_framerate(struct mfc_ctx *ctx, u32 bytesused) +{ + if (ctx->type == MFCINST_DECODER) + __mfc_qos_get_bps(ctx, bytesused); + if (ctx->last_framerate != 0 && ctx->last_framerate != ctx->framerate) { mfc_debug(2, "[QoS] fps changed: %ld -> %ld, qos ratio: %d\n", ctx->framerate, ctx->last_framerate, ctx->qos_ratio); diff --git a/drivers/media/platform/exynos/mfc/mfc_qos.h b/drivers/media/platform/exynos/mfc/mfc_qos.h index a56e57cb8bfb..73755d8a6a20 100644 --- a/drivers/media/platform/exynos/mfc/mfc_qos.h +++ b/drivers/media/platform/exynos/mfc/mfc_qos.h @@ -38,7 +38,7 @@ void mfc_qos_off(struct mfc_ctx *ctx); #define mfc_qos_off(ctx) do {} while (0) #endif -void mfc_qos_update_framerate(struct mfc_ctx *ctx); +void mfc_qos_update_framerate(struct mfc_ctx *ctx, u32 bytesused); void mfc_qos_update_last_framerate(struct mfc_ctx *ctx, u64 timestamp); static inline void mfc_qos_reset_framerate(struct mfc_ctx *ctx)