From 9cd3fd6a0cd7d89a1a86aa2312d77929f8435c66 Mon Sep 17 00:00:00 2001 From: Jeonghee Kim Date: Wed, 23 May 2018 13:04:38 +0900 Subject: [PATCH] [COMMON] media: mfc: parse dts for checking features Change-Id: I018b700dc0ca70b2c07b3e76537a9213bbe73644 Signed-off-by: Jeonghee Kim --- drivers/media/platform/exynos/mfc/s5p_mfc.c | 6 ++++ .../media/platform/exynos/mfc/s5p_mfc_cal.h | 11 +++--- .../platform/exynos/mfc/s5p_mfc_common.h | 35 ------------------ .../platform/exynos/mfc/s5p_mfc_data_struct.h | 6 ++++ .../media/platform/exynos/mfc/s5p_mfc_dec.c | 2 +- .../platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c | 2 +- .../media/platform/exynos/mfc/s5p_mfc_enc.c | 36 +++++++------------ .../platform/exynos/mfc/s5p_mfc_enc_ops.c | 3 +- .../platform/exynos/mfc/s5p_mfc_enc_param.c | 8 ++--- .../media/platform/exynos/mfc/s5p_mfc_inst.c | 8 ++--- .../media/platform/exynos/mfc/s5p_mfc_irq.c | 8 ++--- .../media/platform/exynos/mfc/s5p_mfc_nal_q.c | 6 ++-- .../media/platform/exynos/mfc/s5p_mfc_reg.c | 2 +- 13 files changed, 46 insertions(+), 87 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc.c b/drivers/media/platform/exynos/mfc/s5p_mfc.c index fbf17f60704a..3d0c87ff47ab 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc.c @@ -945,6 +945,12 @@ static void mfc_parse_dt(struct device_node *np, struct s5p_mfc_dev *mfc) of_property_read_u32(np, "ip_ver", &pdata->ip_ver); of_property_read_u32(np, "debug_mode", &pdata->debug_mode); of_property_read_u32(np, "nal_q", &pdata->nal_q); + of_property_read_u32(np, "skype", &pdata->skype); + of_property_read_u32(np, "black_bar", &pdata->black_bar); + of_property_read_u32(np, "color_aspect_dec", &pdata->color_aspect_dec); + of_property_read_u32(np, "static_info_dec", &pdata->static_info_dec); + of_property_read_u32(np, "color_aspect_enc", &pdata->color_aspect_enc); + of_property_read_u32(np, "static_info_enc", &pdata->static_info_enc); #ifdef CONFIG_MFC_USE_BUS_DEVFREQ of_property_read_u32(np, "num_qos_steps", &pdata->num_qos_steps); of_property_read_u32(np, "max_qos_steps", &pdata->max_qos_steps); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cal.h b/drivers/media/platform/exynos/mfc/s5p_mfc_cal.h index 6dfefddc34c5..f2a965f436d9 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_cal.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_cal.h @@ -63,8 +63,7 @@ static inline void s5p_mfc_risc_on(struct s5p_mfc_dev *dev) s5p_mfc_clean_dev_int_flags(dev); MFC_WRITEL(0x1, S5P_FIMV_RISC_ON); - if (FW_HAS_HWACG(dev)) - MFC_WRITEL(0x0, S5P_FIMV_MFC_OFF); + MFC_WRITEL(0x0, S5P_FIMV_MFC_OFF); mfc_debug(1, "RISC_ON\n"); MFC_TRACE_DEV(">> RISC ON\n"); } @@ -93,11 +92,9 @@ static inline void s5p_mfc_risc_off(struct s5p_mfc_dev *dev) static inline void s5p_mfc_mfc_off(struct s5p_mfc_dev *dev) { - if (FW_HAS_HWACG(dev)) { - mfc_info_dev("MFC h/w state: %d\n", - MFC_READL(S5P_FIMV_MFC_STATE) & 0x7); - MFC_WRITEL(0x1, S5P_FIMV_MFC_OFF); - } + mfc_info_dev("MFC h/w state: %d\n", + MFC_READL(S5P_FIMV_MFC_STATE) & 0x7); + MFC_WRITEL(0x1, S5P_FIMV_MFC_OFF); } static inline void s5p_mfc_enable_all_clocks(struct s5p_mfc_dev *dev) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h index 750a9144a428..42208d97aa10 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h @@ -180,39 +180,4 @@ #define MFC_VER_MAJOR(dev) ((dev->pdata->ip_ver >> 8) & 0xFF) #define MFC_VER_MINOR(dev) (dev->pdata->ip_ver & 0xFF) -/* - * Version Description - */ -#define IS_MFCV10X(dev) ((dev->pdata->ip_ver == 0xA0) || \ - (dev->pdata->ip_ver == 0xA01)) -#define IS_MFCV11X(dev) (dev->pdata->ip_ver == 0x1100) -#define IS_MFCV12X(dev) (dev->pdata->ip_ver == 0x1200) -#define IS_MFCV13X(dev) (dev->pdata->ip_ver == 0x1300) -#define FROM_MFCV11X(dev) (IS_MFCV11X(dev) || IS_MFCV12X(dev) || \ - IS_MFCV13X(dev)) -#define FROM_MFCV10X(dev) (IS_MFCV10X(dev) || FROM_MFCV11X(dev)) - -/* supported feature macros by F/W version */ -#define FW_HAS_CONCEAL_CONTROL(dev) (FROM_MFCV10X(dev)) -#define FW_HAS_ROI_CONTROL(dev) (FROM_MFCV10X(dev)) -#define FW_HAS_HWACG(dev) (FROM_MFCV10X(dev)) -#define FW_HAS_SPECIAL_PARSING(dev) (FROM_MFCV10X(dev)) -#define FW_SUPPORT_SKYPE(dev) (FROM_MFCV10X(dev) && \ - (dev->fw.date >= 0x150901)) -#define FW_HAS_VIDEO_SIGNAL_TYPE(dev) (FROM_MFCV10X(dev) && \ - (dev->fw.date >= 0x151223)) -#define FW_HAS_SEI_INFO_FOR_HDR(dev) (FROM_MFCV10X(dev) && \ - (dev->fw.date >= 0x160415)) -#define FW_HAS_BLACK_BAR_DETECT(dev) (FROM_MFCV11X(dev) && \ - (dev->fw.date >= 0x161017)) -#define FW_HAS_VP9_HDR(dev) (IS_MFCV12X(dev) && \ - (dev->fw.date >= 0x171023)) -#define FW_HAS_RATIO_INTRA_CTRL(dev) (FROM_MFCV11X(dev) && \ - (dev->fw.date >= 0x171113)) -#define FW_HAS_ENC_COLOR_ASPECT(dev) (FROM_MFCV11X(dev) && \ - (dev->fw.date >= 0x171023)) -#define FW_HAS_HP_BITRATE_CONTROL(dev) (FROM_MFCV11X(dev) && \ - (dev->fw.date >= 0x180314)) -#define FW_HAS_ENC_STATIC_INFO(dev) (IS_MFCV13X(dev) && \ - (dev->fw.date >= 0x180314)) #endif /* __S5P_MFC_COMMON_H */ diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h index 6ebc3089a319..e04fb56904f8 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h @@ -373,6 +373,12 @@ struct s5p_mfc_platdata { int ip_ver; int debug_mode; int nal_q; + int skype; + int black_bar; + int color_aspect_dec; + int static_info_dec; + int color_aspect_enc; + int static_info_enc; #ifdef CONFIG_MFC_USE_BUS_DEVFREQ int num_qos_steps; int max_qos_steps; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c index 3a11ce8cb7a2..93ee73436264 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c @@ -880,7 +880,7 @@ static int mfc_dec_ext_info(struct s5p_mfc_ctx *ctx) int val = 0; val |= DEC_SET_DYNAMIC_DPB; - if (FW_SUPPORT_SKYPE(dev)) + if (dev->pdata->skype) val |= DEC_SET_SKYPE_FLAG; return val; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c index 500163bb3653..25a5e83c2d06 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c @@ -378,7 +378,7 @@ static void mfc_dec_src_stop_streaming(struct s5p_mfc_ctx *ctx) while (1) { csd = s5p_mfc_peek_buf_csd(&ctx->buf_queue_lock, &ctx->src_buf_queue); - if (FW_HAS_SPECIAL_PARSING(dev) && (csd == 1)) { + if (csd == 1) { s5p_mfc_clean_ctx_int_flags(ctx); if (need_to_special_parsing(ctx)) { s5p_mfc_change_state(ctx, MFCINST_SPECIAL_PARSING); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c index c59e85e33490..66805a334598 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c @@ -79,12 +79,6 @@ static int mfc_enc_check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control * return -ERANGE; } - if (!FW_HAS_ROI_CONTROL(dev) && ctrl->id == \ - V4L2_CID_MPEG_VIDEO_ROI_CONTROL) { - mfc_err_ctx("Not support feature(0x%x) for F/W\n", ctrl->id); - return -ERANGE; - } - return 0; } @@ -366,14 +360,13 @@ static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv, ctx->capture_state = QUEUE_FREE; - if (FW_HAS_ROI_CONTROL(dev)) { - ret = s5p_mfc_alloc_enc_roi_buffer(ctx); - if (ret) { - mfc_err_ctx("Failed to allocate ROI buffers.\n"); - s5p_mfc_release_instance_context(ctx); - return -ENOMEM; - } + ret = s5p_mfc_alloc_enc_roi_buffer(ctx); + if (ret) { + mfc_err_ctx("Failed to allocate ROI buffers.\n"); + s5p_mfc_release_instance_context(ctx); + return -ENOMEM; } + MFC_TRACE_CTX_HWLOCK("**ENC s_fmt\n"); ret = s5p_mfc_get_hwlock_ctx(ctx); @@ -812,26 +805,21 @@ static int mfc_enc_ext_info(struct s5p_mfc_ctx *ctx) val |= ENC_SET_SPARE_SIZE; val |= ENC_SET_TEMP_SVC_CH; - if (FW_SUPPORT_SKYPE(dev)) + if (dev->pdata->skype) val |= ENC_SET_SKYPE_FLAG; - if (FW_HAS_ROI_CONTROL(dev)) - val |= ENC_SET_ROI_CONTROL; - + val |= ENC_SET_ROI_CONTROL; val |= ENC_SET_QP_BOUND_PB; val |= ENC_SET_FIXED_SLICE; val |= ENC_SET_PVC_MODE; + val |= ENC_SET_RATIO_OF_INTRA; - if (FW_HAS_RATIO_INTRA_CTRL(dev)) - val |= ENC_SET_RATIO_OF_INTRA; - - if (FW_HAS_ENC_COLOR_ASPECT(dev)) + if (dev->pdata->color_aspect_enc) val |= ENC_SET_COLOR_ASPECT; - if (FW_HAS_HP_BITRATE_CONTROL(dev)) - val |= ENC_SET_HP_BITRATE_CONTROL; + val |= ENC_SET_HP_BITRATE_CONTROL; - if (FW_HAS_ENC_STATIC_INFO(dev)) + if (dev->pdata->static_info_enc) val |= ENC_SET_STATIC_INFO; return val; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c index ab548a400424..b958a590fe51 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c @@ -1164,8 +1164,7 @@ static void mfc_enc_set_buf_ctrls_exception(struct s5p_mfc_ctx *ctx, p->config_qp = buf_ctrl->val; /* set the ROI buffer DVA */ - if ((buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) && - FW_HAS_ROI_CONTROL(dev)) { + if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) { MFC_WRITEL(enc->roi_buf[buf_ctrl->old_val2].daddr, S5P_FIMV_E_ROI_BUFFER_ADDR); mfc_debug(3, "ROI: buffer[%d] addr %#llx, QP val: %#x\n", diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c index b913f3e6cda6..a8870dc51702 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c @@ -641,7 +641,7 @@ void s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) MFC_WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO); } - if (FW_HAS_ENC_COLOR_ASPECT(dev) && p->check_color_range) { + if (dev->pdata->color_aspect_enc && p->check_color_range) { reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE); /* VIDEO_SIGNAL_TYPE_FLAG */ reg |= 0x1 << 31; @@ -1118,7 +1118,7 @@ void s5p_mfc_set_enc_params_vp9(struct s5p_mfc_ctx *ctx) reg |= p_vp9->rc_min_qp_p & 0xFF; MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB); - if (FW_HAS_ENC_COLOR_ASPECT(dev) && p->check_color_range) { + if (dev->pdata->color_aspect_enc && p->check_color_range) { reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE); /* VIDEO_SIGNAL_TYPE_FLAG */ reg |= 0x1 << 31; @@ -1363,7 +1363,7 @@ void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx) MFC_WRITEL(reg, S5P_FIMV_E_RC_ROI_CTRL); mfc_debug(3, "ROI: HEVC ROI enable\n"); - if (FW_HAS_ENC_COLOR_ASPECT(dev) && p->check_color_range) { + if (dev->pdata->color_aspect_enc && p->check_color_range) { reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE); /* VIDEO_SIGNAL_TYPE_FLAG */ reg |= 0x1 << 31; @@ -1394,7 +1394,7 @@ void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx) MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE); } - if (FW_HAS_ENC_STATIC_INFO(dev) && p->static_info_enable && ctx->is_10bit) { + if (dev->pdata->static_info_enc && p->static_info_enable && ctx->is_10bit) { reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS_2); /* HDR_STATIC_INFO_ENABLE */ reg |= p->static_info_enable; diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c b/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c index 0b69908416a5..2542044835b4 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c @@ -148,8 +148,7 @@ int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx) reg |= (0x1 << S5P_FIMV_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT); /* conceal control to specific color */ - if (FW_HAS_CONCEAL_CONTROL(dev)) - reg |= (0x4 << S5P_FIMV_D_DEC_OPT_CONCEAL_CONTROL_SHIFT); + reg |= (0x4 << S5P_FIMV_D_DEC_OPT_CONCEAL_CONTROL_SHIFT); /* Disable parallel processing if nal_q_parallel_disable was set */ if (nal_q_parallel_disable) @@ -163,8 +162,7 @@ int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx) MFC_WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS); - if (FW_HAS_CONCEAL_CONTROL(dev)) - MFC_WRITEL(MFC_CONCEAL_COLOR, S5P_FIMV_D_FORCE_PIXEL_VAL); + MFC_WRITEL(MFC_CONCEAL_COLOR, S5P_FIMV_D_FORCE_PIXEL_VAL); if (IS_FIMV1_DEC(ctx)) { mfc_debug(2, "Setting FIMV1 resolution to %dx%d\n", @@ -179,7 +177,7 @@ int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx) /* Enable realloc interface if SEI is enabled */ if (dec->sei_parse) reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT); - if (FW_HAS_SEI_INFO_FOR_HDR(dev)) { + if (dev->pdata->static_info_dec) { reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT); reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT); } diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c index afd50772dc48..f900a9280e19 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c @@ -224,17 +224,17 @@ static void mfc_handle_frame_output_del(struct s5p_mfc_ctx *ctx, unsigned int is_content_light = 0, is_display_colour = 0; unsigned int i, index; - if (FW_HAS_VIDEO_SIGNAL_TYPE(dev)) { + if (dev->pdata->color_aspect_dec) { is_video_signal_type = s5p_mfc_get_video_signal_type(); is_colour_description = s5p_mfc_get_colour_description(); } - if (FW_HAS_SEI_INFO_FOR_HDR(dev)) { + if (dev->pdata->static_info_dec) { is_content_light = s5p_mfc_get_sei_avail_content_light(); is_display_colour = s5p_mfc_get_sei_avail_mastering_display(); } - if (FW_HAS_BLACK_BAR_DETECT(dev) && dec->detect_black_bar) + if (dev->pdata->black_bar && dec->detect_black_bar) mfc_handle_black_bar_info(dev, ctx); else dec->black_bar_updated = 0; @@ -284,7 +284,7 @@ static void mfc_handle_frame_output_del(struct s5p_mfc_ctx *ctx, } } - if (IS_VP9_DEC(ctx) && FW_HAS_VP9_HDR(dev)) { + if (IS_VP9_DEC(ctx) && dev->pdata->color_aspect_dec) { if (dec->color_space != S5P_FIMV_D_COLOR_UNKNOWN) { ref_mb->vb.reserved2 |= (1 << 3); mfc_debug(2, "color space parsed\n"); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c index 052fb4615317..a88e2ae227e8 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c @@ -1231,7 +1231,7 @@ static void mfc_nal_q_handle_frame_output_del(struct s5p_mfc_ctx *ctx, unsigned int disp_err; int i, index; - if (FW_HAS_VIDEO_SIGNAL_TYPE(dev)) { + if (dev->pdata->color_aspect_dec) { is_video_signal_type = ((pOutStr->VideoSignalType >> S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT) & S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK); @@ -1240,7 +1240,7 @@ static void mfc_nal_q_handle_frame_output_del(struct s5p_mfc_ctx *ctx, & S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK); } - if (FW_HAS_SEI_INFO_FOR_HDR(dev)) { + if (dev->pdata->static_info_dec) { is_content_light = ((pOutStr->SeiAvail >> S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT) & S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK); is_display_colour = ((pOutStr->SeiAvail >> S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT) @@ -1288,7 +1288,7 @@ static void mfc_nal_q_handle_frame_output_del(struct s5p_mfc_ctx *ctx, } } - if (IS_VP9_DEC(ctx) && FW_HAS_VP9_HDR(dev)) { + if (IS_VP9_DEC(ctx) && dev->pdata->color_aspect_dec) { if (dec->color_space != S5P_FIMV_D_COLOR_UNKNOWN) { ref_mb->vb.reserved2 |= (1 << 3); mfc_debug(2, "NAL Q: color space parsed\n"); diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c index 1062a8dc29df..8b21e3271f4b 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c @@ -459,7 +459,7 @@ int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb) mfc_debug(2, "Dst addr [%d] = 0x%08llx\n", dst_index, dst_mb->addr[0][0]); /* for debugging about black bar detection */ - if (FW_HAS_BLACK_BAR_DETECT(dev) && dec->detect_black_bar) { + if (dev->pdata->black_bar && dec->detect_black_bar) { for (i = 0; i < raw->num_planes; i++) { dec->frame_vaddr[i][dec->frame_cnt] = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, i); dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[0][i]; -- 2.20.1