Merge commit '866b86dd10b13dfe38eeb440c20d3dfa0e7c1397'

* commit '866b86dd10b13dfe38eeb440c20d3dfa0e7c1397':
  arm64: configs: rockchip_linux_defconfig: Add GPIO based HP for PCIe
  PCI: rockchip: dw: Add gpio based hotplug
  ARM: rk3506_defconfig: Enable CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
  BACKPORT: ARM: 9404/1: arm32: enable HAVE_LD_DEAD_CODE_DATA_ELIMINATION
  media: rockchip: vpss: support suspend and resume
  media: rockchip: vpss: offline add some debug info
  drm/rockchip: fix some csc parameters error
  ARM: rk3506_defconfig: Disable more unused NET_VENDOR
  media: i2c: rk628: reduce power consumption when there is no hdmi in

Change-Id: I1c6686c648dda72859b325ea426e5bcbc949d49b
This commit is contained in:
Tao Huang
2024-08-21 19:47:18 +08:00
22 changed files with 608 additions and 192 deletions

View File

@@ -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

View File

@@ -125,7 +125,7 @@ SECTIONS
. = BSS_START;
__bss_start = .;
.bss : { *(.bss) }
.bss : { *(.bss .bss.*) }
_end = .;
. = ALIGN(8); /* the stack must be 64-bit aligned */

View File

@@ -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
@@ -102,17 +103,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 +143,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

View File

@@ -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 \

View File

@@ -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 )

View File

@@ -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 : {

View File

@@ -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 = .;
}

View File

@@ -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

View File

@@ -54,6 +54,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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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));

View File

@@ -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);

View File

@@ -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)
@@ -323,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:
@@ -351,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;
@@ -362,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;
@@ -373,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 = {

View File

@@ -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);

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}
@@ -1999,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:
@@ -2028,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;
}
@@ -2131,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);

View File

@@ -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);

View File

@@ -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");