diff --git a/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi b/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi index 2fbddb1879a8..bd3d8fe80a0b 100644 --- a/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi +++ b/arch/arm/boot/dts/rv1106-evb-dual-cam.dtsi @@ -7,6 +7,8 @@ * sc4336 0x30 lane2~3(dphy2) * v1.1.0 gc2053 0x37 lane0~1(dphy1) * gc2053 0x3f lane2~3(dphy2) + * v1.2.0 sc301iot 0x30 lane0~1(dphy1) + * sc301iot 0x32 lane2~3(dphy2) */ &csi2_dphy_hw { @@ -36,6 +38,12 @@ remote-endpoint = <&gc2053_out>; data-lanes = <1 2>; }; + + csi_dphy_input4: endpoint@3 { + reg = <3>; + remote-endpoint = <&sc301iot_out>; + data-lanes = <1 2>; + }; }; port@1 { @@ -74,6 +82,12 @@ remote-endpoint = <&gc2053_1_out>; data-lanes = <1 2>; }; + + csi_dphy_input5: endpoint@3 { + reg = <3>; + remote-endpoint = <&sc301iot_1_out>; + data-lanes = <1 2>; + }; }; port@1 { @@ -139,6 +153,28 @@ }; }; + sc301iot: sc301iot@30 { + compatible = "smartsens,sc301iot"; + status = "okay"; + reg = <0x30>; + clocks = <&cru MCLK_REF_MIPI0>; + clock-names = "xvclk"; + reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_refclk_out0>; + rockchip,camera-module-index = <0>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2349-PC1"; + rockchip,camera-module-lens-name = "65IRC-F20"; + port { + sc301iot_out: endpoint { + remote-endpoint = <&csi_dphy_input4>; + data-lanes = <1 2>; + }; + }; + }; + sc4336: sc4336@30 { compatible = "smartsens,sc4336"; status = "okay"; @@ -182,6 +218,28 @@ }; }; }; + + sc301iot_1: sc301iot_1@32 { + compatible = "smartsens,sc301iot"; + status = "okay"; + reg = <0x32>; + clocks = <&cru MCLK_REF_MIPI1>; + clock-names = "xvclk"; + reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&mipi_refclk_out1>; + rockchip,camera-module-index = <1>; + rockchip,camera-module-facing = "back"; + rockchip,camera-module-name = "CMK-OT2349-PC1"; + rockchip,camera-module-lens-name = "65IRC-F20"; + port { + sc301iot_1_out: endpoint { + remote-endpoint = <&csi_dphy_input5>; + data-lanes = <1 2>; + }; + }; + }; }; &mipi0_csi2 { diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi index 119c84431d1f..30c2eb88a85d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi @@ -281,7 +281,7 @@ route_rgb: route-rgb { status = "disabled"; logo,uboot = "logo.bmp"; - /* logo,kernel = "logo_kernel.bmp"; */ + logo,kernel = "logo_kernel.bmp"; logo,mode = "center"; charge_logo,mode = "center"; connect = <&vop_out_rgb>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-excavator-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-excavator-sapphire.dtsi index e17867f04d7b..c12a87057876 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-excavator-sapphire.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-excavator-sapphire.dtsi @@ -10,23 +10,34 @@ compatible = "rockchip,rk3399-sapphire-excavator", "rockchip,rk3399"; rt5651_sound: rt5651-sound { - compatible = "simple-audio-card"; - simple-audio-card,format = "i2s"; - simple-audio-card,name = "realtek,rt5651-codec"; - simple-audio-card,mclk-fs = <256>; - simple-audio-card,widgets = - "Microphone", "Mic Jack", - "Headphone", "Headphone Jack"; - simple-audio-card,routing = - "Mic Jack", "MICBIAS1", - "IN1P", "Mic Jack", - "Headphone Jack", "HPOL", - "Headphone Jack", "HPOR"; - simple-audio-card,cpu { - sound-dai = <&i2s0>; - }; - simple-audio-card,codec { - sound-dai = <&rt5651>; + status = "okay"; + compatible = "rockchip,multicodecs-card"; + rockchip,card-name = "realtek,rt5651-codec"; + keyup-threshold-microvolt = <1800000>; + poll-interval = <100>; + spk-con-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>; + hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_HIGH>; + rockchip,format = "i2s"; + rockchip,mclk-fs = <256>; + rockchip,cpu = <&i2s0>; + rockchip,codec = <&rt5651>; + rockchip,audio-routing = + "Headphone", "HPOL", + "Headphone", "HPOR", + "Speaker", "HPOL", + "Speaker", "HPOR", + "Headphone", "Headphone Power", + "Headphone", "Headphone Power", + "Speaker", "Speaker Power", + "Speaker", "Speaker Power", + "IN1P", "Main Mic", + "IN2P", "Headset Mic", + "IN2N", "Headset Mic"; + "Headset Mic", "micbias1"; + play-pause-key { + label = "playpause"; + linux,code = ; + press-threshold-microvolt = <2000>; }; }; @@ -152,8 +163,6 @@ clock-names = "mclk"; pinctrl-names = "default"; pinctrl-0 = <&i2s_8ch_mclk>; - spk-con-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>; - hp-det-gpio = <&gpio4 28 GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-adsp-audio-s66.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-adsp-audio-s66.dtsi index 5609397a2442..18d41026b68b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-vehicle-adsp-audio-s66.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-vehicle-adsp-audio-s66.dtsi @@ -71,6 +71,8 @@ assigned-clock-parents = <&mclkin_i2s3>; pinctrl-0 = <&i2s3_sdi &i2s3_sdo + &i2s3_lrck + &i2s3_sclk &i2s3_mclk>; status = "okay"; }; diff --git a/arch/arm64/configs/rk3308bs_mipi_display.config b/arch/arm64/configs/rk3308bs_mipi_display.config new file mode 100644 index 000000000000..24498f0aed59 --- /dev/null +++ b/arch/arm64/configs/rk3308bs_mipi_display.config @@ -0,0 +1,128 @@ +CONFIG_CMA=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_MFD_RK618=y +CONFIG_CLK_RK618=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +# CONFIG_CMA_INACTIVE is not set +CONFIG_CMA_SIZE_MBYTES=16 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_COMMON_CLK_ROCKCHIP_REGMAP=y +CONFIG_CONTIG_ALLOC=y +CONFIG_DMA_CMA=y +# CONFIG_DMA_PERNUMA_CMA is not set +CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_PANEL_ASUS_Z00T_TM5P5_NT35596 is not set +# CONFIG_DRM_PANEL_BOE_HIMAX8279D is not set +# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set +# CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set +# CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02 is not set +# CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set +# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04 is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W is not set +# CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829 is not set +# CONFIG_DRM_PANEL_MANTIX_MLAF057WE51 is not set +# CONFIG_DRM_PANEL_NOVATEK_NT35510 is not set +# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set +# CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM67191 is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_RONBO_RB070D30 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6D16D0 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7701 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7703 is not set +# CONFIG_DRM_PANEL_SONY_ACX424AKP is not set +# CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA is not set +# CONFIG_DRM_PANEL_VISIONOX_RM69299 is not set +# CONFIG_DRM_PANEL_XINPENG_XPP055C272 is not set +CONFIG_DRM_ROCKCHIP_RK618=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_RK628_MISC is not set +# CONFIG_RK_CMA_PROCFS is not set +# CONFIG_SND_SOC_ROCKCHIP_I2S_TDM_MULTI_LANES is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ADC is not set +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CY8CTMA140 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELAN5515 is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_GSL3673 is not set +# CONFIG_TOUCHSCREEN_GSL3673_800X1280 is not set +# CONFIG_TOUCHSCREEN_GSLX680_PAD is not set +CONFIG_TOUCHSCREEN_GT1X=y +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_IQS5XX is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +CONFIG_TOUCHSCREEN_PROPERTIES=y +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_STMFTS is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ZINITIX is not set diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 26a989124cac..99c758ff264d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -222,6 +222,7 @@ struct dw_hdmi_phy_data { struct dw_hdmi_qp { struct drm_connector connector; struct drm_bridge bridge; + struct drm_bridge *next_bridge; struct drm_panel *panel; struct platform_device *hdcp_dev; struct platform_device *audio; @@ -257,6 +258,7 @@ struct dw_hdmi_qp { bool cec_enable; bool allm_enable; bool support_hdmi; + bool skip_connector; int force_output; int vp_id; int old_vp_id; @@ -2058,6 +2060,9 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) if (hdmi->panel) return connector_status_connected; + if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_DETECT) + return drm_bridge_detect(hdmi->next_bridge); + if (hdmi->plat_data->left) secondary = hdmi->plat_data->left; else if (hdmi->plat_data->right) @@ -2137,9 +2142,21 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) void *data = hdmi->plat_data->phy_data; int i, ret = 0; + if (hdmi->plat_data->right && hdmi->plat_data->right->next_bridge) { + struct drm_bridge *bridge = hdmi->plat_data->right->next_bridge; + + if (bridge->ops & DRM_BRIDGE_OP_MODES) { + if (!drm_bridge_get_modes(bridge, connector)) + return 0; + } + } + if (hdmi->panel) return drm_panel_get_modes(hdmi->panel, connector); + if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_MODES) + return drm_bridge_get_modes(hdmi->next_bridge, connector); + if (!hdmi->ddc) return 0; @@ -2226,7 +2243,6 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) dev_info(hdmi->dev, "failed to get edid\n"); } - dw_hdmi_qp_check_output_type_changed(hdmi); return ret; } @@ -2548,7 +2564,8 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector, } if (check_hdr_color_change(old_state, new_state, hdmi) || hdmi->logo_plug_out || - dw_hdmi_color_changed(connector, state)) { + dw_hdmi_color_changed(connector, state) || + dw_hdmi_qp_check_output_type_changed(hdmi)) { u32 mtmdsclk; crtc_state = drm_atomic_get_crtc_state(state, crtc); @@ -2610,17 +2627,6 @@ static void dw_hdmi_connector_atomic_commit(struct drm_connector *connector, void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val) { hdmi->force_output = val; - - if (!dw_hdmi_qp_check_output_type_changed(hdmi)) - return; - - if (hdmi->disabled) - return; - - if (!hdmi->sink_is_hdmi) - hdmi_modb(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0); - else - hdmi_modb(hdmi, 0, OPMODE_DVI, LINK_CONFIG0); } EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_output_type); @@ -2684,13 +2690,31 @@ static int dw_hdmi_qp_bridge_attach(struct drm_bridge *bridge, struct drm_connector *connector = &hdmi->connector; struct cec_connector_info conn_info; struct cec_notifier *notifier; + bool skip_connector = false; - if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) + if (hdmi->next_bridge) { + struct drm_bridge *next_bridge = hdmi->next_bridge; + int ret; + + ret = drm_bridge_attach(bridge->encoder, next_bridge, bridge, + next_bridge->ops & DRM_BRIDGE_OP_MODES ? + DRM_BRIDGE_ATTACH_NO_CONNECTOR : 0); + if (ret) { + DRM_ERROR("failed to attach next bridge: %d\n", ret); + return ret; + } + + skip_connector = !(next_bridge->ops & DRM_BRIDGE_OP_MODES); + } + + hdmi->skip_connector = skip_connector; + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR || skip_connector) return 0; connector->interlace_allowed = 1; connector->polled = DRM_CONNECTOR_POLL_HPD; - + if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_DETECT) + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs, @@ -2730,9 +2754,19 @@ dw_hdmi_qp_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode) { + struct dw_hdmi_qp *hdmi = bridge->driver_private; + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; + if (mode->clock <= 25000) return MODE_CLOCK_RANGE; + if (!hdmi->sink_is_hdmi && mode->clock > 340000) + return MODE_BAD; + + if (pdata->mode_valid) + return pdata->mode_valid(NULL, pdata->priv_data, info, + mode); + return MODE_OK; } @@ -3354,10 +3388,11 @@ __dw_hdmi_probe(struct platform_device *pdev, struct dw_hdmi_qp_cec_data cec; struct resource *iores = NULL; struct drm_panel *panel = NULL; + struct drm_bridge *bridge = NULL; int irq; int ret; - ret = drm_of_find_panel_or_bridge(np, 1, -1, &panel, NULL); + ret = drm_of_find_panel_or_bridge(np, 1, -1, &panel, &bridge); if (ret < 0 && ret != -ENODEV) return ERR_PTR(ret); @@ -3366,6 +3401,7 @@ __dw_hdmi_probe(struct platform_device *pdev, return ERR_PTR(-ENOMEM); hdmi->panel = panel; + hdmi->next_bridge = bridge; hdmi->connector.stereo_allowed = 1; hdmi->plat_data = plat_data; hdmi->dev = dev; @@ -3648,6 +3684,10 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev, } plat_data->connector = &hdmi->connector; + if (hdmi->skip_connector && hdmi->next_bridge) + plat_data->bridge = hdmi->next_bridge; + else + plat_data->bridge = NULL; } if (plat_data->split_mode && !hdmi->plat_data->first_screen) { diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 15616b5f1549..9bfc9517efa2 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -1610,14 +1610,6 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, struct drm_crtc *crtc; struct rockchip_hdmi *hdmi; - /* - * Pixel clocks we support are always < 2GHz and so fit in an - * int. We should make sure source rate does too so we don't get - * overflow when we multiply by 1000. - */ - if (mode->clock > INT_MAX / 1000) - return MODE_BAD; - if (!encoder) { const struct drm_connector_helper_funcs *funcs; @@ -1634,6 +1626,21 @@ dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, hdmi = to_rockchip_hdmi(encoder); + if (hdmi->is_hdmi_qp) { + if (!hdmi->enable_gpio && mode->clock > 600000) + return MODE_BAD; + + return MODE_OK; + } + + /* + * Pixel clocks we support are always < 2GHz and so fit in an + * int. We should make sure source rate does too so we don't get + * overflow when we multiply by 1000. + */ + if (mode->clock > INT_MAX / 1000) + return MODE_BAD; + /* * If sink max TMDS clock < 340MHz, we should check the mode pixel * clock > 340MHz is YCbCr420 or not and whether the platform supports @@ -2050,11 +2057,6 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, else color_depth = 8; - if (!sink_is_hdmi) { - *color_format = RK_IF_FORMAT_RGB; - color_depth = 8; - } - *eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; if (conn_state->hdr_output_metadata) { hdr_metadata = (struct hdr_output_metadata *) @@ -2104,6 +2106,11 @@ dw_hdmi_rockchip_select_output(struct drm_connector_state *conn_state, if (hdmi->is_hdmi_qp && mode.clock >= 600000) *color_format = RK_IF_FORMAT_YCBCR420; + if (!sink_is_hdmi) { + *color_format = RK_IF_FORMAT_RGB; + color_depth = 8; + } + if (*color_format == RK_IF_FORMAT_YCBCR422 || color_depth == 8) tmdsclock = pixclock; else @@ -3382,6 +3389,7 @@ struct rockchip_hdmi_chip_data rk3588_hdmi_chip_data = { }; static const struct dw_hdmi_plat_data rk3588_hdmi_drv_data = { + .mode_valid = dw_hdmi_rockchip_mode_valid, .phy_data = &rk3588_hdmi_chip_data, .qp_phy_ops = &rk3588_hdmi_phy_ops, .phy_name = "samsung_hdptx_phy", @@ -3700,7 +3708,20 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, drm_encoder_cleanup(&hdmi->encoder); } - if (plat_data->connector) { + if (plat_data->bridge) { + struct drm_connector *connector = NULL; + struct list_head *connector_list = + &plat_data->bridge->dev->mode_config.connector_list; + + list_for_each_entry(connector, connector_list, head) + if (drm_connector_has_possible_encoder(connector, + &hdmi->encoder)) + break; + + hdmi->sub_dev.connector = connector; + hdmi->sub_dev.of_node = dev->of_node; + rockchip_drm_register_sub_dev(&hdmi->sub_dev); + } else if (plat_data->connector) { hdmi->sub_dev.connector = plat_data->connector; hdmi->sub_dev.loader_protect = dw_hdmi_rockchip_encoder_loader_protect; if (secondary && device_property_read_bool(secondary->dev, "split-mode")) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index e75b932a10e7..6ee5611139a2 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -4655,6 +4655,7 @@ static int rkcif_create_dummy_buf(struct rkcif_stream *stream) struct rkcif_dummy_buffer *dummy_buf = &hw->dummy_buf; struct rkcif_device *tmp_dev = NULL; struct v4l2_subdev_frame_interval_enum fie; + struct v4l2_subdev_format fmt; u32 max_size = 0; u32 size = 0; int ret = 0; @@ -4689,6 +4690,21 @@ static int rkcif_create_dummy_buf(struct rkcif_stream *stream) continue; } } + + if (max_size == 0 && dev->terminal_sensor.sd) { + fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(dev->terminal_sensor.sd, + pad, get_fmt, NULL, &fmt); + if (!ret) { + if (fmt.format.code == MEDIA_BUS_FMT_RGB888_1X24) + size = fmt.format.width * fmt.format.height * 3; + else + size = fmt.format.width * fmt.format.height * 2; + if (size > max_size) + max_size = size; + } + } + dummy_buf->size = max_size; dummy_buf->is_need_vaddr = true; diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 5975bdfba68e..d2cc1bdf6cf6 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -171,7 +171,7 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); - unsigned long period, duty; + unsigned long period, duty, delay_ns; unsigned long flags; u64 div; u32 ctrl; @@ -193,11 +193,13 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, div = (u64)pc->clk_rate * state->duty_cycle; duty = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC); + if (pc->data->supports_lock) { + div = (u64)10 * NSEC_PER_SEC * dclk_div * pc->data->prescaler; + delay_ns = DIV_ROUND_UP_ULL(div, pc->clk_rate); + } + local_irq_save(flags); - /* - * Lock the period and duty of previous configuration, then - * change the duty and period, that would not be effective. - */ + ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); if (pc->data->vop_pwm) { if (pc->vop_pwm_en) @@ -255,6 +257,10 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } #endif + /* + * Lock the period and duty of previous configuration, then + * change the duty and period, that would not be effective. + */ if (pc->data->supports_lock) { ctrl |= PWM_LOCK_EN; writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); @@ -272,12 +278,14 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } /* - * Unlock and set polarity at the same time, - * the configuration of duty, period and polarity - * would be effective together at next period. + * Unlock and set polarity at the same time, the configuration of duty, + * period and polarity would be effective together at next period. It + * takes 10 dclk cycles to make sure lock works before unlocking. */ - if (pc->data->supports_lock) + if (pc->data->supports_lock) { ctrl &= ~PWM_LOCK_EN; + ndelay(delay_ns); + } writel(ctrl, pc->base + pc->data->regs.ctrl); local_irq_restore(flags); diff --git a/drivers/video/rockchip/vehicle/vehicle_dev.c b/drivers/video/rockchip/vehicle/vehicle_dev.c index 7e9ece0ed9dc..29c0f67111ed 100644 --- a/drivers/video/rockchip/vehicle/vehicle_dev.c +++ b/drivers/video/rockchip/vehicle/vehicle_dev.c @@ -106,12 +106,11 @@ static int __init vechile_module_init(void) return 0; } -static void __exit vechile_module_exit(void) +void vechile_module_exit(void) { misc_deregister(&vechile_dev); } module_init(vechile_module_init); -module_exit(vechile_module_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/video/rockchip/vehicle/vehicle_main.c b/drivers/video/rockchip/vehicle/vehicle_main.c index 8c98dd7aa4d6..a3ffdd1e3f8a 100644 --- a/drivers/video/rockchip/vehicle/vehicle_main.c +++ b/drivers/video/rockchip/vehicle/vehicle_main.c @@ -487,6 +487,7 @@ VEHICLE_EXIT: #endif // msleep(1000); vehicle_exit_complete_notify(v); + vechile_module_exit(); return 0; } diff --git a/drivers/video/rockchip/vehicle/vehicle_main.h b/drivers/video/rockchip/vehicle/vehicle_main.h index 2f4a78290261..4d66db14a978 100644 --- a/drivers/video/rockchip/vehicle/vehicle_main.h +++ b/drivers/video/rockchip/vehicle/vehicle_main.h @@ -14,5 +14,6 @@ void vehicle_gpio_stat_change_notify(void); void vehicle_cif_error_notify(int last_line); void vehicle_android_is_ready_notify(void); void vehicle_apk_state_change(char crtc[22]); +void vechile_module_exit(void); #endif diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index ba237a225d48..cdc3af4d5e87 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -268,6 +268,7 @@ struct dw_hdmi_plat_data { /* Vendor Property support */ const struct dw_hdmi_property_ops *property_ops; struct drm_connector *connector; + struct drm_bridge *bridge; }; struct dw_hdmi_cec_wake_ops { diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index 4e3d536f4ce7..0d3d04597c27 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -1398,6 +1398,20 @@ static int rockchip_sai_probe(struct platform_device *pdev) if (ret) return ret; + ret = rockchip_sai_init_dai(sai, res, &dai); + if (ret) + return ret; + + /* + * MUST: after pm_runtime_enable step, any register R/W + * should be wrapped with pm_runtime_get_sync/put. + * + * Another approach is to enable the regcache true to + * avoid access HW registers. + * + * Alternatively, performing the registers R/W before + * pm_runtime_enable is also a good option. + */ pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { ret = rockchip_sai_runtime_resume(&pdev->dev); @@ -1405,10 +1419,6 @@ static int rockchip_sai_probe(struct platform_device *pdev) goto err_runtime_disable; } - ret = rockchip_sai_init_dai(sai, res, &dai); - if (ret) - goto err_runtime_suspend; - ret = devm_snd_soc_register_component(&pdev->dev, &rockchip_sai_component, dai, 1);