From 4436ad171d411a0a41ab60fd98f963786df659ec Mon Sep 17 00:00:00 2001 From: Ayoung Sim Date: Tue, 24 Jul 2018 16:25:56 +0900 Subject: [PATCH] [COMMON] media: mfc: parse the NAL_Q size Because NAL_Q structure size is differenct by F/W, we parse this dependency from device tree. Change-Id: I23ddcd3fcdae6b80ffe80ea372cf81965b47de85 Signed-off-by: Ayoung Sim --- drivers/media/platform/exynos/mfc/mfc.c | 4 + .../platform/exynos/mfc/mfc_data_struct.h | 39 ++-------- drivers/media/platform/exynos/mfc/mfc_nal_q.c | 73 ++++++++++++------- .../media/platform/exynos/mfc/mfc_watchdog.c | 9 ++- 4 files changed, 66 insertions(+), 59 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/mfc.c b/drivers/media/platform/exynos/mfc/mfc.c index 88b76973706e..b50bec31a21b 100644 --- a/drivers/media/platform/exynos/mfc/mfc.c +++ b/drivers/media/platform/exynos/mfc/mfc.c @@ -980,6 +980,10 @@ static void __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc) of_property_read_u32(np, "axid_mask", &pdata->axid_mask); of_property_read_u32(np, "mfc_fault_num", &pdata->mfc_fault_num); + /* NAL-Q size */ + of_property_read_u32(np, "nal_q_entry_size", &pdata->nal_q_entry_size); + of_property_read_u32(np, "nal_q_dump_size", &pdata->nal_q_dump_size); + /* Features */ of_property_read_u32_array(np, "nal_q", &pdata->nal_q.support, 2); of_property_read_u32_array(np, "skype", &pdata->skype.support, 2); diff --git a/drivers/media/platform/exynos/mfc/mfc_data_struct.h b/drivers/media/platform/exynos/mfc/mfc_data_struct.h index 3618747d04da..a685de59a689 100644 --- a/drivers/media/platform/exynos/mfc/mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/mfc_data_struct.h @@ -446,6 +446,9 @@ struct mfc_platdata { struct mfc_qos *qos_table; struct mfc_qos_boost *qos_boost_table; #endif + /* NAL-Q size */ + unsigned int nal_q_entry_size; + unsigned int nal_q_dump_size; /* Features */ struct mfc_feature nal_q; struct mfc_feature skype; @@ -474,18 +477,10 @@ struct mfc_platdata { }; /************************ NAL_Q data structure ************************/ -#define NAL_Q_IN_ENTRY_SIZE 512 -#define NAL_Q_OUT_ENTRY_SIZE 512 +#define NAL_Q_ENTRY_SIZE_FOR_HDR10 512 -#define NAL_Q_IN_DEC_STR_SIZE 112 -#define NAL_Q_IN_ENC_STR_SIZE 324 -#define NAL_Q_OUT_DEC_STR_SIZE 376 -#define NAL_Q_OUT_ENC_STR_SIZE 64 -#define NAL_Q_DUMP_MAX_STR_SIZE 376 - -/* 512*128(max instance 32 * slot 4) = 64 kbytes */ -#define NAL_Q_IN_QUEUE_SIZE 128 -#define NAL_Q_OUT_QUEUE_SIZE 128 +/* slot 4 * max instance 32 = 128 */ +#define NAL_Q_QUEUE_SIZE 128 typedef struct __DecoderInputStr { int StartCode; /* = 0xAAAAAAAA; Decoder input structure marker */ @@ -508,7 +503,6 @@ typedef struct __DecoderInputStr { int Frame2BitStrideSize[2]; unsigned int ScratchBufAddr; int ScratchBufSize; - char reserved[NAL_Q_IN_ENTRY_SIZE - NAL_Q_IN_DEC_STR_SIZE]; } DecoderInputStr; /* 28*4 = 112 bytes */ typedef struct __EncoderInputStr { @@ -555,7 +549,6 @@ typedef struct __EncoderInputStr { int WeightUpper; int RcMode; int St2094_40sei[30]; - char reserved[NAL_Q_IN_ENTRY_SIZE - NAL_Q_IN_ENC_STR_SIZE]; } EncoderInputStr; /* 81*4 = 324 bytes */ typedef struct __DecoderOutputStr { @@ -620,7 +613,6 @@ typedef struct __DecoderOutputStr { int FirstPlaneDpbSize; int SecondPlaneDpbSize; int St2094_40sei[30]; - char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_DEC_STR_SIZE]; } DecoderOutputStr; /* 94*4 = 376 bytes */ typedef struct __EncoderOutputStr { @@ -638,7 +630,6 @@ typedef struct __EncoderOutputStr { unsigned int ReconLumaDpbAddr; unsigned int ReconChromaDpbAddr; int EncCnt; - char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_ENC_STR_SIZE]; } EncoderOutputStr; /* 16*4 = 64 bytes */ /** @@ -650,33 +641,19 @@ typedef enum _nal_queue_state { NAL_Q_STATE_STOPPED, /* when mfc_nal_q_stop() is called */ } nal_queue_state; -typedef struct _nal_in_queue { - union { - DecoderInputStr dec; - EncoderInputStr enc; - } entry[NAL_Q_IN_QUEUE_SIZE]; -} nal_in_queue; - -typedef struct _nal_out_queue { - union { - DecoderOutputStr dec; - EncoderOutputStr enc; - } entry[NAL_Q_OUT_QUEUE_SIZE]; -} nal_out_queue; - struct _nal_queue_handle; typedef struct _nal_queue_in_handle { struct _nal_queue_handle *nal_q_handle; struct mfc_special_buf in_buf; unsigned int in_exe_count; - nal_in_queue *nal_q_in_addr; + void *nal_q_in_addr; } nal_queue_in_handle; typedef struct _nal_queue_out_handle { struct _nal_queue_handle *nal_q_handle; struct mfc_special_buf out_buf; unsigned int out_exe_count; - nal_out_queue *nal_q_out_addr; + void *nal_q_out_addr; int nal_q_ctx; } nal_queue_out_handle; diff --git a/drivers/media/platform/exynos/mfc/mfc_nal_q.c b/drivers/media/platform/exynos/mfc/mfc_nal_q.c index c88be065e216..07ce22d128e9 100644 --- a/drivers/media/platform/exynos/mfc/mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/mfc_nal_q.c @@ -211,13 +211,19 @@ static nal_queue_in_handle* __mfc_nal_q_create_in_q(struct mfc_dev *dev, nal_q_in_handle->nal_q_handle = nal_q_handle; nal_q_in_handle->in_buf.buftype = MFCBUF_NORMAL; - nal_q_in_handle->in_buf.size = NAL_Q_IN_ENTRY_SIZE * (NAL_Q_IN_QUEUE_SIZE + 2); + /* + * Total nal_q buf size = entry size * num slot * max instance + * ex) entry size is 512 byte + * 512 byte * 4 slot * 32 instance = 64KB + * Plus 1 is needed for margin, because F/W exceeds sometimes. + */ + nal_q_in_handle->in_buf.size = dev->pdata->nal_q_entry_size * (NAL_Q_QUEUE_SIZE + 1); if (mfc_mem_ion_alloc(dev, &nal_q_in_handle->in_buf)) { mfc_err_dev("[NALQ] failed to get memory\n"); kfree(nal_q_in_handle); return NULL; } - nal_q_in_handle->nal_q_in_addr = (nal_in_queue *)nal_q_in_handle->in_buf.vaddr; + nal_q_in_handle->nal_q_in_addr = nal_q_in_handle->in_buf.vaddr; mfc_debug_leave(); @@ -239,13 +245,19 @@ static nal_queue_out_handle* __mfc_nal_q_create_out_q(struct mfc_dev *dev, nal_q_out_handle->nal_q_handle = nal_q_handle; nal_q_out_handle->out_buf.buftype = MFCBUF_NORMAL; - nal_q_out_handle->out_buf.size = NAL_Q_OUT_ENTRY_SIZE * (NAL_Q_OUT_QUEUE_SIZE + 2); + /* + * Total nal_q buf size = entry size * num slot * max instance + * ex) entry size is 512 byte + * 512 byte * 4 slot * 32 instance = 64KB + * Plus 1 is needed for margin, because F/W exceeds sometimes. + */ + nal_q_out_handle->out_buf.size = dev->pdata->nal_q_entry_size * (NAL_Q_QUEUE_SIZE + 1); if (mfc_mem_ion_alloc(dev, &nal_q_out_handle->out_buf)) { mfc_err_dev("[NALQ] failed to get memory\n"); kfree(nal_q_out_handle); return NULL; } - nal_q_out_handle->nal_q_out_addr = (nal_out_queue *)nal_q_out_handle->out_buf.vaddr; + nal_q_out_handle->nal_q_out_addr = nal_q_out_handle->out_buf.vaddr; mfc_debug_leave(); @@ -412,7 +424,7 @@ void mfc_nal_q_start(struct mfc_dev *dev, nal_queue_handle *nal_q_handle) addr = nal_q_handle->nal_q_in_handle->in_buf.daddr; - mfc_update_nal_queue_input(dev, addr, NAL_Q_IN_ENTRY_SIZE * NAL_Q_IN_QUEUE_SIZE); + mfc_update_nal_queue_input(dev, addr, dev->pdata->nal_q_entry_size * NAL_Q_QUEUE_SIZE); mfc_debug(2, "[NALQ] MFC_REG_NAL_QUEUE_INPUT_ADDR=0x%x\n", mfc_get_nal_q_input_addr()); @@ -421,7 +433,7 @@ void mfc_nal_q_start(struct mfc_dev *dev, nal_queue_handle *nal_q_handle) addr = nal_q_handle->nal_q_out_handle->out_buf.daddr; - mfc_update_nal_queue_output(dev, addr, NAL_Q_OUT_ENTRY_SIZE * NAL_Q_OUT_QUEUE_SIZE); + mfc_update_nal_queue_output(dev, addr, dev->pdata->nal_q_entry_size * NAL_Q_QUEUE_SIZE); mfc_debug(2, "[NALQ] MFC_REG_NAL_QUEUE_OUTPUT_ADDR=0x%x\n", mfc_get_nal_q_output_addr()); @@ -559,6 +571,11 @@ static void __mfc_nal_q_get_hdr_plus_info(struct mfc_ctx *ctx, DecoderOutputStr int num_win, num_distribution; int i, j; + if (dev->pdata->nal_q_entry_size < NAL_Q_ENTRY_SIZE_FOR_HDR10) { + mfc_err_dev("[NALQ][HDR+] insufficient NAL-Q entry size\n"); + return; + } + sei_meta->valid = 1; /* iru_t_t35 */ @@ -651,6 +668,11 @@ static void __mfc_nal_q_set_hdr_plus_info(struct mfc_ctx *ctx, EncoderInputStr * int num_win, num_distribution; int i, j; + if (dev->pdata->nal_q_entry_size < NAL_Q_ENTRY_SIZE_FOR_HDR10) { + mfc_err_dev("[NALQ][HDR+] insufficient NAL-Q entry size\n"); + return; + } + pInStr->HevcNalControl &= ~(sei_meta->valid << 6); pInStr->HevcNalControl |= ((sei_meta->valid & 0x1) << 6); @@ -1837,7 +1859,7 @@ int mfc_nal_q_enqueue_in_buf(struct mfc_dev *dev, struct mfc_ctx *ctx, unsigned int input_count = 0; unsigned int input_exe_count = 0; int input_diff = 0; - unsigned int index = 0; + unsigned int index = 0, offset = 0; EncoderInputStr *pStr = NULL; int ret = 0; @@ -1863,26 +1885,27 @@ int mfc_nal_q_enqueue_in_buf(struct mfc_dev *dev, struct mfc_ctx *ctx, /* * meaning of the variable input_diff - * 0: number of available slots = NAL_Q_IN_QUEUE_SIZE - * 1: number of available slots = NAL_Q_IN_QUEUE_SIZE - 1 + * 0: number of available slots = NAL_Q_QUEUE_SIZE + * 1: number of available slots = NAL_Q_QUEUE_SIZE - 1 * ... - * NAL_Q_IN_QUEUE_SIZE-1: number of available slots = 1 - * NAL_Q_IN_QUEUE_SIZE: number of available slots = 0 + * NAL_Q_QUEUE_SIZE-1: number of available slots = 1 + * NAL_Q_QUEUE_SIZE: number of available slots = 0 */ mfc_debug(2, "[NALQ] input_diff = %d(in: %d, exe: %d)\n", input_diff, input_count, input_exe_count); - if ((input_diff < 0) || (input_diff >= NAL_Q_IN_QUEUE_SIZE)) { + if ((input_diff < 0) || (input_diff >= NAL_Q_QUEUE_SIZE)) { mfc_err_dev("[NALQ] No available input slot(%d)\n", input_diff); spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags); return -EINVAL; } - index = input_count % NAL_Q_IN_QUEUE_SIZE; - pStr = &(nal_q_in_handle->nal_q_in_addr->entry[index].enc); + index = input_count % NAL_Q_QUEUE_SIZE; + offset = dev->pdata->nal_q_entry_size * index; + pStr = (EncoderInputStr *)(nal_q_in_handle->nal_q_in_addr + offset); - memset(pStr, 0, NAL_Q_IN_ENTRY_SIZE); + memset(pStr, 0, dev->pdata->nal_q_entry_size); if (ctx->type == MFCINST_ENCODER) ret = __mfc_nal_q_run_in_buf_enc(ctx, pStr); @@ -1900,7 +1923,7 @@ int mfc_nal_q_enqueue_in_buf(struct mfc_dev *dev, struct mfc_ctx *ctx, ctx->type == MFCINST_ENCODER ? "ENC" : "DEC", dev->curr_ctx, input_diff, input_count, input_exe_count); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, - (int *)pStr, NAL_Q_DUMP_MAX_STR_SIZE, false); + (int *)pStr, dev->pdata->nal_q_dump_size, false); printk("...\n"); } input_count++; @@ -1931,12 +1954,11 @@ EncoderOutputStr *mfc_nal_q_dequeue_out_buf(struct mfc_dev *dev, unsigned long flags; unsigned int output_count = 0; unsigned int output_exe_count = 0; + int input_diff = 0; int output_diff = 0; - unsigned int index = 0; + unsigned int index = 0, offset = 0; EncoderOutputStr *pStr = NULL; - int input_diff = 0; - mfc_debug_enter(); if (!nal_q_out_handle || !nal_q_out_handle->nal_q_out_addr) { @@ -1955,20 +1977,21 @@ EncoderOutputStr *mfc_nal_q_dequeue_out_buf(struct mfc_dev *dev, * 0: number of output slots = 0 * 1: number of output slots = 1 * ... - * NAL_Q_OUT_QUEUE_SIZE-1: number of output slots = NAL_Q_OUT_QUEUE_SIZE - 1 - * NAL_Q_OUT_QUEUE_SIZE: number of output slots = NAL_Q_OUT_QUEUE_SIZE + * NAL_Q_QUEUE_SIZE-1: number of output slots = NAL_Q_QUEUE_SIZE - 1 + * NAL_Q_QUEUE_SIZE: number of output slots = NAL_Q_QUEUE_SIZE */ mfc_debug(2, "[NALQ] output_diff = %d(out: %d, exe: %d)\n", output_diff, output_count, output_exe_count); - if ((output_diff <= 0) || (output_diff > NAL_Q_OUT_QUEUE_SIZE)) { + if ((output_diff <= 0) || (output_diff > NAL_Q_QUEUE_SIZE)) { spin_unlock_irqrestore(&nal_q_out_handle->nal_q_handle->lock, flags); mfc_debug(2, "[NALQ] No available output slot(%d)\n", output_diff); return pStr; } - index = output_exe_count % NAL_Q_OUT_QUEUE_SIZE; - pStr = &(nal_q_out_handle->nal_q_out_addr->entry[index].enc); + index = output_exe_count % NAL_Q_QUEUE_SIZE; + offset = dev->pdata->nal_q_entry_size * index; + pStr = (EncoderOutputStr *)(nal_q_out_handle->nal_q_out_addr + offset); nal_q_out_handle->nal_q_ctx = __mfc_nal_q_find_ctx(dev, pStr); if (nal_q_out_handle->nal_q_ctx < 0) { @@ -1984,7 +2007,7 @@ EncoderOutputStr *mfc_nal_q_dequeue_out_buf(struct mfc_dev *dev, nal_q_out_handle->nal_q_ctx, output_diff, output_count, output_exe_count); print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, - (int *)pStr, NAL_Q_DUMP_MAX_STR_SIZE, false); + (int *)pStr, dev->pdata->nal_q_dump_size, false); printk("...\n"); } nal_q_out_handle->out_exe_count++; diff --git a/drivers/media/platform/exynos/mfc/mfc_watchdog.c b/drivers/media/platform/exynos/mfc/mfc_watchdog.c index 7bd48b433bfa..96bc08af3d92 100644 --- a/drivers/media/platform/exynos/mfc/mfc_watchdog.c +++ b/drivers/media/platform/exynos/mfc/mfc_watchdog.c @@ -145,12 +145,15 @@ static void __mfc_save_logging_sfr(struct mfc_dev *dev) static int __mfc_get_curr_ctx(struct mfc_dev *dev) { nal_queue_handle *nal_q_handle = dev->nal_q_handle; - int index; + unsigned int index, offset; + DecoderInputStr *pStr; if (nal_q_handle) { if (nal_q_handle->nal_q_state == NAL_Q_STATE_STARTED) { - index = nal_q_handle->nal_q_in_handle->in_exe_count % NAL_Q_IN_QUEUE_SIZE; - return nal_q_handle->nal_q_in_handle->nal_q_in_addr->entry[index].dec.InstanceId; + index = nal_q_handle->nal_q_in_handle->in_exe_count % NAL_Q_QUEUE_SIZE; + offset = dev->pdata->nal_q_entry_size * index; + pStr = (DecoderInputStr *)(nal_q_handle->nal_q_in_handle->nal_q_in_addr + offset); + return pStr->InstanceId; } } -- 2.20.1