From 484a8737c755071ae456adf3561f6749dd250881 Mon Sep 17 00:00:00 2001 From: Qian Cai Date: Sun, 7 Jun 2020 22:53:40 -0400 Subject: [PATCH 01/20] drm: rcar-du: Make DRM_RCAR_WRITEBACK depends on DRM_RCAR_DU There is no need to select DRM_RCAR_WRITEBACK if DRM_RCAR_DU=n which just make the generated .config a bit ugly. # ARM devices # # end of ARM devices CONFIG_DRM_RCAR_WRITEBACK=y # # Frame buffer Devices Let DRM_RCAR_WRITEBACK depend on DRM_RCAR_DU instead. Signed-off-by: Qian Cai Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index f65d1489dc50..49b590aa69be 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -49,3 +49,4 @@ config DRM_RCAR_VSP config DRM_RCAR_WRITEBACK bool default y if ARM64 + depends on DRM_RCAR_DU From c3415d91832cf47bf54973ef5415caeaba5249c6 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 7 Aug 2020 18:49:48 +0100 Subject: [PATCH 02/20] dt-bindings: display: renesas,du: Document the r8a7742 bindings Document the RZ/G1H (R8A7742) SoC in the R-Car DU bindings. Signed-off-by: Lad Prabhakar Reviewed-by: Marian-Cristian Rotariu Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Laurent Pinchart --- Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 51cd4d162770..3f1e3ca4bea9 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -3,6 +3,7 @@ Required Properties: - compatible: must be one of the following. + - "renesas,du-r8a7742" for R8A7742 (RZ/G1H) compatible DU - "renesas,du-r8a7743" for R8A7743 (RZ/G1M) compatible DU - "renesas,du-r8a7744" for R8A7744 (RZ/G1N) compatible DU - "renesas,du-r8a7745" for R8A7745 (RZ/G1E) compatible DU @@ -68,6 +69,7 @@ corresponding to each DU output. Port0 Port1 Port2 Port3 ----------------------------------------------------------------------------- + R8A7742 (RZ/G1H) DPAD 0 LVDS 0 LVDS 1 - R8A7743 (RZ/G1M) DPAD 0 LVDS 0 - - R8A7744 (RZ/G1N) DPAD 0 LVDS 0 - - R8A7745 (RZ/G1E) DPAD 0 DPAD 1 - - From 9edf73fece3d27e6fb5a764b732eca94c941838e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 7 Aug 2020 18:49:49 +0100 Subject: [PATCH 03/20] drm: rcar-du: Add r8a7742 support Add direct support for the r8a7742 (RZ/G1H). The RZ/G1H shares a common, compatible configuration with the r8a7790 (R-Car H2) so that device info structure is reused, the only difference being TCON is unsupported on RZ/G1H (Currently unsupported by the driver). Signed-off-by: Lad Prabhakar Reviewed-by: Marian-Cristian Rotariu Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index f53b0ec71085..0f870c282455 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -216,8 +216,9 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { .channels_mask = BIT(2) | BIT(1) | BIT(0), .routes = { /* - * R8A7790 has one RGB output, two LVDS outputs and one - * (currently unsupported) TCON output. + * R8A7742 and R8A7790 each have one RGB output and two LVDS + * outputs. Additionally R8A7790 supports one TCON output + * (currently unsupported by the driver). */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(2) | BIT(1) | BIT(0), @@ -443,6 +444,7 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { }; static const struct of_device_id rcar_du_of_table[] = { + { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info }, { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info }, { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info }, { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info }, From 109bf47277a0b94670743b0648d76e61b982696b Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 7 Aug 2020 18:49:50 +0100 Subject: [PATCH 04/20] dt-bindings: display: renesas,lvds: Document r8a7742 bindings Document the RZ/G1H (R8A7742) LVDS bindings. Signed-off-by: Lad Prabhakar Reviewed-by: Marian-Cristian Rotariu Reviewed-by: Laurent Pinchart [Port to the YAML binding document] Acked-by: Rob Herring Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/renesas,lvds.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml index baaf2a2a6fed..bf3dee252c1a 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml @@ -16,6 +16,7 @@ description: | properties: compatible: enum: + - renesas,r8a7742-lvds # for RZ/G1H compatible LVDS encoders - renesas,r8a7743-lvds # for RZ/G1M compatible LVDS encoders - renesas,r8a7744-lvds # for RZ/G1N compatible LVDS encoders - renesas,r8a774a1-lvds # for RZ/G2M compatible LVDS encoders From 3fa98ed530a4bd80e4936635831fa77666eea82e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 7 Aug 2020 18:49:51 +0100 Subject: [PATCH 05/20] drm: rcar-du: lvds: Add r8a7742 support The LVDS encoders on RZ/G1H SoC is identical to the R-Car Gen2 family. Add support for RZ/G1H (R8A7742) SoC to the LVDS encoder driver. Signed-off-by: Lad Prabhakar Reviewed-by: Marian-Cristian Rotariu Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_lvds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index bced729a96fe..dc386e3a763c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -978,6 +978,7 @@ static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = { }; static const struct of_device_id rcar_lvds_of_table[] = { + { .compatible = "renesas,r8a7742-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7743-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7744-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info }, From 2cd9df2be75766452fef87c37ec37d91f4cbaf6b Mon Sep 17 00:00:00 2001 From: Biju Das Date: Mon, 10 Aug 2020 16:22:17 +0100 Subject: [PATCH 06/20] dt-bindings: display: bridge: lvds-codec: Document power-supply property Document optional power-supply property that may be used to specify the regulator powering up the device. Signed-off-by: Biju Das Reviewed-by: Laurent Pinchart Reviewed-by: Rob Herring Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/lvds-codec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index 68951d56ebba..ff3ae25f8b23 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -79,6 +79,9 @@ properties: The GPIO used to control the power down line of this device. maxItems: 1 + power-supply: + maxItems: 1 + required: - compatible - ports From 946a61ab2d758cc645f6e63f1a5e2731690c3943 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Mon, 10 Aug 2020 16:22:18 +0100 Subject: [PATCH 07/20] drm/bridge: lvds-codec: Add support for regulator Add the support for enabling optional regulator that may be used as VCC source. Signed-off-by: Biju Das Reviewed-by: Laurent Pinchart [Replaced 'error' variable with 'ret'] [Renamed regulator from 'vcc' to 'power'] Signed-off-by: Laurent Pinchart Reviewed-by: Biju Das --- drivers/gpu/drm/bridge/lvds-codec.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index f19d9f7a5db2..f52ccffc1bd1 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -10,13 +10,16 @@ #include #include #include +#include #include #include struct lvds_codec { + struct device *dev; struct drm_bridge bridge; struct drm_bridge *panel_bridge; + struct regulator *vcc; struct gpio_desc *powerdown_gpio; u32 connector_type; }; @@ -38,6 +41,14 @@ static int lvds_codec_attach(struct drm_bridge *bridge, static void lvds_codec_enable(struct drm_bridge *bridge) { struct lvds_codec *lvds_codec = to_lvds_codec(bridge); + int ret; + + ret = regulator_enable(lvds_codec->vcc); + if (ret) { + dev_err(lvds_codec->dev, + "Failed to enable regulator \"vcc\": %d\n", ret); + return; + } if (lvds_codec->powerdown_gpio) gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0); @@ -46,9 +57,15 @@ static void lvds_codec_enable(struct drm_bridge *bridge) static void lvds_codec_disable(struct drm_bridge *bridge) { struct lvds_codec *lvds_codec = to_lvds_codec(bridge); + int ret; if (lvds_codec->powerdown_gpio) gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1); + + ret = regulator_disable(lvds_codec->vcc); + if (ret) + dev_err(lvds_codec->dev, + "Failed to disable regulator \"vcc\": %d\n", ret); } static const struct drm_bridge_funcs funcs = { @@ -63,12 +80,24 @@ static int lvds_codec_probe(struct platform_device *pdev) struct device_node *panel_node; struct drm_panel *panel; struct lvds_codec *lvds_codec; + int ret; lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); if (!lvds_codec) return -ENOMEM; + lvds_codec->dev = &pdev->dev; lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev); + + lvds_codec->vcc = devm_regulator_get(lvds_codec->dev, "power"); + if (IS_ERR(lvds_codec->vcc)) { + ret = PTR_ERR(lvds_codec->vcc); + if (ret != -EPROBE_DEFER) + dev_err(lvds_codec->dev, + "Unable to get \"vcc\" supply: %d\n", ret); + return ret; + } + lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); if (IS_ERR(lvds_codec->powerdown_gpio)) From 4b6f2b971e8d142474b7ab7e6d3c23e38d83057f Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 12 Aug 2020 15:02:09 +0100 Subject: [PATCH 08/20] dt-bindings: display: renesas,du: Document r8a774e1 bindings Document the RZ/G2H (a.k.a. r8a774e1) SoC in the R-Car DU bindings. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart --- Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 3f1e3ca4bea9..0a14f944180d 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -11,6 +11,7 @@ Required Properties: - "renesas,du-r8a774a1" for R8A774A1 (RZ/G2M) compatible DU - "renesas,du-r8a774b1" for R8A774B1 (RZ/G2N) compatible DU - "renesas,du-r8a774c0" for R8A774C0 (RZ/G2E) compatible DU + - "renesas,du-r8a774e1" for R8A774E1 (RZ/G2H) compatible DU - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU @@ -77,6 +78,7 @@ corresponding to each DU output. R8A774A1 (RZ/G2M) DPAD 0 HDMI 0 LVDS 0 - R8A774B1 (RZ/G2N) DPAD 0 HDMI 0 LVDS 0 - R8A774C0 (RZ/G2E) DPAD 0 LVDS 0 LVDS 1 - + R8A774E1 (RZ/G2H) DPAD 0 HDMI 0 LVDS 0 - R8A7779 (R-Car H1) DPAD 0 DPAD 1 - - R8A7790 (R-Car H2) DPAD 0 LVDS 0 LVDS 1 - R8A7791 (R-Car M2-W) DPAD 0 LVDS 0 - - From 31057d444d41ea820a5c61126e2c810a80a16e79 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 12 Aug 2020 15:02:10 +0100 Subject: [PATCH 09/20] drm: rcar-du: Add support for R8A774E1 SoC Hookup RZ/G2H (R8A774E1) to DU driver. R8A774E1 has one RGB output, one LVDS output and one HDMI output. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0f870c282455..0e3dd5d8d5c3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -186,6 +186,35 @@ static const struct rcar_du_device_info rcar_du_r8a774c0_info = { .lvds_clk_mask = BIT(1) | BIT(0), }; +static const struct rcar_du_device_info rcar_du_r8a774e1_info = { + .gen = 3, + .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK + | RCAR_DU_FEATURE_VSP1_SOURCE + | RCAR_DU_FEATURE_INTERLACED + | RCAR_DU_FEATURE_TVM_SYNC, + .channels_mask = BIT(3) | BIT(1) | BIT(0), + .routes = { + /* + * R8A774E1 has one RGB output, one LVDS output and one HDMI + * output. + */ + [RCAR_DU_OUTPUT_DPAD0] = { + .possible_crtcs = BIT(2), + .port = 0, + }, + [RCAR_DU_OUTPUT_HDMI0] = { + .possible_crtcs = BIT(1), + .port = 1, + }, + [RCAR_DU_OUTPUT_LVDS0] = { + .possible_crtcs = BIT(0), + .port = 2, + }, + }, + .num_lvds = 1, + .dpll_mask = BIT(1), +}; + static const struct rcar_du_device_info rcar_du_r8a7779_info = { .gen = 1, .features = RCAR_DU_FEATURE_INTERLACED @@ -452,6 +481,7 @@ static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info }, { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info }, { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info }, + { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info }, { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info }, { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info }, { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info }, From 45d6ec79dd42258ada43fedf3bb00c04ae7c17eb Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 12 Aug 2020 15:02:12 +0100 Subject: [PATCH 10/20] dt-bindings: display: renesas,lvds: Document r8a774e1 bindings Document the RZ/G2H (R8A774E1) LVDS bindings. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/renesas,lvds.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml index bf3dee252c1a..e5b163951b91 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml +++ b/Documentation/devicetree/bindings/display/bridge/renesas,lvds.yaml @@ -22,6 +22,7 @@ properties: - renesas,r8a774a1-lvds # for RZ/G2M compatible LVDS encoders - renesas,r8a774b1-lvds # for RZ/G2N compatible LVDS encoders - renesas,r8a774c0-lvds # for RZ/G2E compatible LVDS encoders + - renesas,r8a774e1-lvds # for RZ/G2H compatible LVDS encoders - renesas,r8a7790-lvds # for R-Car H2 compatible LVDS encoders - renesas,r8a7791-lvds # for R-Car M2-W compatible LVDS encoders - renesas,r8a7793-lvds # for R-Car M2-N compatible LVDS encoders From 0c905a0a30d16c43efc381a29f509fbff606b91d Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 12 Aug 2020 15:02:13 +0100 Subject: [PATCH 11/20] dt-bindings: display: renesas,dw-hdmi: Add r8a774e1 support Document RZ/G2H (R8A774E1) SoC bindings. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index 819f3e31013c..f275997ab947 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -14,6 +14,7 @@ Required properties: - compatible : Shall contain one or more of - "renesas,r8a774a1-hdmi" for R8A774A1 (RZ/G2M) compatible HDMI TX - "renesas,r8a774b1-hdmi" for R8A774B1 (RZ/G2N) compatible HDMI TX + - "renesas,r8a774e1-hdmi" for R8A774E1 (RZ/G2H) compatible HDMI TX - "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX - "renesas,r8a7796-hdmi" for R8A7796 (R-Car M3-W) compatible HDMI TX - "renesas,r8a77965-hdmi" for R8A77965 (R-Car M3-N) compatible HDMI TX From 6d981d276110c7d6e866179db4bb1c6cbfcd1819 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 12 Aug 2020 15:02:15 +0100 Subject: [PATCH 12/20] drm: rcar-du: lvds: Add support for R8A774E1 SoC The LVDS encoder on RZ/G2H (R8A774E1) SoC is identical to R-Car Gen3 so just reuse the rcar_lvds_gen3_info structure to hookup R8A774E1 to LVDS encoder driver. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_lvds.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index dc386e3a763c..70dbbe44bb23 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -984,6 +984,7 @@ static const struct of_device_id rcar_lvds_of_table[] = { { .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info }, { .compatible = "renesas,r8a774b1-lvds", .data = &rcar_lvds_gen3_info }, { .compatible = "renesas,r8a774c0-lvds", .data = &rcar_lvds_r8a77990_info }, + { .compatible = "renesas,r8a774e1-lvds", .data = &rcar_lvds_gen3_info }, { .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info }, { .compatible = "renesas,r8a7793-lvds", .data = &rcar_lvds_gen2_info }, From 542d9a658eebac0e6054a5734cb1f893778a43f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Sep 2020 09:34:04 +0900 Subject: [PATCH 13/20] dt-bindings: display: renesas: du: Document the r8a77961 bindings Document the R-Car M3-W+ (R8A77961) SoC in the R-Car DU bindings. Signed-off-by: Kuninori Morimoto Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Acked-by: Rob Herring Signed-off-by: Laurent Pinchart --- Documentation/devicetree/bindings/display/renesas,du.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 0a14f944180d..7d65c24fcda8 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -20,6 +20,7 @@ Required Properties: - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU - "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU + - "renesas,du-r8a77961" for R8A77961 (R-Car M3-W+) compatible DU - "renesas,du-r8a77965" for R8A77965 (R-Car M3-N) compatible DU - "renesas,du-r8a77970" for R8A77970 (R-Car V3M) compatible DU - "renesas,du-r8a77980" for R8A77980 (R-Car V3H) compatible DU @@ -87,6 +88,7 @@ corresponding to each DU output. R8A7794 (R-Car E2) DPAD 0 DPAD 1 - - R8A7795 (R-Car H3) DPAD 0 HDMI 0 HDMI 1 LVDS 0 R8A7796 (R-Car M3-W) DPAD 0 HDMI 0 LVDS 0 - + R8A77961 (R-Car M3-W+) DPAD 0 HDMI 0 LVDS 0 - R8A77965 (R-Car M3-N) DPAD 0 HDMI 0 LVDS 0 - R8A77970 (R-Car V3M) DPAD 0 LVDS 0 - - R8A77980 (R-Car V3H) DPAD 0 LVDS 0 - - From 0356f0fbc53d7d787e4d827ed06241ce9df1fbfc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Sep 2020 09:34:11 +0900 Subject: [PATCH 14/20] dt-bindings: display: renesas: dw-hdmi: Tidyup example compatible The DT example erronously uses the "renesas,r8a7795-dw-hdmi", when the correct value is "renesas,r8a7795-hdmi". It is furthermore missing the generic "renesas,rcar-gen3-hdmi" compatible string. Fix it. Signed-off-by: Kuninori Morimoto Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham [Add "renesas,rcar-gen3-hdmi" and rework commit message] Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index f275997ab947..9c56c5169a88 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -43,7 +43,7 @@ Optional properties: Example: hdmi0: hdmi@fead0000 { - compatible = "renesas,r8a7795-dw-hdmi"; + compatible = "renesas,r8a7795-hdmi", "renesas,rcar-gen3-hdmi"; reg = <0 0xfead0000 0 0x10000>; interrupts = <0 389 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cpg CPG_CORE R8A7795_CLK_S0D4>, <&cpg CPG_MOD 729>; From 460941cd6923fdfe731d12ca97a433bc4c2f0afb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Sep 2020 09:34:17 +0900 Subject: [PATCH 15/20] dt-bindings: display: renesas: dw-hdmi: Add R8A77961 support This patch adds R-Car M3-W+ (R8A77961) SoC bindings. Signed-off-by: Kuninori Morimoto Reviewed-by: Geert Uytterhoeven Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Acked-by: Rob Herring Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/bridge/renesas,dw-hdmi.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt index 9c56c5169a88..3f6072651182 100644 --- a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -17,6 +17,7 @@ Required properties: - "renesas,r8a774e1-hdmi" for R8A774E1 (RZ/G2H) compatible HDMI TX - "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX - "renesas,r8a7796-hdmi" for R8A7796 (R-Car M3-W) compatible HDMI TX + - "renesas,r8a77961-hdmi" for R8A77961 (R-Car M3-W+) compatible HDMI TX - "renesas,r8a77965-hdmi" for R8A77965 (R-Car M3-N) compatible HDMI TX - "renesas,rcar-gen3-hdmi" for the generic R-Car Gen3 and RZ/G2 compatible HDMI TX From ef84ad32f41c2b84560ca3577fb0cb85dd4895fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 8 Sep 2020 09:34:32 +0900 Subject: [PATCH 16/20] drm: rcar-du: Add r8a77961 support This patch adds R-Car M3-W+ (R8A77961) support which is compatible with the R-Car M3-W (R8A77960). Signed-off-by: Kuninori Morimoto Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 0e3dd5d8d5c3..447be991fa25 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -490,6 +490,7 @@ static const struct of_device_id rcar_du_of_table[] = { { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, + { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info }, { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info }, { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info }, From dc86d6bc9bc3d0080bd18b54777a22b70eae4aa6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 6 Aug 2020 05:24:34 +0300 Subject: [PATCH 17/20] drm: rcar-du: Fix pitch handling for fully planar YUV formats When creating a frame buffer, the driver verifies that the pitches for the chroma planes match the luma plane. This is done incorrectly for fully planar YUV formats, without taking horizontal subsampling into account. Fix it. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 54 ++++++++++++++++++++++++++- drivers/gpu/drm/rcar-du/rcar_du_kms.h | 1 + 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 482329102f19..72dda446355f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -40,6 +40,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_RGB565, .bpp = 16, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP, .edf = PnDDCR4_EDF_NONE, }, { @@ -47,6 +48,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_ARGB555, .bpp = 16, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_ARGB, .edf = PnDDCR4_EDF_NONE, }, { @@ -61,6 +63,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_XBGR32, .bpp = 32, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_TP | PnMR_DDDF_16BPP, .edf = PnDDCR4_EDF_RGB888, }, { @@ -68,6 +71,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_ABGR32, .bpp = 32, .planes = 1, + .hsub = 1, .pnmr = PnMR_SPIM_ALP | PnMR_DDDF_16BPP, .edf = PnDDCR4_EDF_ARGB8888, }, { @@ -75,6 +79,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_UYVY, .bpp = 16, .planes = 1, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -82,6 +87,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_YUYV, .bpp = 16, .planes = 1, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -89,6 +95,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_NV12M, .bpp = 12, .planes = 2, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -96,6 +103,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_NV21M, .bpp = 12, .planes = 2, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, { @@ -103,6 +111,7 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_NV16M, .bpp = 16, .planes = 2, + .hsub = 2, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .edf = PnDDCR4_EDF_NONE, }, @@ -115,156 +124,187 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { .v4l2 = V4L2_PIX_FMT_RGB332, .bpp = 8, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ARGB4444, .v4l2 = V4L2_PIX_FMT_ARGB444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XRGB4444, .v4l2 = V4L2_PIX_FMT_XRGB444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBA4444, .v4l2 = V4L2_PIX_FMT_RGBA444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBX4444, .v4l2 = V4L2_PIX_FMT_RGBX444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ABGR4444, .v4l2 = V4L2_PIX_FMT_ABGR444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XBGR4444, .v4l2 = V4L2_PIX_FMT_XBGR444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRA4444, .v4l2 = V4L2_PIX_FMT_BGRA444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRX4444, .v4l2 = V4L2_PIX_FMT_BGRX444, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBA5551, .v4l2 = V4L2_PIX_FMT_RGBA555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBX5551, .v4l2 = V4L2_PIX_FMT_RGBX555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ABGR1555, .v4l2 = V4L2_PIX_FMT_ABGR555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XBGR1555, .v4l2 = V4L2_PIX_FMT_XBGR555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRA5551, .v4l2 = V4L2_PIX_FMT_BGRA555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRX5551, .v4l2 = V4L2_PIX_FMT_BGRX555, .bpp = 16, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGR888, .v4l2 = V4L2_PIX_FMT_RGB24, .bpp = 24, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGB888, .v4l2 = V4L2_PIX_FMT_BGR24, .bpp = 24, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBA8888, .v4l2 = V4L2_PIX_FMT_BGRA32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_RGBX8888, .v4l2 = V4L2_PIX_FMT_BGRX32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_ABGR8888, .v4l2 = V4L2_PIX_FMT_RGBA32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_XBGR8888, .v4l2 = V4L2_PIX_FMT_RGBX32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRA8888, .v4l2 = V4L2_PIX_FMT_ARGB32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_BGRX8888, .v4l2 = V4L2_PIX_FMT_XRGB32, .bpp = 32, .planes = 1, + .hsub = 1, }, { .fourcc = DRM_FORMAT_YVYU, .v4l2 = V4L2_PIX_FMT_YVYU, .bpp = 16, .planes = 1, + .hsub = 2, }, { .fourcc = DRM_FORMAT_NV61, .v4l2 = V4L2_PIX_FMT_NV61M, .bpp = 16, .planes = 2, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YUV420, .v4l2 = V4L2_PIX_FMT_YUV420M, .bpp = 12, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YVU420, .v4l2 = V4L2_PIX_FMT_YVU420M, .bpp = 12, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YUV422, .v4l2 = V4L2_PIX_FMT_YUV422M, .bpp = 16, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YVU422, .v4l2 = V4L2_PIX_FMT_YVU422M, .bpp = 16, .planes = 3, + .hsub = 2, }, { .fourcc = DRM_FORMAT_YUV444, .v4l2 = V4L2_PIX_FMT_YUV444M, .bpp = 24, .planes = 3, + .hsub = 1, }, { .fourcc = DRM_FORMAT_YVU444, .v4l2 = V4L2_PIX_FMT_YVU444M, .bpp = 24, .planes = 3, + .hsub = 1, }, }; @@ -311,6 +351,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, { struct rcar_du_device *rcdu = dev->dev_private; const struct rcar_du_format_info *format; + unsigned int chroma_pitch; unsigned int max_pitch; unsigned int align; unsigned int i; @@ -353,10 +394,19 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-EINVAL); } + /* + * Calculate the chroma plane(s) pitch using the horizontal subsampling + * factor. For semi-planar formats, the U and V planes are combined, the + * pitch must thus be doubled. + */ + chroma_pitch = mode_cmd->pitches[0] / format->hsub; + if (format->planes == 2) + chroma_pitch *= 2; + for (i = 1; i < format->planes; ++i) { - if (mode_cmd->pitches[i] != mode_cmd->pitches[0]) { + if (mode_cmd->pitches[i] != chroma_pitch) { dev_dbg(dev->dev, - "luma and chroma pitches do not match\n"); + "luma and chroma pitches are not compatible\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.h b/drivers/gpu/drm/rcar-du/rcar_du_kms.h index 0346504d8c59..8f5fff176754 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.h @@ -22,6 +22,7 @@ struct rcar_du_format_info { u32 v4l2; unsigned int bpp; unsigned int planes; + unsigned int hsub; unsigned int pnmr; unsigned int edf; }; From f4dfa76d73f76eb0b0016d8ebacebb85db743018 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 8 Aug 2020 00:07:21 +0300 Subject: [PATCH 18/20] drm: rcar-du: Fix crash when enabling a non-visible plane The DU driver handles non-visible planes (fully clipped by the display's boundaries) by considering them as disabled. It thus disables the plane at the hardware level when the plane is moved off-screen. However, if the plane was previously disabled and is non-visible when it gets enabled, the attempt to disable it crashes, as the plane wasn't previously enabled. Fix it. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index f1a81c9b184d..ff233a7b398d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -279,7 +279,7 @@ static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane, if (plane->state->visible) rcar_du_vsp_plane_setup(rplane); - else + else if (old_state->crtc) vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe, rplane->index, NULL); } From 709b66b4b745bca5324941cd4d7a34ffeba87cf0 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 11 Sep 2020 11:07:41 +0100 Subject: [PATCH 19/20] drm: rcar-du: Update description for DRM_RCAR_DW_HDMI Kconfig entry The rcar_dw_hdmi driver is also used on Renesas RZ/G2 SoCs. Update the Kconfig entry description to reflect this. Signed-off-by: Lad Prabhakar Reviewed-by: Chris Paterson Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index 49b590aa69be..b47e74421e34 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -22,11 +22,11 @@ config DRM_RCAR_CMM Enable support for R-Car Color Management Module (CMM). config DRM_RCAR_DW_HDMI - tristate "R-Car DU Gen3 HDMI Encoder Support" + tristate "R-Car Gen3 and RZ/G2 DU HDMI Encoder Support" depends on DRM && OF select DRM_DW_HDMI help - Enable support for R-Car Gen3 internal HDMI encoder. + Enable support for R-Car Gen3 or RZ/G2 internal HDMI encoder. config DRM_RCAR_LVDS tristate "R-Car DU LVDS Encoder Support" From 2a32dbdc2c7db5463483fa01fb220fd1b770c6bc Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 16 Sep 2020 02:23:47 +0300 Subject: [PATCH 20/20] drm: rcar-du: Put reference to VSP device The reference to the VSP device acquired with of_find_device_by_node() in rcar_du_vsp_init() is never released. Fix it with a drmm action, which gets run both in the probe error path and in the remove path. Fixes: 6d62ef3ac30b ("drm: rcar-du: Expose the VSP1 compositor through KMS planes") Reported-by: Yu Kuai Reviewed-by: Kieran Bingham Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index ff233a7b398d..f4db9dca5135 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -341,6 +342,13 @@ static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = { .atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state, }; +static void rcar_du_vsp_cleanup(struct drm_device *dev, void *res) +{ + struct rcar_du_vsp *vsp = res; + + put_device(vsp->vsp); +} + int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, unsigned int crtcs) { @@ -357,6 +365,10 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, vsp->vsp = &pdev->dev; + ret = drmm_add_action(rcdu->ddev, rcar_du_vsp_cleanup, vsp); + if (ret < 0) + return ret; + ret = vsp1_du_init(vsp->vsp); if (ret < 0) return ret;