#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;
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);
#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))
#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
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;
int qos_has_enc_ctx;
struct mutex qos_mutex;
#endif
+ int bps_ratio;
+
int id;
atomic_t clk_ref;
int interval;
};
+struct mfc_bitrate {
+ struct list_head list;
+ int bytesused;
+};
+
struct mfc_dec {
int total_dpb_count;
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;
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;
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);
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);
}
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);
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);
/* 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);
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);
#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)