From b56ae053d3512bc5f39cc6e45d95d6a4b5ade792 Mon Sep 17 00:00:00 2001 From: Chen Shunqing Date: Fri, 9 Aug 2024 14:48:56 +0800 Subject: [PATCH 1/9] media: i2c: rk628: reduce power consumption when there is no hdmi in Signed-off-by: Chen Shunqing Change-Id: Idc4b5f2b6372414e61634b3144b01d6ca0acc447 --- drivers/media/i2c/rk628/rk628_combtxphy.c | 8 ++++---- drivers/media/i2c/rk628/rk628_csi_v4l2.c | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/media/i2c/rk628/rk628_combtxphy.c b/drivers/media/i2c/rk628/rk628_combtxphy.c index dac86c39ab20..299b798eb2fe 100644 --- a/drivers/media/i2c/rk628/rk628_combtxphy.c +++ b/drivers/media/i2c/rk628/rk628_combtxphy.c @@ -246,10 +246,10 @@ EXPORT_SYMBOL(rk628_txphy_power_on); void rk628_txphy_power_off(struct rk628 *rk628) { - rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_TX_IDLE_MASK | SW_TX_PD_MASK | - SW_PD_PLL_MASK | SW_MODULEB_EN_MASK | - SW_MODULEA_EN_MASK, SW_TX_IDLE(0x3ff) | - SW_TX_PD(0x3ff) | SW_PD_PLL); + rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_TX_IDLE_MASK | SW_TX_PD_MASK | + SW_PD_PLL_MASK | SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK | + SW_GVI_LVDS_EN_MASK | SW_MIPI_DSI_EN_MASK, + SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL); } EXPORT_SYMBOL(rk628_txphy_power_off); diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index d5038ddf545b..e4be55fa5e28 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -494,6 +494,7 @@ static void rk628_hdmirx_plugout(struct v4l2_subdev *sd) rk628_hdmirx_hpd_ctrl(sd, false); rk628_hdmirx_inno_phy_power_off(sd); rk628_hdmirx_verisyno_phy_power_off(csi->rk628); + mipi_dphy_power_off(csi); } static void rk628_hdmirx_config_all(struct v4l2_subdev *sd) @@ -1458,9 +1459,6 @@ static void rk628_csi_initial_setup(struct v4l2_subdev *sd) } csi->rk628->dphy_lane_en = 0x1f; - if (csi->plat_data->tx_mode == CSI_MODE) - mipi_dphy_power_on(csi); - csi->txphy_pwron = true; if (tx_5v_power_present(sd)) schedule_delayed_work(&csi->delayed_work_enable_hotplug, msecs_to_jiffies(4000)); From 0cb1f2340ce207bfc0b821c00ba1723781da1bec Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Aug 2024 10:53:18 +0800 Subject: [PATCH 2/9] ARM: rk3506_defconfig: Disable more unused NET_VENDOR Change-Id: Ie466c01ef94d34c9aad8a64fb4bc055d5108550a Signed-off-by: Tao Huang --- arch/arm/configs/rk3506_defconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/configs/rk3506_defconfig b/arch/arm/configs/rk3506_defconfig index cb4c9dccbeb5..313d7fc4292e 100644 --- a/arch/arm/configs/rk3506_defconfig +++ b/arch/arm/configs/rk3506_defconfig @@ -102,17 +102,23 @@ CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_ASIX is not set # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CADENCE is not set # CONFIG_NET_VENDOR_CAVIUM is not set # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_DAVICOM is not set +# CONFIG_NET_VENDOR_ENGLEDER is not set # CONFIG_NET_VENDOR_EZCHIP is not set # CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_FUNGIBLE is not set # CONFIG_NET_VENDOR_GOOGLE is not set # CONFIG_NET_VENDOR_HISILICON is not set # CONFIG_NET_VENDOR_HUAWEI is not set # CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_ADI is not set +# CONFIG_NET_VENDOR_LITEX is not set # CONFIG_NET_VENDOR_MARVELL is not set # CONFIG_NET_VENDOR_MELLANOX is not set # CONFIG_NET_VENDOR_MICREL is not set @@ -136,7 +142,9 @@ CONFIG_STMMAC_FULL=y # CONFIG_DWMAC_GENERIC is not set CONFIG_DWMAC_ROCKCHIP_TOOL=y # CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VERTEXCOM is not set # CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WANGXUN is not set # CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_NET_VENDOR_XILINX is not set CONFIG_MOTORCOMM_PHY=y From 9ce43aae96634dbac558632dc51c3ba57b8e63cc Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Fri, 16 Aug 2024 16:52:48 +0800 Subject: [PATCH 3/9] drm/rockchip: fix some csc parameters error 1. Fix the csc matrix. For YUV709L to YUV709L, YUV601L to YUV601L, YUV2020L to YUV2020L, The csc matrix should be identity matrix. For YUV601L to YUV709L, modeify the csc matrix. 2. optimize the final calculation result. Use the new r2y and y2r matrix for csc yuv2yuv and rgb2rgb case. A simple round is used for csc yuv2yuv and rgb2rgb case for a more precise result. Change-Id: I51f1b597c2aa3edcb66bc359df709b9b61a97b52 Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/rockchip_post_csc.c | 145 +++++++++++-------- 1 file changed, 87 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_post_csc.c b/drivers/gpu/drm/rockchip/rockchip_post_csc.c index a57d562bf04f..7e8d183ebc2e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_post_csc.c +++ b/drivers/gpu/drm/rockchip/rockchip_post_csc.c @@ -207,6 +207,13 @@ static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsd /* xv_ycc BT.601 (i.e. SD) -> to BT.709 (i.e. HD) */ static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr = { + 1024, -118, -213, + 0, 1043, 117, + 0, 77, 1050 +}; + +/* xv_ycc BT.601 full(i.e. SD) -> to BT.709 full(i.e. HD) */ +static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_full_to_hdy_cb_cr_full = { 1024, -121, -218, 0, 1043, 117, 0, 77, 1050 @@ -642,7 +649,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = { }, { RK_PQ_CSC_YUV2YUV, "YUV L->YUV L", - &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, + &rk_csc_table_identity_y_cb_cr_to_y_cb_cr, &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, { OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_ITU_R_BT_709, false, false @@ -690,7 +697,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = { }, { RK_PQ_CSC_YUV2YUV_601_709_FULL, "YUV601 F->YUV709 F", - &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, + &rk_csc_table_xv_yccsdy_cb_cr_full_to_hdy_cb_cr_full, &rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full, { OPTM_CS_E_XV_YCC_601, OPTM_CS_E_ITU_R_BT_709, true, true @@ -890,7 +897,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = { }, { RK_PQ_CSC_YUV2YUV, "YUV 601 L->YUV 601 L", - &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, + &rk_csc_table_identity_y_cb_cr_to_y_cb_cr, &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, { OPTM_CS_E_XV_YCC_601, OPTM_CS_E_XV_YCC_601, false, false @@ -922,7 +929,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = { }, { RK_PQ_CSC_YUV2YUV, "YUV 2020 L->YUV 2020 L", - &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, + &rk_csc_table_identity_y_cb_cr_to_y_cb_cr, &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr, { OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_XV_YCC_2020, false, false @@ -988,14 +995,26 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = { static const struct rk_pq_csc_coef r2y_for_y2y = { 306, 601, 117, - -151, -296, 446, - 630, -527, -102, + -173, -339, 512, + 512, -429, -83, }; static const struct rk_pq_csc_coef y2r_for_y2y = { - 1024, -0, 1167, - 1024, -404, -594, - 1024, 2081, -1, + 1024, -1, 1436, + 1024, -353, -731, + 1024, 1814, 1, +}; + +static const struct rk_pq_csc_coef r2y_for_r2r = { + 1024, 0, 1612, + 1024, -192, -480, + 1024, 1900, -2, +}; + +static const struct rk_pq_csc_coef y2r_for_r2r = { + 218, 732, 74, + -117, -395, 512, + 512, -465, -47, }; static const struct rk_pq_csc_coef rgb_input_swap_matrix = { @@ -1124,7 +1143,7 @@ static void csc_matrix_ventor_multiply(struct rk_pq_csc_ventor *dst, m0->csc_coef22 * v0->csc_offset2; } -static void csc_matrix_element_left_shift(struct rk_pq_csc_coef *m, int n) +static void csc_matrix_element_right_shift(struct rk_pq_csc_coef *m, int n) { m->csc_coef00 = m->csc_coef00 >> n; m->csc_coef01 = m->csc_coef01 >> n; @@ -1137,6 +1156,30 @@ static void csc_matrix_element_left_shift(struct rk_pq_csc_coef *m, int n) m->csc_coef22 = m->csc_coef22 >> n; } +static inline s32 csc_simple_round(s32 x, s32 n) +{ + s32 value = 0; + + if (n == 0) + return x; + + value = (abs(x) + (1 << (n - 1))) >> (n); + return (((x) >= 0) ? value : -value); +} + +static void csc_matrix_element_right_shift_with_simple_round(struct rk_pq_csc_coef *m, int n) +{ + m->csc_coef00 = csc_simple_round(m->csc_coef00, n); + m->csc_coef01 = csc_simple_round(m->csc_coef01, n); + m->csc_coef02 = csc_simple_round(m->csc_coef02, n); + m->csc_coef10 = csc_simple_round(m->csc_coef10, n); + m->csc_coef11 = csc_simple_round(m->csc_coef11, n); + m->csc_coef12 = csc_simple_round(m->csc_coef12, n); + m->csc_coef20 = csc_simple_round(m->csc_coef20, n); + m->csc_coef21 = csc_simple_round(m->csc_coef21, n); + m->csc_coef22 = csc_simple_round(m->csc_coef22, n); +} + static struct rk_pq_csc_coef create_rgb_gain_matrix(s32 r_gain, s32 g_gain, s32 b_gain) { struct rk_pq_csc_coef m; @@ -1280,23 +1323,23 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv, csc_matrix_multiply(&temp0, csc_mode_cfg->pst_csc_coef, &hue_matrix); /* * The value bits width is 32 bit, so every time 2 matirx multifly, - * left shift is necessary to avoid overflow. For enhancing the + * right shift is necessary to avoid overflow. For enhancing the * calculator precision, PQ_CALC_ENHANCE_BIT bits is reserved and - * left shift before get the final result. + * right shift before get the final result. */ - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH - - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH - + PQ_CALC_ENHANCE_BIT); csc_matrix_multiply(&temp1, &temp0, &saturation_matrix); - csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(&temp0, &temp1, r2y_matrix); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH); csc_matrix_multiply(&temp1, &temp0, &gain_matrix); - csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(&temp0, &temp1, &contrast_matrix); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(out_matrix, &temp0, y2r_matrix); - csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH + - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift_with_simple_round(out_matrix, + PQ_CSC_PARAM_FIX_BIT_WIDTH + PQ_CALC_ENHANCE_BIT); dc_in_ventor.csc_offset0 = dc_in_offset; dc_in_ventor.csc_offset1 = -PQ_CSC_DC_IN_OUT_DEFAULT; @@ -1311,15 +1354,15 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv, * hue_matrix * saturation_matrix */ csc_matrix_multiply(&temp0, csc_mode_cfg->pst_csc_coef, &hue_matrix); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH - - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH - + PQ_CALC_ENHANCE_BIT); csc_matrix_multiply(&temp1, &temp0, &saturation_matrix); - csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(&temp0, &contrast_matrix, &temp1); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(out_matrix, &gain_matrix, &temp0); - csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH + - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift(out_matrix, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH + + PQ_CALC_ENHANCE_BIT); dc_in_ventor.csc_offset0 = dc_in_offset; dc_in_ventor.csc_offset1 = -PQ_CSC_DC_IN_OUT_DEFAULT; @@ -1334,15 +1377,15 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv, * gain_matrix * contrast_matrix */ csc_matrix_multiply(&temp0, csc_mode_cfg->pst_csc_coef, &gain_matrix); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH - - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH - + PQ_CALC_ENHANCE_BIT); csc_matrix_multiply(&temp1, &temp0, &contrast_matrix); - csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(&temp0, &saturation_matrix, &temp1); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(out_matrix, &hue_matrix, &temp0); - csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH + - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH + + PQ_CALC_ENHANCE_BIT); dc_in_ventor.csc_offset0 = dc_in_offset; dc_in_ventor.csc_offset1 = dc_in_offset; @@ -1356,35 +1399,21 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv, * so output = T * gain_matrix * contrast_matrix * * N_y2r * hue_matrix * saturation_matrix * N_r2y */ - if (!color_info->in_full_range && color_info->out_full_range) { - r2y_matrix = &rk_csc_table_rgb_limit_to_hdy_cb_cr; - y2r_matrix = &rk_csc_table_hdy_cb_cr_limit_to_rgb_full; - } else if (color_info->in_full_range && !color_info->out_full_range) { - r2y_matrix = &rk_csc_table_rgb_to_hdy_cb_cr; - y2r_matrix = &rk_csc_table_hdy_cb_cr_limit_to_rgb_limit; - } else if (color_info->in_full_range && color_info->out_full_range) { - r2y_matrix = &rk_csc_table_rgb_to_hdy_cb_cr_full; - y2r_matrix = &rk_csc_table_hdy_cb_cr_to_rgb_full; - } else { - r2y_matrix = &rk_csc_table_rgb_limit_to_hdy_cb_cr; - y2r_matrix = &rk_csc_table_hdy_cb_cr_limit_to_rgb_limit; - } + r2y_matrix = &r2y_for_r2r; + y2r_matrix = &y2r_for_r2r; csc_matrix_multiply(&temp0, &contrast_matrix, y2r_matrix); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH - - PQ_CALC_ENHANCE_BIT); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH - + PQ_CALC_ENHANCE_BIT); csc_matrix_multiply(&temp1, &gain_matrix, &temp0); - csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(&temp0, &temp1, &hue_matrix); - csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH); csc_matrix_multiply(&temp1, &temp0, &saturation_matrix); - csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); + csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH); csc_matrix_multiply(out_matrix, &temp1, r2y_matrix); - csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH + - PQ_CALC_ENHANCE_BIT); - - if (color_info->in_full_range && color_info->out_full_range) - out_matrix->csc_coef00 += 1; + csc_matrix_element_right_shift_with_simple_round(out_matrix, + PQ_CSC_PARAM_FIX_BIT_WIDTH + PQ_CALC_ENHANCE_BIT); dc_in_ventor.csc_offset0 = dc_in_offset; dc_in_ventor.csc_offset1 = dc_in_offset; @@ -1522,9 +1551,9 @@ int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_s rockchip_swap_color_channel(convert_mode->is_input_yuv, convert_mode->is_output_yuv, csc_simple_coef, &out_matrix, &out_dc); - csc_simple_coef->csc_dc0 = pq_csc_simple_round(csc_simple_coef->csc_dc0, bit_num); - csc_simple_coef->csc_dc1 = pq_csc_simple_round(csc_simple_coef->csc_dc1, bit_num); - csc_simple_coef->csc_dc2 = pq_csc_simple_round(csc_simple_coef->csc_dc2, bit_num); + csc_simple_coef->csc_dc0 = csc_simple_round(csc_simple_coef->csc_dc0, bit_num); + csc_simple_coef->csc_dc1 = csc_simple_round(csc_simple_coef->csc_dc1, bit_num); + csc_simple_coef->csc_dc2 = csc_simple_round(csc_simple_coef->csc_dc2, bit_num); csc_simple_coef->range_type = csc_mode_cfg->st_csc_color_info.out_full_range; return ret; From ed7f33a28dba5591697b0b954660d678ca8e256c Mon Sep 17 00:00:00 2001 From: Mingwei Yan Date: Mon, 15 Jul 2024 14:43:42 +0800 Subject: [PATCH 4/9] media: rockchip: vpss: offline add some debug info Signed-off-by: Mingwei Yan Change-Id: Idcdb789929698242a2d78a43a0f28b46be0b27d7 --- drivers/media/platform/rockchip/vpss/common.h | 1 + drivers/media/platform/rockchip/vpss/dev.c | 26 +- .../platform/rockchip/vpss/vpss_offline.c | 250 +++++++++++------- 3 files changed, 186 insertions(+), 91 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/common.h b/drivers/media/platform/rockchip/vpss/common.h index 6e4d71b8c1c7..5d64bf0090df 100644 --- a/drivers/media/platform/rockchip/vpss/common.h +++ b/drivers/media/platform/rockchip/vpss/common.h @@ -90,6 +90,7 @@ static inline struct vb2_queue *to_vb2_queue(struct file *file) extern int rkvpss_debug; extern struct platform_driver rkvpss_plat_drv; +extern int rkvpss_cfginfo_num; void rkvpss_idx_write(struct rkvpss_device *dev, u32 reg, u32 val, int idx); void rkvpss_unite_write(struct rkvpss_device *dev, u32 reg, u32 val); diff --git a/drivers/media/platform/rockchip/vpss/dev.c b/drivers/media/platform/rockchip/vpss/dev.c index 971d4e209691..4ff43faccb6d 100644 --- a/drivers/media/platform/rockchip/vpss/dev.c +++ b/drivers/media/platform/rockchip/vpss/dev.c @@ -24,7 +24,7 @@ int rkvpss_debug; module_param_named(debug, rkvpss_debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-3)"); +MODULE_PARM_DESC(debug, "Debug level (0-6)"); static bool rkvpss_clk_dbg; module_param_named(clk_dbg, rkvpss_clk_dbg, bool, 0644); @@ -34,6 +34,30 @@ static char rkvpss_version[RKVPSS_VERNO_LEN]; module_param_string(version, rkvpss_version, RKVPSS_VERNO_LEN, 0444); MODULE_PARM_DESC(version, "version number"); +int rkvpss_cfginfo_num = 5; + +static int rkvpss_get_cfginfo_num(const char *val, const struct kernel_param *kp) +{ + int num, ret; + + ret = kstrtoint(val, 10, &num); + if (ret) + return ret; + if (num < 0 || num > 50) { + pr_info("rkvpss_cfginfo_num must be range of 0 to 50"); + return -EINVAL; + } + + return param_set_int(val, kp); +} + +static const struct kernel_param_ops cfginfo_num_ops = { + .set = rkvpss_get_cfginfo_num, + .get = param_get_int, +}; +module_param_cb(cfginfo_num, &cfginfo_num_ops, &rkvpss_cfginfo_num, 0644); +MODULE_PARM_DESC(cfginfo_num, "rkvpss offline cfginfo number"); + void rkvpss_set_clk_rate(struct clk *clk, unsigned long rate) { if (rkvpss_clk_dbg) diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline.c b/drivers/media/platform/rockchip/vpss/vpss_offline.c index 09f3e448e0af..0505272af651 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline.c @@ -148,7 +148,8 @@ static struct rkvpss_offline_buf *buf_add(struct file *file, int id, int fd, int buf->alloc = false; list_add_tail(&buf->list, &ofl->list); v4l2_dbg(1, rkvpss_debug, &ofl->v4l2_dev, - "%s file:%p dev_id:%d fd:%d dbuf:%p\n", __func__, file, id, fd, dbuf); + "%s file:%p dev_id:%d fd:%d dbuf:%p size:%d\n", __func__, + file, id, fd, dbuf, size); } else { dma_buf_put(dbuf); } @@ -417,6 +418,13 @@ static void poly_phase_scale(struct rkvpss_frame_cfg *frame_cfg, end: val = RKVPSS_ZME_GEN_UPD | RKVPSS_ZME_FORCE_UPD; rkvpss_hw_write(hw, RKVPSS_ZME_UPDATE, val); + + v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, + "%s unite:%d left:%d hw ctrl:0x%x y_src_size:0x%x y_dst_size:0x%x\n", + __func__, unite, left, + rkvpss_hw_read(hw, RKVPSS_ZME_CTRL), + rkvpss_hw_read(hw, RKVPSS_ZME_Y_SRC_SIZE), + rkvpss_hw_read(hw, RKVPSS_ZME_Y_DST_SIZE)); } static void bilinear_scale(struct rkvpss_frame_cfg *frame_cfg, @@ -537,6 +545,13 @@ end: rkvpss_hw_write(hw, reg_base, ctrl); val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD; rkvpss_hw_write(hw, reg_base + 0x4, val); + + v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, + "%s unite:%d left:%d hw ch:%d ctrl:0x%x y_src_size:0x%x y_dst_size:0x%x\n", + __func__, unite, left, idx, + rkvpss_hw_read(hw, reg_base), + rkvpss_hw_read(hw, reg_base + 0x8), + rkvpss_hw_read(hw, reg_base + 0xc)); } static void scale_config(struct file *file, @@ -556,7 +571,7 @@ static void scale_config(struct file *file, } } -static void cmsc_config(struct rkvpss_offline_dev *ofl, +static int cmsc_config(struct rkvpss_offline_dev *ofl, struct rkvpss_frame_cfg *cfg, bool unite, bool left) { struct rkvpss_hw_dev *hw = ofl->hw; @@ -568,9 +583,10 @@ static void cmsc_config(struct rkvpss_offline_dev *ofl, u32 ch_win_mode[RKVPSS_OUTPUT_MAX]; u32 win_color[RKVPSS_CMSC_WIN_MAX]; u32 val, slope, hor, mask, mosaic_block = 0, ctrl = 0; + u32 hw_in_w, hw_in_h; if (!hw->is_ofl_cmsc) - return; + return 0; for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) { if (!cfg->output[i].enable) @@ -597,14 +613,8 @@ static void cmsc_config(struct rkvpss_offline_dev *ofl, cfg->output[i].cmsc.win[j].cover_color_a = 15; win_color[j] |= RKVPSS_CMSC_WIN_ALPHA(cfg->output[i].cmsc.win[j].cover_color_a); } - for (k = 0; k < RKVPSS_CMSC_POINT_MAX; k++) { + for (k = 0; k < RKVPSS_CMSC_POINT_MAX; k++) tmp_cfg.win[j].point[k] = cmsc_cfg->win[j].point[k]; - v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, - "%s input params dev_id:%d, unite:%d left:%d ch:%d win:%d point:%d x:%u y:%u", - __func__, cfg->dev_id, unite, left, i, j, k, - tmp_cfg.win[j].point[k].x, - tmp_cfg.win[j].point[k].y); - } } } @@ -705,10 +715,23 @@ static void cmsc_config(struct rkvpss_offline_dev *ofl, } rkvpss_hw_write(hw, RKVPSS_CMSC_CHN0_WIN + i * 4, ch_win_en[i]); rkvpss_hw_write(hw, RKVPSS_CMSC_CHN0_MODE + i * 4, ch_win_mode[i]); + hw_in_w = rkvpss_hw_read(hw, RKVPSS_MI_RD_Y_WIDTH); + hw_in_h = rkvpss_hw_read(hw, RKVPSS_MI_RD_Y_HEIGHT); for (j = 0; j < RKVPSS_CMSC_WIN_MAX; j++) { if (!(ch_win_en[i] & BIT(j))) continue; for (k = 0; k < RKVPSS_CMSC_POINT_MAX; k++) { + if (tmp_cfg.win[j].point[k].x > hw_in_w || + tmp_cfg.win[j].point[k].y > hw_in_h) { + v4l2_err(&ofl->v4l2_dev, + "%s cmsc coordinate error dev_id:%d unite:%u left:%u ch:%d win:%d point:%d x:%u y:%u hw_in_w:%u hw_in_h:%u\n", + __func__, cfg->dev_id, unite, left, + i, j, k, + tmp_cfg.win[j].point[k].x, + tmp_cfg.win[j].point[k].y, + hw_in_w, hw_in_w); + return -EINVAL; + } val = RKVPSS_CMSC_WIN_VTX(tmp_cfg.win[j].point[k].x, tmp_cfg.win[j].point[k].y); rkvpss_hw_write(hw, RKVPSS_CMSC_WIN0_L0_VTX + k * 8 + j * 32, val); @@ -718,7 +741,7 @@ static void cmsc_config(struct rkvpss_offline_dev *ofl, &slope, &hor); val = RKVPSS_CMSC_WIN_SLP(slope, hor); rkvpss_hw_write(hw, RKVPSS_CMSC_WIN0_L0_SLP + k * 8 + j * 32, val); - v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, + v4l2_dbg(4, rkvpss_debug, &ofl->v4l2_dev, "%s dev_id:%d, unite:%d left:%d ch:%d win:%d point:%d x:%u y:%u", __func__, cfg->dev_id, unite, left, i, j, k, tmp_cfg.win[j].point[k].x, @@ -736,9 +759,11 @@ static void cmsc_config(struct rkvpss_offline_dev *ofl, val = RKVPSS_CMSC_GEN_UPD | RKVPSS_CMSC_FORCE_UPD; rkvpss_hw_write(hw, RKVPSS_CMSC_UPDATE, val); - v4l2_dbg(4, rkvpss_debug, &ofl->v4l2_dev, - "%s dev_id:%d, unite:%d left:%d ctrl:0x%x update_val:0x%x", + v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, + "%s dev_id:%d, unite:%d left:%d hw ctrl:0x%x update_val:0x%x", __func__, cfg->dev_id, unite, left, ctrl, val); + + return 0; } static void aspt_config(struct file *file, @@ -789,6 +814,14 @@ static void aspt_config(struct file *file, rkvpss_hw_write(hw, reg_base, RKVPSS_RATIO_EN); val = RKVPSS_RATIO_FORCE_UPD | RKVPSS_RATIO_GEN_UPD; rkvpss_hw_write(hw, reg_base + 0x4, val); + + v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, + "%s hw ch:%d ctrl:0x%x in_size:0x%x out_size:0x%x offset:0x%x\n", + __func__, i, + rkvpss_hw_read(hw, reg_base), + rkvpss_hw_read(hw, reg_base + 0x10), + rkvpss_hw_read(hw, reg_base + 0x14), + rkvpss_hw_read(hw, reg_base + 0x18)); } } @@ -821,14 +854,16 @@ static void add_cfginfo(struct rkvpss_offline_dev *ofl, struct rkvpss_frame_cfg list_for_each_entry(cfginfo, &ofl->cfginfo_list, list) { count++; } - if (count >= 5) { + while (count >= rkvpss_cfginfo_num && count != 0) { first_cfg = list_first_entry(&ofl->cfginfo_list, struct rkvpss_ofl_cfginfo, list); list_del_init(&first_cfg->list); kfree(first_cfg); - list_add_tail(&new_cfg->list, &ofl->cfginfo_list); - } else { - list_add_tail(&new_cfg->list, &ofl->cfginfo_list); + count--; } + if (rkvpss_cfginfo_num) + list_add_tail(&new_cfg->list, &ofl->cfginfo_list); + else + kfree(new_cfg); mutex_unlock(&ofl->ofl_lock); } @@ -1028,7 +1063,7 @@ static int read_config(struct file *file, struct rkvpss_frame_cfg *cfg, bool uni } v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, - "%s unite:%d left:%d width:%d height:%d y_base:0x%x\n", + "%s unite:%d left:%d hw width:%d height:%d y_base:0x%x\n", __func__, unite, left, rkvpss_hw_read(hw, RKVPSS_MI_RD_Y_WIDTH), rkvpss_hw_read(hw, RKVPSS_MI_RD_Y_HEIGHT), @@ -1144,13 +1179,17 @@ static void crop_config(struct file *file, struct rkvpss_frame_cfg *cfg, bool un rkvpss_hw_write(hw, RKVPSS_CROP0_CTRL, crop_en); rkvpss_hw_write(hw, RKVPSS_CROP0_UPDATE, RKVPSS_CROP_FORCE_UPD); - v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, - "%s unite:%d left:%d h_offs:%d v_offs:%d width:%d height:%d\n", - __func__, unite, left, - rkvpss_hw_read(hw, RKVPSS_CROP0_0_H_OFFS), - rkvpss_hw_read(hw, RKVPSS_CROP0_0_V_OFFS), - rkvpss_hw_read(hw, RKVPSS_CROP0_0_H_SIZE), - rkvpss_hw_read(hw, RKVPSS_CROP0_0_V_SIZE)); + for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) { + if (!cfg->output[i].enable) + continue; + v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, + "%s unite:%d left:%d hw ch:%d h_offs:%d v_offs:%d width:%d height:%d\n", + __func__, unite, left, i, + rkvpss_hw_read(hw, RKVPSS_CROP0_0_H_OFFS + i * 0x10), + rkvpss_hw_read(hw, RKVPSS_CROP0_0_V_OFFS + i * 0x10), + rkvpss_hw_read(hw, RKVPSS_CROP0_0_H_SIZE + i * 0x10), + rkvpss_hw_read(hw, RKVPSS_CROP0_0_V_SIZE + i * 0x10)); + } } static int write_config(struct file *file, struct rkvpss_frame_cfg *cfg, bool unite, bool left) @@ -1375,7 +1414,7 @@ static int write_config(struct file *file, struct rkvpss_frame_cfg *cfg, bool un mi_update |= (RKVPSS_MI_CHN0_FORCE_UPD << i); v4l2_dbg(3, rkvpss_debug, &ofl->v4l2_dev, - "%s unite:%d left:%d ch:%d y_size:%d y_stride:%d y_pic_size:%d y_base:0x%x", + "%s unite:%d left:%d hw ch:%d y_size:%d y_stride:%d y_pic_size:%d y_base:0x%x", __func__, unite, left, i, rkvpss_hw_read(hw, RKVPSS_MI_CHN0_WR_Y_SIZE + i * 100), rkvpss_hw_read(hw, RKVPSS_MI_CHN0_WR_Y_STRIDE + i * 100), @@ -1505,22 +1544,22 @@ static void calc_unite_scl_params(struct file *file, struct rkvpss_frame_cfg *cf params->scl_in_crop_w_y = right_y_crop_total - params->quad_crop_w; params->scl_in_crop_w_c = right_c_crop_total - params->quad_crop_w; - if (rkvpss_debug >= 2) { + if (rkvpss_debug >= 4) { v4l2_info(&ofl->v4l2_dev, "%s dev_id:%d seq:%d ch:%d y_w_fac:%u c_w_fac:%u y_h_fac:%u c_h_fac:%u\n", __func__, cfg->dev_id, cfg->sequence, i, params->y_w_fac, params->c_w_fac, params->y_h_fac, params->c_h_fac); v4l2_info(&ofl->v4l2_dev, - "\t%s unite_right_enlarge:%u", - __func__, ofl->unite_right_enlarge); + "\t\t\t\t\t\t unite_right_enlarge:%u", + ofl->unite_right_enlarge); v4l2_info(&ofl->v4l2_dev, - "\t%s y_w_phase:%u c_w_phase:%u quad_crop_w:%u scl_in_crop_w_y:%u scl_in_crop_w_c:%u\n", - __func__, params->y_w_phase, params->c_w_phase, + "\t\t\t\t\t\t y_w_phase:%u c_w_phase:%u quad_crop_w:%u scl_in_crop_w_y:%u scl_in_crop_w_c:%u\n", + params->y_w_phase, params->c_w_phase, params->quad_crop_w, params->scl_in_crop_w_y, params->scl_in_crop_w_c); v4l2_info(&ofl->v4l2_dev, - "\t%s right_scl_need_size_y:%u right_scl_need_size_c:%u\n", - __func__, params->right_scl_need_size_y, + "\t\t\t\t\t\t right_scl_need_size_y:%u right_scl_need_size_c:%u\n", + params->right_scl_need_size_y, params->right_scl_need_size_c); } } @@ -1531,41 +1570,12 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg, bool struct rkvpss_offline_dev *ofl = video_drvdata(file); struct rkvpss_hw_dev *hw = ofl->hw; u32 update, val, mask; - ktime_t t = 0; - s64 us = 0; int ret, i; - u64 ns; bool left_tmp; - if (rkvpss_debug >= 2) { - v4l2_info(&ofl->v4l2_dev, - "%s dev_id:%d seq:%d mirror:%d input:%dx%d buffd:%d format:%c%c%c%c\n", - __func__, cfg->dev_id, cfg->sequence, cfg->mirror, - cfg->input.width, cfg->input.height, cfg->input.buf_fd, - cfg->input.format, cfg->input.format >> 8, - cfg->input.format >> 16, cfg->input.format >> 24); - for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) { - if (!cfg->output[i].enable) - continue; - v4l2_info(&ofl->v4l2_dev, - "\t\t\tch%d crop:(%d,%d)/%dx%d scl:%dx%d flip:%d buffd:%d format:%c%c%c%c\n", - i, cfg->output[i].crop_h_offs, cfg->output[i].crop_v_offs, - cfg->output[i].crop_width, cfg->output[i].crop_height, - cfg->output[i].scl_width, cfg->output[i].scl_height, - cfg->output[i].flip, cfg->output[i].buf_fd, - cfg->output[i].format, cfg->output[i].format >> 8, - cfg->output[i].format >> 16, cfg->output[i].format >> 24); - } - t = ktime_get(); - } - if (!unite || left) add_cfginfo(ofl, cfg); - ns = ktime_get_ns(); - ofl->dev_rate[cfg->dev_id].in_rate = ns - ofl->dev_rate[cfg->dev_id].in_timestamp; - ofl->dev_rate[cfg->dev_id].in_timestamp = ns; - init_completion(&ofl->cmpl); ofl->mode_sel_en = false; @@ -1581,7 +1591,9 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg, bool else left_tmp = left; - cmsc_config(ofl, cfg, unite, left_tmp); + ret = cmsc_config(ofl, cfg, unite, left_tmp); + if (ret) + return ret; crop_config(file, cfg, unite, left_tmp); scale_config(file, cfg, unite, left_tmp); if (!unite) @@ -1614,20 +1626,6 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg, bool rkvpss_hw_write(hw, RKVPSS_VPSS_UPDATE, update); rkvpss_hw_set_bits(hw, RKVPSS_VPSS_IMSC, 0, RKVPSS_ALL_FRM_END); - if (rkvpss_debug >=5) { - v4l2_info(&ofl->v4l2_dev, - "%s dev_id%d unite:%d left:%d\n", - __func__, cfg->dev_id, unite, left); - for (i = 0; i < 16128; i += 16) { - printk("%04x: %08x %08x %08x %08x\n", - i, - rkvpss_hw_read(hw, i), - rkvpss_hw_read(hw, i + 4), - rkvpss_hw_read(hw, i + 8), - rkvpss_hw_read(hw, i + 12)); - } - } - rkvpss_hw_write(hw, RKVPSS_MI_RD_START, RKVPSS_MI_RD_ST); ret = wait_for_completion_timeout(&ofl->cmpl, msecs_to_jiffies(500)); @@ -1638,19 +1636,6 @@ static int rkvpss_ofl_run(struct file *file, struct rkvpss_frame_cfg *cfg, bool ret = 0; } - if (rkvpss_debug >= 2) { - us = ktime_us_delta(ktime_get(), t); - v4l2_info(&ofl->v4l2_dev, - "%s end, time:%lldus\n", __func__, us); - } - - ns = ktime_get_ns(); - ofl->dev_rate[cfg->dev_id].out_rate = ns - ofl->dev_rate[cfg->dev_id].out_timestamp; - ofl->dev_rate[cfg->dev_id].out_timestamp = ns; - ofl->dev_rate[cfg->dev_id].sequence = cfg->sequence; - ofl->dev_rate[cfg->dev_id].delay = ofl->dev_rate[cfg->dev_id].out_timestamp - - ofl->dev_rate[cfg->dev_id].in_timestamp; - return ret; } @@ -1970,11 +1955,83 @@ static int rkvpss_prepare_run(struct file *file, struct rkvpss_frame_cfg *cfg) struct rkvpss_offline_dev *ofl = video_drvdata(file); int ret = 0; bool unite; + int i, j, k; + s64 us = 0; + u64 ns; + ktime_t t = 0; + + ns = ktime_get_ns(); + ofl->dev_rate[cfg->dev_id].in_rate = ns - ofl->dev_rate[cfg->dev_id].in_timestamp; + ofl->dev_rate[cfg->dev_id].in_timestamp = ns; ret = rkvpss_check_params(file, cfg, &unite); if (ret < 0) goto end; + /******** show cfg info ********/ + if (rkvpss_debug >= 2) { + t = ktime_get(); + + v4l2_info(&ofl->v4l2_dev, + "%s dev_id:%d seq:%d mirror:%d input:%dx%d buffd:%d format:%c%c%c%c stride:%d rotate:%d\n", + __func__, cfg->dev_id, cfg->sequence, cfg->mirror, + cfg->input.width, cfg->input.height, cfg->input.buf_fd, + cfg->input.format, cfg->input.format >> 8, + cfg->input.format >> 16, cfg->input.format >> 24, + cfg->input.stride, cfg->input.rotate); + for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) { + v4l2_info(&ofl->v4l2_dev, + "\t\t\tch%d enable:%d crop:(%d,%d)/%dx%d scl:%dx%d flip:%d buffd:%d format:%c%c%c%c stride:%d\n", + i, cfg->output[i].enable, + cfg->output[i].crop_h_offs, cfg->output[i].crop_v_offs, + cfg->output[i].crop_width, cfg->output[i].crop_height, + cfg->output[i].scl_width, cfg->output[i].scl_height, + cfg->output[i].flip, cfg->output[i].buf_fd, + cfg->output[i].format, cfg->output[i].format >> 8, + cfg->output[i].format >> 16, cfg->output[i].format >> 24, + cfg->output[i].stride); + if (rkvpss_debug < 4) + break; + if (!cfg->output[i].enable) + continue; + v4l2_info(&ofl->v4l2_dev, + "\t\t\tcmsc mosaic_block:%d width_ro:%d height_ro:%d\n", + cfg->output[i].cmsc.mosaic_block, + cfg->output[i].cmsc.width_ro, + cfg->output[i].cmsc.height_ro); + for (j = 0; j < RKVPSS_CMSC_WIN_MAX; j++) { + if (!cfg->output[i].cmsc.win[j].win_en) + continue; + v4l2_info(&ofl->v4l2_dev, + "\t\t\t\twin:%d win_en:%u mode:%u color_y:%u color_u:%u color_v:%u color_a:%u\n", + j, + cfg->output[i].cmsc.win[j].win_en, + cfg->output[i].cmsc.win[j].mode, + cfg->output[i].cmsc.win[j].cover_color_y, + cfg->output[i].cmsc.win[j].cover_color_u, + cfg->output[i].cmsc.win[j].cover_color_v, + cfg->output[i].cmsc.win[j].cover_color_a); + for (k = 0; k < RKVPSS_CMSC_POINT_MAX; k++) { + v4l2_info(&ofl->v4l2_dev, + "\t\t\t\t\tpoint:%d x:%d y:%d\n", + k, + cfg->output[i].cmsc.win[j].point[k].x, + cfg->output[i].cmsc.win[j].point[k].y); + } + } + v4l2_info(&ofl->v4l2_dev, + "\t\t\taspt_en:%d w:%d h:%d h_offs:%d v_offs:%d color_y:%d color_u:%d color_v:%d\n", + cfg->output[i].aspt.enable, + cfg->output[i].aspt.width, + cfg->output[i].aspt.height, + cfg->output[i].aspt.h_offs, + cfg->output[i].aspt.v_offs, + cfg->output[i].aspt.color_y, + cfg->output[i].aspt.color_u, + cfg->output[i].aspt.color_v); + } + } + if (!unite) { ret = rkvpss_ofl_run(file, cfg, false, false); if (ret < 0) @@ -1992,6 +2049,19 @@ static int rkvpss_prepare_run(struct file *file, struct rkvpss_frame_cfg *cfg) } } + if (rkvpss_debug >= 2) { + us = ktime_us_delta(ktime_get(), t); + v4l2_info(&ofl->v4l2_dev, + "%s end, time:%lldus\n", __func__, us); + } + + ns = ktime_get_ns(); + ofl->dev_rate[cfg->dev_id].out_rate = ns - ofl->dev_rate[cfg->dev_id].out_timestamp; + ofl->dev_rate[cfg->dev_id].out_timestamp = ns; + ofl->dev_rate[cfg->dev_id].sequence = cfg->sequence; + ofl->dev_rate[cfg->dev_id].delay = ofl->dev_rate[cfg->dev_id].out_timestamp - + ofl->dev_rate[cfg->dev_id].in_timestamp; + end: return ret; } From 205bc82ae44f67e0311fb4b5c590877da92e65fe Mon Sep 17 00:00:00 2001 From: Mingwei Yan Date: Thu, 1 Aug 2024 17:03:43 +0800 Subject: [PATCH 5/9] media: rockchip: vpss: support suspend and resume Signed-off-by: Mingwei Yan Change-Id: I30a15c5952853b99968acbe732adcc83301e1d62 --- drivers/media/platform/rockchip/vpss/dev.c | 47 ++++- drivers/media/platform/rockchip/vpss/dev.h | 3 + drivers/media/platform/rockchip/vpss/hw.c | 165 ++++++++++++++++-- drivers/media/platform/rockchip/vpss/hw.h | 4 + drivers/media/platform/rockchip/vpss/stream.c | 14 +- drivers/media/platform/rockchip/vpss/vpss.c | 10 +- .../platform/rockchip/vpss/vpss_offline.c | 17 +- .../platform/rockchip/vpss/vpss_offline.h | 2 + 8 files changed, 236 insertions(+), 26 deletions(-) diff --git a/drivers/media/platform/rockchip/vpss/dev.c b/drivers/media/platform/rockchip/vpss/dev.c index 4ff43faccb6d..e93011d10fb3 100644 --- a/drivers/media/platform/rockchip/vpss/dev.c +++ b/drivers/media/platform/rockchip/vpss/dev.c @@ -347,6 +347,8 @@ static int rkvpss_plat_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); vpss_dev->is_probe_end = true; init_waitqueue_head(&vpss_dev->stop_done); + vpss_dev->is_suspend = false; + vpss_dev->is_idle = true; return 0; err_unreg_media_dev: @@ -375,7 +377,7 @@ static int rkvpss_plat_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused rkvpss_runtime_suspend(struct device *dev) +static int __maybe_unused rkvpss_dev_runtime_suspend(struct device *dev) { struct rkvpss_device *vpss_dev = dev_get_drvdata(dev); int ret; @@ -386,7 +388,7 @@ static int __maybe_unused rkvpss_runtime_suspend(struct device *dev) return (ret > 0) ? 0 : ret; } -static int __maybe_unused rkvpss_runtime_resume(struct device *dev) +static int __maybe_unused rkvpss_dev_runtime_resume(struct device *dev) { struct rkvpss_device *vpss_dev = dev_get_drvdata(dev); int ret; @@ -397,9 +399,46 @@ static int __maybe_unused rkvpss_runtime_resume(struct device *dev) return (ret > 0) ? 0 : ret; } +static int rkvpss_pm_suspend(struct device *dev) +{ + struct rkvpss_device *vpss_dev = dev_get_drvdata(dev); + u32 ret; + + v4l2_dbg(4, rkvpss_debug, &vpss_dev->v4l2_dev, "%s enter\n", __func__); + if (vpss_dev->vpss_sdev.state == VPSS_STOP) + return 0; + + vpss_dev->is_suspend = true; + /* wait fe*/ + if (!vpss_dev->is_idle) { + ret = wait_for_completion_timeout(&vpss_dev->pm_suspend_wait_fe, + msecs_to_jiffies(200)); + if (!ret) + v4l2_info(&vpss_dev->v4l2_dev, "%s wait fe timeout\n", __func__); + } + v4l2_dbg(4, rkvpss_debug, &vpss_dev->v4l2_dev, "%s exit\n", __func__); + return 0; +} + +static int rkvpss_pm_resume(struct device *dev) +{ + struct rkvpss_device *vpss_dev = dev_get_drvdata(dev); + + v4l2_dbg(4, rkvpss_debug, &vpss_dev->v4l2_dev, "%s enter\n", __func__); + if (vpss_dev->vpss_sdev.state == VPSS_STOP) + return 0; + + vpss_dev->is_suspend = false; + v4l2_dbg(4, rkvpss_debug, &vpss_dev->v4l2_dev, "%s exit\n", __func__); + + return 0; +} + static const struct dev_pm_ops rkvpss_plat_pm_ops = { - SET_RUNTIME_PM_OPS(rkvpss_runtime_suspend, - rkvpss_runtime_resume, NULL) + .suspend = rkvpss_pm_suspend, + .resume = rkvpss_pm_resume, + SET_RUNTIME_PM_OPS(rkvpss_dev_runtime_suspend, + rkvpss_dev_runtime_resume, NULL) }; struct platform_driver rkvpss_plat_drv = { diff --git a/drivers/media/platform/rockchip/vpss/dev.h b/drivers/media/platform/rockchip/vpss/dev.h index be9830241462..eaebd3fbdab0 100644 --- a/drivers/media/platform/rockchip/vpss/dev.h +++ b/drivers/media/platform/rockchip/vpss/dev.h @@ -79,6 +79,9 @@ struct rkvpss_device { unsigned int irq_ends_mask; bool is_probe_end; + bool is_suspend; + bool is_idle; + struct completion pm_suspend_wait_fe; }; void rkvpss_pipeline_default_fmt(struct rkvpss_device *dev); diff --git a/drivers/media/platform/rockchip/vpss/hw.c b/drivers/media/platform/rockchip/vpss/hw.c index bd974b17cfeb..f5bd2c96d5e2 100644 --- a/drivers/media/platform/rockchip/vpss/hw.c +++ b/drivers/media/platform/rockchip/vpss/hw.c @@ -702,6 +702,107 @@ static const struct of_device_id rkvpss_hw_of_match[] = { {}, }; +void rkvpss_hw_reg_save(struct rkvpss_hw_dev *dev) +{ + void *buf = dev->sw_reg; + + dev_info(dev->dev, "%s\n", __func__); + memcpy_fromio(buf, dev->base_addr, RKVPSS_SW_REG_SIZE); +} + +void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev) +{ + void __iomem *base = dev->base_addr; + void *reg_buf = dev->sw_reg; + u32 val, *reg, i; + + dev_info(dev->dev, "%s\n", __func__); + + /* cmsc */ + for (i = RKVPSS_CMSC_BASE; i <= RKVPSS_CMSC_WIN7_L3_SLP; i += 4) { + if (i == RKVPSS_CMSC_UPDATE) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_CMSC_GEN_UPD | RKVPSS_CMSC_UPDATE; + writel(val, base + RKVPSS_CMSC_UPDATE); + + /* crop1 */ + for (i = RKVPSS_CROP1_CTRL; i <= RKVPSS_CROP1_3_V_SIZE; i += 4) { + if (i == RKVPSS_CROP1_UPDATE) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_CROP_GEN_UPD | RKVPSS_CROP_FORCE_UPD; + writel(val, base + RKVPSS_CROP1_UPDATE); + writel(val, base + RKVPSS_CROP1_UPDATE); + + /* scale */ + for (i = RKVPSS_ZME_BASE; i <= RKVPSS_ZME_UV_YSCL_FACTOR; i += 4) { + if (i == RKVPSS_ZME_UPDATE) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_ZME_GEN_UPD | RKVPSS_ZME_FORCE_UPD; + writel(val, base + RKVPSS_ZME_UPDATE); + + for (i = RKVPSS_SCALE1_BASE; i <= RKVPSS_SCALE1_IN_CROP_OFFSET; i += 4) { + if (i == RKVPSS_SCALE1_UPDATE) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD; + writel(val, base + RKVPSS_SCALE1_UPDATE); + + for (i = RKVPSS_SCALE2_BASE; i <= RKVPSS_SCALE2_IN_CROP_OFFSET; i += 4) { + if (i == RKVPSS_SCALE2_UPDATE) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD; + writel(val, base + RKVPSS_SCALE2_UPDATE); + + for (i = RKVPSS_SCALE3_BASE; i <= RKVPSS_SCALE3_IN_CROP_OFFSET; i += 4) { + if (i == RKVPSS_SCALE3_UPDATE) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_SCL_GEN_UPD | RKVPSS_SCL_FORCE_UPD; + writel(val, base + RKVPSS_SCALE3_UPDATE); + + /* mi */ + for (i = RKVPSS_MI_BASE; i <= RKVPSS_MI_CHN3_WR_LINE_CNT; i += 4) { + if (i >= RKVPSS_MI_RD_CTRL && i <= RKVPSS_MI_RD_Y_HEIGHT_SHD) + continue; + if (i == RKVPSS_MI_WR_INIT) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_MI_FORCE_UPD; + writel(val, base + RKVPSS_MI_WR_INIT); + writel(val, base + RKVPSS_MI_WR_INIT); + + /* vpss ctrl */ + for (i = RKVPSS_VPSS_BASE; i <= RKVPSS_VPSS_Y2R_OFF2; i += 4) { + if (i == RKVPSS_VPSS_UPDATE || i == RKVPSS_VPSS_RESET) + continue; + reg = reg_buf + i; + writel(*reg, base + i); + } + val = RKVPSS_CFG_FORCE_UPD | RKVPSS_CFG_GEN_UPD | RKVPSS_MIR_GEN_UPD | + RKVPSS_ONLINE2_CHN_FORCE_UPD; + if (!dev->is_ofl_cmsc) + val |= RKVPSS_MIR_FORCE_UPD; + writel(val, base + RKVPSS_VPSS_UPDATE); +} + static int rkvpss_hw_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -721,6 +822,9 @@ static int rkvpss_hw_probe(struct platform_device *pdev) if (!hw_dev) return -ENOMEM; + hw_dev->sw_reg = devm_kzalloc(dev, RKVPSS_SW_REG_SIZE, GFP_KERNEL); + if (!hw_dev->sw_reg) + return -ENOMEM; dev_set_drvdata(dev, hw_dev); hw_dev->dev = dev; match_data = match->data; @@ -749,8 +853,8 @@ static int rkvpss_hw_probe(struct platform_device *pdev) irq = platform_get_irq_byname(pdev, match_data->irqs[i].name); if (irq < 0) { dev_err(dev, "no irq %s in dts\n", match_data->irqs[i].name); - ret = irq; - goto err; + ret = irq; + goto err; } ret = devm_request_irq(dev, irq, match_data->irqs[i].irq_hdl, @@ -798,6 +902,7 @@ static int rkvpss_hw_probe(struct platform_device *pdev) hw_dev->is_dma_contig = true; hw_dev->is_shutdown = false; hw_dev->is_mmu = is_iommu_enable(dev); + hw_dev->is_suspend = false; ret = of_reserved_mem_device_init(dev); if (ret) { is_mem_reserved = false; @@ -839,40 +944,72 @@ static void rkvpss_hw_shutdown(struct platform_device *pdev) } } -static int __maybe_unused rkvpss_runtime_suspend(struct device *dev) +static int __maybe_unused rkvpss_hw_runtime_suspend(struct device *dev) { struct rkvpss_hw_dev *hw_dev = dev_get_drvdata(dev); + u32 ret; + + if (rkvpss_debug >= 4) + dev_info(dev, "%s enter\n", __func__); + + if (dev->power.runtime_status) { + rkvpss_hw_write(hw_dev, RKVPSS_MI_IMSC, 0); + rkvpss_hw_write(hw_dev, RKVPSS_VPSS_IMSC, 0); + hw_dev->ofl_dev.mode_sel_en = true; + } else { + rkvpss_hw_reg_save(hw_dev); + hw_dev->is_suspend = true; + if (hw_dev->ofl_dev.pm_need_wait) { + ret = wait_for_completion_timeout(&hw_dev->ofl_dev.pm_cmpl, + msecs_to_jiffies(200)); + if (!ret) + dev_info(dev, "%s pm wait offline timeout\n", __func__); + } + } - rkvpss_hw_write(hw_dev, RKVPSS_MI_IMSC, 0); - rkvpss_hw_write(hw_dev, RKVPSS_VPSS_IMSC, 0); disable_sys_clk(hw_dev); - hw_dev->ofl_dev.mode_sel_en = true; + + if (rkvpss_debug >= 4) + dev_info(dev, "%s exit\n", __func__); + return 0; } -static int __maybe_unused rkvpss_runtime_resume(struct device *dev) +static int __maybe_unused rkvpss_hw_runtime_resume(struct device *dev) { struct rkvpss_hw_dev *hw_dev = dev_get_drvdata(dev); void __iomem *base = hw_dev->base_addr; int i; + if (rkvpss_debug >= 4) + dev_info(dev, "%s enter\n", __func__); + enable_sys_clk(hw_dev); rkvpss_soft_reset(hw_dev); - for (i = 0; i < hw_dev->dev_num; i++) { - void *buf = hw_dev->vpss[i]->sw_base_addr; + if (dev->power.runtime_status) { + for (i = 0; i < hw_dev->dev_num; i++) { + void *buf = hw_dev->vpss[i]->sw_base_addr; - memset(buf, 0, RKVPSS_SW_REG_SIZE_MAX); - memcpy_fromio(buf, base, RKVPSS_SW_REG_SIZE); + memset(buf, 0, RKVPSS_SW_REG_SIZE_MAX); + memcpy_fromio(buf, base, RKVPSS_SW_REG_SIZE); + } + } else { + rkvpss_hw_reg_restore(hw_dev); + hw_dev->is_suspend = false; } + + if (rkvpss_debug >= 4) + dev_info(dev, "%s exit\n", __func__); + return 0; } static const struct dev_pm_ops rkvpss_hw_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - SET_RUNTIME_PM_OPS(rkvpss_runtime_suspend, - rkvpss_runtime_resume, NULL) + SET_RUNTIME_PM_OPS(rkvpss_hw_runtime_suspend, + rkvpss_hw_runtime_resume, NULL) }; static struct platform_driver rkvpss_hw_drv = { diff --git a/drivers/media/platform/rockchip/vpss/hw.h b/drivers/media/platform/rockchip/vpss/hw.h index 662f1763b17b..8fb8bff15ad8 100644 --- a/drivers/media/platform/rockchip/vpss/hw.h +++ b/drivers/media/platform/rockchip/vpss/hw.h @@ -33,6 +33,7 @@ struct rkvpss_hw_dev { struct rkvpss_device *vpss[VPSS_MAX_DEV]; struct rkvpss_offline_dev ofl_dev; struct list_head list; + void *sw_reg; int clk_rate_tbl_num; int clks_num; int dev_num; @@ -52,6 +53,7 @@ struct rkvpss_hw_dev { bool is_single; bool is_dma_contig; bool is_shutdown; + bool is_suspend; }; #define RKVPSS_ZME_TAP_COE(x, y) (((x) & 0x3ff) | (((y) & 0x3ff) << 16)) @@ -67,4 +69,6 @@ void rkvpss_hw_write(struct rkvpss_hw_dev *hw_dev, u32 reg, u32 val); u32 rkvpss_hw_read(struct rkvpss_hw_dev *hw_dev, u32 reg); void rkvpss_hw_set_bits(struct rkvpss_hw_dev *hw, u32 reg, u32 mask, u32 val); void rkvpss_hw_clear_bits(struct rkvpss_hw_dev *hw, u32 reg, u32 mask); +void rkvpss_hw_reg_save(struct rkvpss_hw_dev *dev); +void rkvpss_hw_reg_restore(struct rkvpss_hw_dev *dev); #endif diff --git a/drivers/media/platform/rockchip/vpss/stream.c b/drivers/media/platform/rockchip/vpss/stream.c index 97ccd297fa5b..2ebdbf3c7d09 100644 --- a/drivers/media/platform/rockchip/vpss/stream.c +++ b/drivers/media/platform/rockchip/vpss/stream.c @@ -779,8 +779,9 @@ static void rkvpss_buf_done_task(unsigned long arg) buf = list_first_entry(&local_list, struct rkvpss_buffer, queue); list_del(&buf->queue); v4l2_dbg(2, rkvpss_debug, &stream->dev->v4l2_dev, - "%s id:%d seq:%d buf:0x%x done\n", - node->vdev.name, stream->id, buf->vb.sequence, buf->dma[0]); + "%s stream:%d index:%d seq:%d buf:0x%x done\n", + node->vdev.name, stream->id, buf->vb.vb2_buf.index, + buf->vb.sequence, buf->dma[0]); vb2_buffer_done(&buf->vb.vb2_buf, stream->streaming ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR); } @@ -794,6 +795,9 @@ static void rkvpss_stream_buf_done(struct rkvpss_stream *stream, if (!stream || !buf) return; + v4l2_dbg(3, rkvpss_debug, &stream->dev->v4l2_dev, + "stream:%d\n", stream->id); + spin_lock_irqsave(&stream->vbq_lock, lock_flags); list_add_tail(&buf->queue, &stream->buf_done_list); spin_unlock_irqrestore(&stream->vbq_lock, lock_flags); @@ -807,6 +811,8 @@ static void rkvpss_frame_end(struct rkvpss_stream *stream) struct rkvpss_buffer *buf = NULL; unsigned long lock_flags = 0; + v4l2_dbg(3, rkvpss_debug, &dev->v4l2_dev, + "stream:%d\n", stream->id); spin_lock_irqsave(&stream->vbq_lock, lock_flags); if (stream->curr_buf) { buf = stream->curr_buf; @@ -906,8 +912,8 @@ static void rkvpss_buf_queue(struct vb2_buffer *vb) } v4l2_dbg(2, rkvpss_debug, &dev->v4l2_dev, - "%s stream:%d buf:0x%x\n", __func__, - stream->id, vpssbuf->dma[0]); + "%s stream:%d index:%d buf:0x%x\n", __func__, + stream->id, vb->index, vpssbuf->dma[0]); spin_lock_irqsave(&stream->vbq_lock, lock_flags); list_add_tail(&vpssbuf->queue, &stream->buf_queue); diff --git a/drivers/media/platform/rockchip/vpss/vpss.c b/drivers/media/platform/rockchip/vpss/vpss.c index 3dd809ea1448..ab5c74fc2c90 100644 --- a/drivers/media/platform/rockchip/vpss/vpss.c +++ b/drivers/media/platform/rockchip/vpss/vpss.c @@ -246,10 +246,11 @@ static int rkvpss_sof(struct rkvpss_subdev *sdev, struct rkisp_vpss_sof *info) sdev->frame_seq = info->seq; sdev->frame_timestamp = info->timestamp; dev->unite_index = info->unite_index; + dev->is_idle = false; v4l2_dbg(3, rkvpss_debug, &dev->v4l2_dev, - "%s unite_mode:%u, unite_indev:%u\n", __func__, - dev->unite_mode, dev->unite_index); + "%s unite_mode:%u, unite_indev:%u seq:%d\n", __func__, + dev->unite_mode, dev->unite_index, info->seq); rkvpss_cmsc_config(dev, !info->irq); for (i = 0; i < RKVPSS_OUTPUT_MAX; i++) { @@ -418,6 +419,10 @@ void rkvpss_check_idle(struct rkvpss_device *dev, u32 irq) dev->irq_ends = 0; rkvpss_end_notify_isp(dev); + dev->is_idle = true; + + if (dev->is_suspend) + complete(&dev->pm_suspend_wait_fe); } int rkvpss_register_subdev(struct rkvpss_device *dev, @@ -451,6 +456,7 @@ int rkvpss_register_subdev(struct rkvpss_device *dev, if (ret < 0) goto free_media; rkvpss_subdev_default_fmt(vpss_sdev); + init_completion(&dev->pm_suspend_wait_fe); return ret; free_media: media_entity_cleanup(&sd->entity); diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline.c b/drivers/media/platform/rockchip/vpss/vpss_offline.c index 0505272af651..a26cf8554c6b 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline.c +++ b/drivers/media/platform/rockchip/vpss/vpss_offline.c @@ -2069,11 +2069,16 @@ end: static long rkvpss_ofl_ioctl(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { + struct rkvpss_offline_dev *ofl = video_drvdata(file); long ret = 0; bool unite; - if (!arg) - return -EINVAL; + ofl->pm_need_wait = true; + + if (!arg) { + ret = -EINVAL; + goto out; + } switch (cmd) { case RKVPSS_CMD_MODULE_SEL: @@ -2098,6 +2103,12 @@ static long rkvpss_ofl_ioctl(struct file *file, void *fh, ret = -EFAULT; } +out: + /* notify hw suspend */ + if (ofl->hw->is_suspend) + complete(&ofl->pm_cmpl); + + ofl->pm_need_wait = false; return ret; } @@ -2201,6 +2212,8 @@ int rkvpss_register_offline(struct rkvpss_hw_dev *hw) INIT_LIST_HEAD(&ofl->cfginfo_list); mutex_init(&ofl->ofl_lock); rkvpss_offline_proc_init(ofl); + ofl->pm_need_wait = false; + init_completion(&ofl->pm_cmpl); return 0; unreg_v4l2: mutex_destroy(&ofl->apilock); diff --git a/drivers/media/platform/rockchip/vpss/vpss_offline.h b/drivers/media/platform/rockchip/vpss/vpss_offline.h index 8632e3f18b18..78b7434d6a9c 100644 --- a/drivers/media/platform/rockchip/vpss/vpss_offline.h +++ b/drivers/media/platform/rockchip/vpss/vpss_offline.h @@ -73,8 +73,10 @@ struct rkvpss_offline_dev { struct mutex ofl_lock; struct rkvpss_dev_rate dev_rate[DEV_NUM_MAX]; struct rkvpss_unite_scl_params unite_params[RKVPSS_OUTPUT_MAX]; + struct completion pm_cmpl; u32 unite_right_enlarge; bool mode_sel_en; + bool pm_need_wait; }; int rkvpss_register_offline(struct rkvpss_hw_dev *hw); From cf50c9c2e4481cde39ffd419ee6dc5a73a1c502a Mon Sep 17 00:00:00 2001 From: Yuntao Liu Date: Mon, 3 Jun 2024 16:37:50 +0100 Subject: [PATCH 6/9] BACKPORT: ARM: 9404/1: arm32: enable HAVE_LD_DEAD_CODE_DATA_ELIMINATION The current arm32 architecture does not yet support the HAVE_LD_DEAD_CODE_DATA_ELIMINATION feature. arm32 is widely used in embedded scenarios, and enabling this feature would be beneficial for reducing the size of the kernel image. In order to make this work, we keep the necessary tables by annotating them with KEEP, also it requires further changes to linker script to KEEP some tables and wildcard compiler generated sections into the right place. When using ld.lld for linking, KEEP is not recognized within the OVERLAY command, and Ard proposed a concise method to solve this problem. It boots normally with defconfig, vexpress_defconfig and tinyconfig. The size comparison of zImage is as follows: defconfig vexpress_defconfig tinyconfig 5137712 5138024 424192 no dce 5032560 4997824 298384 dce 2.0% 2.7% 29.7% shrink When using smaller config file, there is a significant reduction in the size of the zImage. We also tested this patch on a commercially available single-board computer, and the comparison is as follows: a15eb_config 2161384 no dce 2092240 dce 3.2% shrink The zImage size has been reduced by approximately 3.2%, which is 70KB on 2.1M. Change-Id: Id2c136f7c992c6699c6c576ada46bfb025378f78 Signed-off-by: Yuntao Liu Tested-by: Arnd Bergmann Reviewed-by: Arnd Bergmann Reviewed-by: Linus Walleij Signed-off-by: Russell King (Oracle) Signed-off-by: Tao Huang (cherry picked from commit ed0f941022515ff40473ea5335769a5dc2524a3f) --- arch/arm/Kconfig | 1 + arch/arm/boot/compressed/vmlinux.lds.S | 2 +- arch/arm/include/asm/vmlinux.lds.h | 2 +- arch/arm/kernel/entry-armv.S | 3 +++ arch/arm/kernel/vmlinux-xip.lds.S | 4 ++-- arch/arm/kernel/vmlinux.lds.S | 6 +++--- drivers/firmware/efi/libstub/Makefile | 4 ++++ 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 773770c47e37..dd68422c2aa1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -108,6 +108,7 @@ config ARM select HAVE_KERNEL_XZ select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M select HAVE_KRETPROBES if HAVE_KPROBES + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI select HAVE_OPTPROBES if !THUMB2_KERNEL diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S index 3fcb3e62dc56..d411abd4310e 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.S +++ b/arch/arm/boot/compressed/vmlinux.lds.S @@ -125,7 +125,7 @@ SECTIONS . = BSS_START; __bss_start = .; - .bss : { *(.bss) } + .bss : { *(.bss .bss.*) } _end = .; . = ALIGN(8); /* the stack must be 64-bit aligned */ diff --git a/arch/arm/include/asm/vmlinux.lds.h b/arch/arm/include/asm/vmlinux.lds.h index fad45c884e98..fa031135710f 100644 --- a/arch/arm/include/asm/vmlinux.lds.h +++ b/arch/arm/include/asm/vmlinux.lds.h @@ -42,7 +42,7 @@ #define PROC_INFO \ . = ALIGN(4); \ __proc_info_begin = .; \ - *(.proc.info.init) \ + KEEP(*(.proc.info.init)) \ __proc_info_end = .; #define IDMAP_TEXT \ diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index c39303e5c234..fe3a24fe6a00 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -1297,6 +1297,7 @@ vector_addrexcptn: .globl vector_fiq .section .vectors, "ax", %progbits + .reloc .text, R_ARM_NONE, . W(b) vector_rst W(b) vector_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_swi ) @@ -1310,6 +1311,7 @@ THUMB( .reloc ., R_ARM_THM_PC12, .L__vector_swi ) #ifdef CONFIG_HARDEN_BRANCH_HISTORY .section .vectors.bhb.loop8, "ax", %progbits + .reloc .text, R_ARM_NONE, . W(b) vector_rst W(b) vector_bhb_loop8_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_bhb_loop8_swi ) @@ -1322,6 +1324,7 @@ THUMB( .reloc ., R_ARM_THM_PC12, .L__vector_bhb_loop8_swi ) W(b) vector_bhb_loop8_fiq .section .vectors.bhb.bpiall, "ax", %progbits + .reloc .text, R_ARM_NONE, . W(b) vector_rst W(b) vector_bhb_bpiall_und ARM( .reloc ., R_ARM_LDR_PC_G0, .L__vector_bhb_bpiall_swi ) diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 76678732c60d..8ab517f26c22 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -64,7 +64,7 @@ SECTIONS . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; - ARM_MMU_KEEP(*(__ex_table)) + ARM_MMU_KEEP(KEEP(*(__ex_table))) __stop___ex_table = .; } @@ -84,7 +84,7 @@ SECTIONS } .init.arch.info : { __arch_info_begin = .; - *(.arch.info.init) + KEEP(*(.arch.info.init)) __arch_info_end = .; } .init.tagtable : { diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index aa12b65a7fd6..392cb962a40c 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -75,7 +75,7 @@ SECTIONS . = ALIGN(4); __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { __start___ex_table = .; - ARM_MMU_KEEP(*(__ex_table)) + ARM_MMU_KEEP(KEEP(*(__ex_table))) __stop___ex_table = .; } @@ -100,7 +100,7 @@ SECTIONS } .init.arch.info : { __arch_info_begin = .; - *(.arch.info.init) + KEEP(*(.arch.info.init)) __arch_info_end = .; } .init.tagtable : { @@ -117,7 +117,7 @@ SECTIONS #endif .init.pv_table : { __pv_table_begin = .; - *(.pv_table) + KEEP(*(.pv_table)) __pv_table_end = .; } diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 473ef18421db..850fcf1a5b88 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -53,6 +53,10 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_CFI), $(KBUILD_CFLAGS)) # disable LTO KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS)) +# The .data section would be renamed to .data.efistub, therefore, remove +# `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL +KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL)) + GCOV_PROFILE := n # Sanitizer runtimes are unavailable and cannot be linked here. KASAN_SANITIZE := n From 57ed7b017f4e4ff36b40f5f334d6cb65c223b257 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Wed, 21 Aug 2024 12:08:32 +0800 Subject: [PATCH 7/9] ARM: rk3506_defconfig: Enable CONFIG_LD_DEAD_CODE_DATA_ELIMINATION before: text data bss dec hex filename 4919662 2289888 114376 7323926 6fc116 vmlinux after: text data bss dec hex filename 4817210 2235024 110208 7162442 6d4a4a vmlinux Change-Id: I66ff62436bafa48242cec573901195220e84fbac Signed-off-by: Tao Huang --- arch/arm/configs/rk3506_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/rk3506_defconfig b/arch/arm/configs/rk3506_defconfig index 313d7fc4292e..06dc4ccd234e 100644 --- a/arch/arm/configs/rk3506_defconfig +++ b/arch/arm/configs/rk3506_defconfig @@ -16,6 +16,7 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set # CONFIG_RD_ZSTD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y # CONFIG_BUG is not set # CONFIG_ELF_CORE is not set # CONFIG_BASE_FULL is not set From 9e3a86e865525e14b279fe5463a72493ef0066e4 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Tue, 12 Mar 2024 16:38:46 +0800 Subject: [PATCH 8/9] PCI: rockchip: dw: Add gpio based hotplug [1]check we do have two devices plugged: console:/ # lspci 00:00.0 Class 0604: Device 1d87:3576 (rev 01) 01:00.0 Class 0108: Device 15b7:5017 (rev 01) 20:00.0 Class 0604: Device 1d87:3576 (rev 01) 21:00.0 Class 0108: Device 1d97:2269 (rev 03) [2]Unplug two NVMe devices: [ 35.680289][ T134] pcieport 0000:00:00.0: Hot-UnPlug Event [ 35.680361][ T134] pcieport 0000:00:00.0: Power Status = 1 [ 35.827183][ T134] rk-pcie 2a200000.pcie: rk_pcie_slot_disable [ 35.827303][ T134] pcieport 0000:00:00.0: Hot-UnPlug Event [ 35.827323][ T134] pcieport 0000:00:00.0: Power Status = 0 [ 35.827334][ T134] pcieport 0000:00:00.0: Device is already removed [ 35.827343][ T134] rk-pcie 2a200000.pcie: rk_pcie_slot_disable [ 38.201153][ T138] pcieport 0000:20:00.0: Hot-UnPlug Event [ 38.201209][ T138] pcieport 0000:20:00.0: Power Status = 1 [ 43.239050][ T138] nvme nvme1: Device shutdown incomplete; abort shutdown [ 46.204721][ T138] rk-pcie 2a210000.pcie: rk_pcie_slot_disable [3]They are removed: console:/ # lspci 00:00.0 Class 0604: Device 1d87:3576 (rev 01) 20:00.0 Class 0604: Device 1d87:3576 (rev 01) [4]Then we plug them again: console:/ # [ 52.435494][ T134] pcieport 0000:00:00.0: Hot-Plug Event [ 52.435583][ T134] pcieport 0000:00:00.0: Power Status = 0 [ 52.435610][ T134] rk-pcie 2a200000.pcie: rk_pcie_slot_enable [ 52.648277][ T134] rk-pcie 2a200000.pcie: PCIe Linking... LTSSM is 0x3 [ 52.735030][ T134] rk-pcie 2a200000.pcie: PCIe Link up, LTSSM is 0x30011 [ 52.777740][ T134] pcieport 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring [ 52.777955][ T134] pci 0000:01:00.0: [1d97:2269] type 00 class 0x010802 [ 52.778072][ T134] pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x00003fff 64bit] [ 52.778977][ T134] pci 0000:01:00.0: 2.000 Gb/s available PCIe bandwidth, limited by 2.5 GT/s PCIe x1 link at 0000:00:00.0 (capable of 63.012 Gb/s with 16.0 GT/s PCIe x4 link) [ 52.791130][ T134] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01 [ 52.791229][ T134] pci 0000:01:00.0: BAR 0: assigned [mem 0x20200000-0x20203fff 64bit] [ 52.792548][ T134] nvme nvme0: pci function 0000:01:00.0 [ 52.792970][ T137] nvme 0000:01:00.0: enabling device (0000 -> 0002) [ 52.820084][ T137] nvme nvme0: allocated 64 MiB host memory buffer. [ 52.834777][ T137] nvme nvme0: 6/0/0 default/read/poll queues [ 52.840583][ T84] nvme nvme0: Ignoring bogus Namespace Identifiers [ 56.454008][ T138] pcieport 0000:20:00.0: Hot-Plug Event [ 56.454062][ T138] pcieport 0000:20:00.0: Power Status = 0 [ 56.454082][ T138] rk-pcie 2a210000.pcie: rk_pcie_slot_enable [ 56.668151][ T138] rk-pcie 2a210000.pcie: PCIe Linking... LTSSM is 0x3 [ 56.755033][ T138] rk-pcie 2a210000.pcie: PCIe Link up, LTSSM is 0x30011 [ 56.771544][ T138] pcieport 0000:20:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring [ 56.771739][ T138] pci 0000:21:00.0: [15b7:5017] type 00 class 0x010802 [ 56.771857][ T138] pci 0000:21:00.0: reg 0x10: [mem 0x00000000-0x00003fff 64bit] [ 56.772592][ T138] pci 0000:21:00.0: 2.000 Gb/s available PCIe bandwidth, limited by 2.5 GT/s PCIe x1 link at 0000:20:00.0 (capable of 63.012 Gb/s with 16.0 GT/s PCIe x4 link) [ 56.783092][ T138] pci_bus 0000:21: busn_res: [bus 21] end is updated to 21 [ 56.783156][ T138] pci 0000:21:00.0: BAR 0: assigned [mem 0x21200000-0x21203fff 64bit] [ 56.784098][ T138] nvme nvme1: pci function 0000:21:00.0 [ 56.784551][ T84] nvme 0000:21:00.0: enabling device (0000 -> 0002) [ 56.795146][ T84] nvme nvme1: allocated 32 MiB host memory buffer. [ 56.813480][ T84] nvme nvme1: 6/0/0 default/read/poll queues [5]Accessing them to check the devices: console:/ # lspci 00:00.0 Class 0604: Device 1d87:3576 (rev 01) 01:00.0 Class 0108: Device 15b7:5017 (rev 01) 20:00.0 Class 0604: Device 1d87:3576 (rev 01) 21:00.0 Class 0108: Device 1d97:2269 (rev 03) console:/ # [ 66.181110][ T534] healthd: battery l=50 v=3300 t=2.6 h=2 st=3 c=-1600 fc=100 chg=au dd if=/dev/block/nvme0n1 of=/dev/null bs=1M count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (0.9 G) copied, 3.322 s, 301 M/s console:/ # dd if=/dev/block/nvme1n1 of=/dev/null bs=1M count=1000 < 1000+0 records in 1000+0 records out 1048576000 bytes (0.9 G) copied, 3.724 s, 269 M/s Signed-off-by: Shawn Lin Change-Id: I49c57755d11cc43bbf7cf9eb23542f5e1e11aaa3 --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index fedd5cf51802..c01dfedd7dd4 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -26,6 +26,7 @@ #include "pcie-designware.h" #include "../rockchip-pcie-dma.h" #include "pcie-dw-dmatest.h" +#include "../../hotplug/gpiophp.h" #define RK_PCIE_DBG 0 @@ -131,6 +132,9 @@ struct rk_pcie { bool is_signal_test; bool bifurcation; bool supports_clkreq; + bool slot_pluggable; + struct gpio_hotplug_slot hp_slot; + bool hp_no_link; struct regulator *vpcie3v3; struct irq_domain *irq_domain; raw_spinlock_t intx_lock; @@ -280,7 +284,7 @@ static int rk_pcie_establish_link(struct dw_pcie *pci) * we still need to reset link as we need to remove all resource info * from devices, for instance BAR, as it wasn't assigned by kernel. */ - if (dw_pcie_link_up(pci)) { + if (dw_pcie_link_up(pci) && !rk_pcie->hp_no_link) { dev_err(pci->dev, "link is already up\n"); return 0; } @@ -346,6 +350,8 @@ static int rk_pcie_establish_link(struct dw_pcie *pci) dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n", rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); rk_pcie_debug_dump(rk_pcie); + if (rk_pcie->slot_pluggable) + rk_pcie->hp_no_link = false; return 0; } } @@ -372,7 +378,12 @@ static int rk_pcie_establish_link(struct dw_pcie *pci) } } - return rk_pcie->is_signal_test == true ? 0 : -EINVAL; + if (rk_pcie->slot_pluggable) { + rk_pcie->hp_no_link = true; + return 0; + } else { + return rk_pcie->is_signal_test == true ? 0 : -EINVAL; + } } static bool rk_pcie_udma_enabled(struct rk_pcie *rk_pcie) @@ -1070,6 +1081,40 @@ remove: return -ENOMEM; } +static int rk_pcie_slot_enable(struct gpio_hotplug_slot *slot) +{ + struct rk_pcie *rk_pcie = container_of(slot, struct rk_pcie, hp_slot); + int ret; + + dev_info(rk_pcie->pci->dev, "%s\n", __func__); + rk_pcie->hp_no_link = true; + rk_pcie_enable_power(rk_pcie); + rk_pcie_fast_link_setup(rk_pcie); + ret = rk_pcie_establish_link(rk_pcie->pci); + if (ret) + dev_err(rk_pcie->pci->dev, "fail to enable slot\n"); + + return ret; +} + +static int rk_pcie_slot_disable(struct gpio_hotplug_slot *slot) +{ + struct rk_pcie *rk_pcie = container_of(slot, struct rk_pcie, hp_slot); + + dev_info(rk_pcie->pci->dev, "%s\n", __func__); + rk_pcie->hp_no_link = true; + rk_pcie_disable_ltssm(rk_pcie); + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); + rk_pcie_disable_power(rk_pcie); + + return 0; +} + +static const struct gpio_hotplug_slot_plat_ops rk_pcie_gpio_hp_plat_ops = { + .enable = rk_pcie_slot_enable, + .disable = rk_pcie_slot_disable, +}; + static int rk_pcie_really_probe(void *p) { struct platform_device *pdev = p; @@ -1128,6 +1173,12 @@ static int rk_pcie_really_probe(void *p) rk_pcie->supports_clkreq = device_property_read_bool(dev, "supports-clkreq"); + if (device_property_read_bool(dev, "hotplug-gpios") || + device_property_read_bool(dev, "hotplug-gpio")) { + rk_pcie->slot_pluggable = true; + dev_info(dev, "support hotplug-gpios!\n"); + } + retry_regulator: /* DON'T MOVE ME: must be enable before phy init */ rk_pcie->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); @@ -1257,9 +1308,23 @@ retry_regulator: if (rk_pcie->is_signal_test == true) return 0; - if (ret) + if (ret && !rk_pcie->slot_pluggable) goto remove_rst_wq; + if (rk_pcie->slot_pluggable) { + rk_pcie->hp_slot.plat_ops = &rk_pcie_gpio_hp_plat_ops; + rk_pcie->hp_slot.np = rk_pcie->pci->dev->of_node; + rk_pcie->hp_slot.slot_nr = rk_pcie->pci->pp.bridge->busnr; + rk_pcie->hp_slot.pdev = pci_get_slot(rk_pcie->pci->pp.bridge->bus, PCI_DEVFN(0, 0)); + + ret = register_gpio_hotplug_slot(&rk_pcie->hp_slot); + if (ret < 0) + dev_warn(dev, "Failed to register ops for GPIO Hot-Plug controller: %d\n", + ret); + /* Set debounce to 200ms for safe if possible */ + gpiod_set_debounce(rk_pcie->hp_slot.gpiod, 200); + } + ret = rk_pcie_init_dma_trx(rk_pcie); if (ret) { dev_err(dev, "failed to add dma extension\n"); From 866b86dd10b13dfe38eeb440c20d3dfa0e7c1397 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Wed, 13 Mar 2024 11:13:49 +0800 Subject: [PATCH 9/9] arm64: configs: rockchip_linux_defconfig: Add GPIO based HP for PCIe Signed-off-by: Shawn Lin Change-Id: If22e9b2532c092a48e4a5ec2c91d86aa0b68848c --- arch/arm64/configs/rockchip_linux_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/rockchip_linux_defconfig b/arch/arm64/configs/rockchip_linux_defconfig index f079f125c510..895097420356 100644 --- a/arch/arm64/configs/rockchip_linux_defconfig +++ b/arch/arm64/configs/rockchip_linux_defconfig @@ -132,6 +132,8 @@ CONFIG_PCIEPORTBUS=y CONFIG_PCIEASPM_POWERSAVE=y CONFIG_PCIEASPM_EXT=y # CONFIG_VGA_ARB is not set +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_GPIO=y CONFIG_PCIE_ROCKCHIP_HOST=y CONFIG_PCIE_DW_ROCKCHIP=y CONFIG_DEVTMPFS=y