From 25ed8aeb9c396475f48c13abdaf76a2e6e6b117b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:25 +0100 Subject: [PATCH 01/73] drm/bridge/synopsys: dsi: driver-specific configuration of phy timings The timing values for dw-dsi are often dependent on the used display and according to Philippe Cornu will most likely also depend on the used phy technology in the soc-specific implementation. To solve this and allow specific implementations to define them as needed add a new get_timing callback to phy_ops and call this from the dphy_timing function to retrieve the necessary values for the specific mode. Right now this handles the hs2lp + lp2hs where Rockchip SoCs need handling according to the phy speed, while STM seems to be ok with static values. changes in v5: - rebase on 5.5-rc1 - merge into px30 dsi series to prevent ordering conflicts changes in v4: - rebase to make it directly fit on top of drm-misc-next after all changes in v3: - check existence of phy_ops->get_timing in __dw_mipi_dsi_probe() - emit actual error when get_timing() call fails - add tags from Philippe and Yannick changes in v2: - add driver-specific handling, don't force all bridge users to use the same timings, as suggested by Philippe Suggested-by: Philippe Cornu Signed-off-by: Heiko Stuebner Reviewed-by: Philippe Cornu Tested-by: Yannick Fertre Reviewed-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-2-heiko@sntech.de --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 27 +++++-- drivers/gpu/drm/rockchip/Kconfig | 1 + .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 78 +++++++++++++++++++ drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 13 ++++ include/drm/bridge/dw_mipi_dsi.h | 9 +++ 5 files changed, 121 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index b6e793bb653c..bfe0061e54a2 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -719,7 +719,15 @@ static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi, static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi) { + const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; + struct dw_mipi_dsi_dphy_timing timing; u32 hw_version; + int ret; + + ret = phy_ops->get_timing(dsi->plat_data->priv_data, + dsi->lane_mbps, &timing); + if (ret) + DRM_DEV_ERROR(dsi->dev, "Retrieving phy timings failed\n"); /* * TODO dw drv improvements @@ -732,16 +740,20 @@ static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi) hw_version = dsi_read(dsi, DSI_VERSION) & VERSION; if (hw_version >= HWVER_131) { - dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME_V131(0x40) | - PHY_LP2HS_TIME_V131(0x40)); + dsi_write(dsi, DSI_PHY_TMR_CFG, + PHY_HS2LP_TIME_V131(timing.data_hs2lp) | + PHY_LP2HS_TIME_V131(timing.data_lp2hs)); dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000)); } else { - dsi_write(dsi, DSI_PHY_TMR_CFG, PHY_HS2LP_TIME(0x40) | - PHY_LP2HS_TIME(0x40) | MAX_RD_TIME(10000)); + dsi_write(dsi, DSI_PHY_TMR_CFG, + PHY_HS2LP_TIME(timing.data_hs2lp) | + PHY_LP2HS_TIME(timing.data_lp2hs) | + MAX_RD_TIME(10000)); } - dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, PHY_CLKHS2LP_TIME(0x40) - | PHY_CLKLP2HS_TIME(0x40)); + dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, + PHY_CLKHS2LP_TIME(timing.clk_hs2lp) | + PHY_CLKLP2HS_TIME(timing.clk_lp2hs)); } static void dw_mipi_dsi_dphy_interface_config(struct dw_mipi_dsi *dsi) @@ -991,7 +1003,8 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, dsi->dev = dev; dsi->plat_data = plat_data; - if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps) { + if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps || + !plat_data->phy_ops->get_timing) { DRM_ERROR("Phy not properly configured\n"); return ERR_PTR(-ENODEV); } diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 1670a5cae3c7..310aa1546893 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -46,6 +46,7 @@ config ROCKCHIP_DW_HDMI config ROCKCHIP_DW_MIPI_DSI bool "Rockchip specific extensions for Synopsys DW MIPI DSI" + select GENERIC_PHY_MIPI_DPHY help This selects support for Rockchip SoC specific extensions for the Synopsys DesignWare HDMI driver. If you want to diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 5f23cf702cb4..b41d86ee9e17 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -559,9 +559,87 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, return 0; } +struct hstt { + unsigned int maxfreq; + struct dw_mipi_dsi_dphy_timing timing; +}; + +#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \ +{ \ + .maxfreq = _maxfreq, \ + .timing = { \ + .clk_lp2hs = _c_lp2hs, \ + .clk_hs2lp = _c_hs2lp, \ + .data_lp2hs = _d_lp2hs, \ + .data_hs2lp = _d_hs2lp, \ + } \ +} + +/* Table A-3 High-Speed Transition Times */ +struct hstt hstt_table[] = { + HSTT( 90, 32, 20, 26, 13), + HSTT( 100, 35, 23, 28, 14), + HSTT( 110, 32, 22, 26, 13), + HSTT( 130, 31, 20, 27, 13), + HSTT( 140, 33, 22, 26, 14), + HSTT( 150, 33, 21, 26, 14), + HSTT( 170, 32, 20, 27, 13), + HSTT( 180, 36, 23, 30, 15), + HSTT( 200, 40, 22, 33, 15), + HSTT( 220, 40, 22, 33, 15), + HSTT( 240, 44, 24, 36, 16), + HSTT( 250, 48, 24, 38, 17), + HSTT( 270, 48, 24, 38, 17), + HSTT( 300, 50, 27, 41, 18), + HSTT( 330, 56, 28, 45, 18), + HSTT( 360, 59, 28, 48, 19), + HSTT( 400, 61, 30, 50, 20), + HSTT( 450, 67, 31, 55, 21), + HSTT( 500, 73, 31, 59, 22), + HSTT( 550, 79, 36, 63, 24), + HSTT( 600, 83, 37, 68, 25), + HSTT( 650, 90, 38, 73, 27), + HSTT( 700, 95, 40, 77, 28), + HSTT( 750, 102, 40, 84, 28), + HSTT( 800, 106, 42, 87, 30), + HSTT( 850, 113, 44, 93, 31), + HSTT( 900, 118, 47, 98, 32), + HSTT( 950, 124, 47, 102, 34), + HSTT(1000, 130, 49, 107, 35), + HSTT(1050, 135, 51, 111, 37), + HSTT(1100, 139, 51, 114, 38), + HSTT(1150, 146, 54, 120, 40), + HSTT(1200, 153, 57, 125, 41), + HSTT(1250, 158, 58, 130, 42), + HSTT(1300, 163, 58, 135, 44), + HSTT(1350, 168, 60, 140, 45), + HSTT(1400, 172, 64, 144, 47), + HSTT(1450, 176, 65, 148, 48), + HSTT(1500, 181, 66, 153, 50) +}; + +static int +dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps, + struct dw_mipi_dsi_dphy_timing *timing) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hstt_table); i++) + if (lane_mbps < hstt_table[i].maxfreq) + break; + + if (i == ARRAY_SIZE(hstt_table)) + i--; + + *timing = hstt_table[i].timing; + + return 0; +} + static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = { .init = dw_mipi_dsi_phy_init, .get_lane_mbps = dw_mipi_dsi_get_lane_mbps, + .get_timing = dw_mipi_dsi_phy_get_timing, }; static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi, diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c index 514efefb0016..4b165635b2d4 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -309,11 +309,24 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, return 0; } +static int +dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps, + struct dw_mipi_dsi_dphy_timing *timing) +{ + timing->clk_hs2lp = 0x40; + timing->clk_lp2hs = 0x40; + timing->data_hs2lp = 0x40; + timing->data_lp2hs = 0x40; + + return 0; +} + static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops = { .init = dw_mipi_dsi_phy_init, .power_on = dw_mipi_dsi_phy_power_on, .power_off = dw_mipi_dsi_phy_power_off, .get_lane_mbps = dw_mipi_dsi_get_lane_mbps, + .get_timing = dw_mipi_dsi_phy_get_timing, }; static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data = { diff --git a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h index 94cc64a342e1..b0e390b3288e 100644 --- a/include/drm/bridge/dw_mipi_dsi.h +++ b/include/drm/bridge/dw_mipi_dsi.h @@ -19,6 +19,13 @@ struct dw_mipi_dsi; struct mipi_dsi_device; struct platform_device; +struct dw_mipi_dsi_dphy_timing { + u16 data_hs2lp; + u16 data_lp2hs; + u16 clk_hs2lp; + u16 clk_lp2hs; +}; + struct dw_mipi_dsi_phy_ops { int (*init)(void *priv_data); void (*power_on)(void *priv_data); @@ -27,6 +34,8 @@ struct dw_mipi_dsi_phy_ops { const struct drm_display_mode *mode, unsigned long mode_flags, u32 lanes, u32 format, unsigned int *lane_mbps); + int (*get_timing)(void *priv_data, unsigned int lane_mbps, + struct dw_mipi_dsi_dphy_timing *timing); }; struct dw_mipi_dsi_host_ops { From 89bddff6be745fd688bbdd53773f5eb3136051eb Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:26 +0100 Subject: [PATCH 02/73] drm/bridge/synopsys: dsi: move phy_ops callbacks around panel enablement If implementation-specific phy_ops need to be defined they probably should be enabled before trying to talk to the panel and disabled only after the panel was disabled. Right now they are enabled last and disabled first, so might make it impossible to talk to some panels - example for this being the px30 with an external Innosilicon dphy that needs the phy to be enabled to transfer commands to the panel. So move the calls appropriately. changed in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Reviewed-by: Neil Armstrong Tested-by: Yannick Fertre Reviewed-by: Philippe Cornu Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-3-heiko@sntech.de --- drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index bfe0061e54a2..b18351b6760a 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -810,9 +810,6 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge) struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; - if (phy_ops->power_off) - phy_ops->power_off(dsi->plat_data->priv_data); - /* * Switch to command mode before panel-bridge post_disable & * panel unprepare. @@ -829,6 +826,9 @@ static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge) */ dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge); + if (phy_ops->power_off) + phy_ops->power_off(dsi->plat_data->priv_data); + if (dsi->slave) { dw_mipi_dsi_disable(dsi->slave); clk_disable_unprepare(dsi->slave->pclk); @@ -895,6 +895,9 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi, /* Switch to cmd mode for panel-bridge pre_enable & panel prepare */ dw_mipi_dsi_set_mode(dsi, 0); + + if (phy_ops->power_on) + phy_ops->power_on(dsi->plat_data->priv_data); } static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge, @@ -911,15 +914,11 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge, static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge) { struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); - const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; /* Switch to video mode for panel-bridge enable & panel enable */ dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO); if (dsi->slave) dw_mipi_dsi_set_mode(dsi->slave, MIPI_DSI_MODE_VIDEO); - - if (phy_ops->power_on) - phy_ops->power_on(dsi->plat_data->priv_data); } static enum drm_mode_status From 0606f9b67e8c8727c1369096b3b142dd74dc0a39 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:27 +0100 Subject: [PATCH 03/73] dt-bindings: display: rockchip-dsi: document external phys Some dw-mipi-dsi instances in Rockchip SoCs use external dphys. In these cases the needs clock will also be generated externally so these don't need the ref-clock as well. changes in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Reviewed-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-4-heiko@sntech.de --- .../bindings/display/rockchip/dw_mipi_dsi_rockchip.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index ce4c1fc9116c..1ba9237d0ac0 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt @@ -9,8 +9,9 @@ Required properties: - reg: Represent the physical address range of the controller. - interrupts: Represent the controller's interrupt to the CPU(s). - clocks, clock-names: Phandles to the controller's pll reference - clock(ref) and APB clock(pclk). For RK3399, a phy config clock - (phy_cfg) and a grf clock(grf) are required. As described in [1]. + clock(ref) when using an internal dphy and APB clock(pclk). + For RK3399, a phy config clock (phy_cfg) and a grf clock(grf) + are required. As described in [1]. - rockchip,grf: this soc should set GRF regs to mux vopl/vopb. - ports: contain a port node with endpoint definitions as defined in [2]. For vopb,set the reg = <0> and set the reg = <1> for vopl. @@ -18,6 +19,8 @@ Required properties: - video port 1 for either a panel or subsequent encoder Optional properties: +- phys: from general PHY binding: the phandle for the PHY device. +- phy-names: Should be "dphy" if phys references an external phy. - power-domains: a phandle to mipi dsi power domain node. - resets: list of phandle + reset specifier pairs, as described in [3]. - reset-names: string reset name, must be "apb". From 94bedc45acb5d03ca7e4f556964c13befba247e7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:28 +0100 Subject: [PATCH 04/73] drm/rockchip: add ability to handle external dphys in mipi-dsi While the common case is that the dsi controller uses an internal dphy, accessed through the phy registers inside the dsi controller, there is also the possibility to use a separate dphy from a different vendor. One such case is the Rockchip px30 that uses a Innosilicon Mipi dphy, so add the support for handling such a constellation, including the pll also getting generated inside that external phy. changes in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Reviewed-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-5-heiko@sntech.de --- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 68 +++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index b41d86ee9e17..17effcc73877 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -223,6 +224,10 @@ struct dw_mipi_dsi_rockchip { bool is_slave; struct dw_mipi_dsi_rockchip *slave; + /* optional external dphy */ + struct phy *phy; + union phy_configure_opts phy_opts; + unsigned int lane_mbps; /* per lane */ u16 input_div; u16 feedback_div; @@ -359,6 +364,9 @@ static int dw_mipi_dsi_phy_init(void *priv_data) struct dw_mipi_dsi_rockchip *dsi = priv_data; int ret, i, vco; + if (dsi->phy) + return 0; + /* * Get vco from frequency(lane_mbps) * vco frequency table @@ -467,6 +475,28 @@ static int dw_mipi_dsi_phy_init(void *priv_data) return ret; } +static void dw_mipi_dsi_phy_power_on(void *priv_data) +{ + struct dw_mipi_dsi_rockchip *dsi = priv_data; + int ret; + + ret = phy_set_mode(dsi->phy, PHY_MODE_MIPI_DPHY); + if (ret) { + DRM_DEV_ERROR(dsi->dev, "failed to set phy mode: %d\n", ret); + return; + } + + phy_configure(dsi->phy, &dsi->phy_opts); + phy_power_on(dsi->phy); +} + +static void dw_mipi_dsi_phy_power_off(void *priv_data) +{ + struct dw_mipi_dsi_rockchip *dsi = priv_data; + + phy_power_off(dsi->phy); +} + static int dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, unsigned long mode_flags, u32 lanes, u32 format, @@ -504,6 +534,17 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode, "DPHY clock frequency is out of range\n"); } + /* for external phy only a the mipi_dphy_config is necessary */ + if (dsi->phy) { + phy_mipi_dphy_get_default_config(mode->clock * 1000 * 10 / 8, + bpp, lanes, + &dsi->phy_opts.mipi_dphy); + dsi->lane_mbps = target_mbps; + *lane_mbps = dsi->lane_mbps; + + return 0; + } + fin = clk_get_rate(dsi->pllref_clk); fout = target_mbps * USEC_PER_SEC; @@ -638,6 +679,8 @@ dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps, static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = { .init = dw_mipi_dsi_phy_init, + .power_on = dw_mipi_dsi_phy_power_on, + .power_off = dw_mipi_dsi_phy_power_off, .get_lane_mbps = dw_mipi_dsi_get_lane_mbps, .get_timing = dw_mipi_dsi_phy_get_timing, }; @@ -998,12 +1041,29 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev) return -EINVAL; } + /* try to get a possible external dphy */ + dsi->phy = devm_phy_optional_get(dev, "dphy"); + if (IS_ERR(dsi->phy)) { + ret = PTR_ERR(dsi->phy); + DRM_DEV_ERROR(dev, "failed to get mipi dphy: %d\n", ret); + return ret; + } + dsi->pllref_clk = devm_clk_get(dev, "ref"); if (IS_ERR(dsi->pllref_clk)) { - ret = PTR_ERR(dsi->pllref_clk); - DRM_DEV_ERROR(dev, - "Unable to get pll reference clock: %d\n", ret); - return ret; + if (dsi->phy) { + /* + * if external phy is present, pll will be + * generated there. + */ + dsi->pllref_clk = NULL; + } else { + ret = PTR_ERR(dsi->pllref_clk); + DRM_DEV_ERROR(dev, + "Unable to get pll reference clock: %d\n", + ret); + return ret; + } } if (dsi->cdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) { From 95da672f386c937cc22f892fadb019de3b2c2f0d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:29 +0100 Subject: [PATCH 05/73] dt-bindings: display: rockchip-dsi: add px30 compatible The px30 SoC also uses a dw-mipi-dsi controller, so add the compatible value for it. changes in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Acked-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-6-heiko@sntech.de --- .../bindings/display/rockchip/dw_mipi_dsi_rockchip.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index 1ba9237d0ac0..151be3bba06f 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt @@ -4,8 +4,10 @@ Rockchip specific extensions to the Synopsys Designware MIPI DSI Required properties: - #address-cells: Should be <1>. - #size-cells: Should be <0>. -- compatible: "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi". - "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi". +- compatible: one of + "rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi" + "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi" + "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi" - reg: Represent the physical address range of the controller. - interrupts: Represent the controller's interrupt to the CPU(s). - clocks, clock-names: Phandles to the controller's pll reference From 49a37dc393d774b7f7b8ba3944b75c7f8673b43a Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:30 +0100 Subject: [PATCH 06/73] drm/rockchip: dsi: add px30 support Add the compatible and GRF definitions for the PX30 soc. changes in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Reviewed-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-7-heiko@sntech.de --- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 17effcc73877..6e1270e45f97 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -140,6 +140,12 @@ #define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0) #define DW_MIPI_NEEDS_GRF_CLK BIT(1) +#define PX30_GRF_PD_VO_CON1 0x0438 +#define PX30_DSI_FORCETXSTOPMODE (0xf << 7) +#define PX30_DSI_FORCERXMODE BIT(6) +#define PX30_DSI_TURNDISABLE BIT(5) +#define PX30_DSI_LCDC_SEL BIT(0) + #define RK3288_GRF_SOC_CON6 0x025c #define RK3288_DSI0_LCDC_SEL BIT(6) #define RK3288_DSI1_LCDC_SEL BIT(9) @@ -1127,6 +1133,24 @@ static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev) return 0; } +static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = { + { + .reg = 0xff450000, + .lcdsel_grf_reg = PX30_GRF_PD_VO_CON1, + .lcdsel_big = HIWORD_UPDATE(0, PX30_DSI_LCDC_SEL), + .lcdsel_lit = HIWORD_UPDATE(PX30_DSI_LCDC_SEL, + PX30_DSI_LCDC_SEL), + + .lanecfg1_grf_reg = PX30_GRF_PD_VO_CON1, + .lanecfg1 = HIWORD_UPDATE(0, PX30_DSI_TURNDISABLE | + PX30_DSI_FORCERXMODE | + PX30_DSI_FORCETXSTOPMODE), + + .max_data_lanes = 4, + }, + { /* sentinel */ } +}; + static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = { { .reg = 0xff960000, @@ -1195,6 +1219,9 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = { static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = { { + .compatible = "rockchip,px30-mipi-dsi", + .data = &px30_chip_data, + }, { .compatible = "rockchip,rk3288-mipi-dsi", .data = &rk3288_chip_data, }, { From 8582e244e5fe72d2e9ace186fa8f3ed3bb4122e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:22 +0100 Subject: [PATCH 07/73] drm/modes: parse_cmdline: Fix possible reference past end of string Before this commit, if the last option of a video=... option is for example "rotate" without a "=" after it then delim will point to the terminating 0 of the string, and value which is sets to will point one position past the end of the string. This commit fixes this by enforcing that the contents of delim equals '=' as it should be for options which take a value, this check is done in a new drm_mode_parse_cmdline_int helper function which factors out the common integer parsing code for all the options which take an int. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-1-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 68 ++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 88232698d7a0..3c3c7435225f 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1568,11 +1568,34 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length, return 0; } +static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) +{ + const char *value; + char *endp; + + /* + * delim must point to the '=', otherwise it is a syntax error and + * if delim points to the terminating zero, then delim + 1 wil point + * past the end of the string. + */ + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + *int_ret = simple_strtol(value, &endp, 10); + + /* Make sure we have parsed something */ + if (endp == value) + return -EINVAL; + + return 0; +} + static int drm_mode_parse_cmdline_options(char *str, size_t len, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { - unsigned int rotation = 0; + unsigned int deg, margin, rotation = 0; char *sep = str; while ((sep = strchr(sep, ','))) { @@ -1588,13 +1611,7 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, } if (!strncmp(option, "rotate", delim - option)) { - const char *value = delim + 1; - unsigned int deg; - - deg = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, °)) return -EINVAL; switch (deg) { @@ -1619,57 +1636,32 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len, } } else if (!strncmp(option, "reflect_x", delim - option)) { rotation |= DRM_MODE_REFLECT_X; - sep = delim; } else if (!strncmp(option, "reflect_y", delim - option)) { rotation |= DRM_MODE_REFLECT_Y; - sep = delim; } else if (!strncmp(option, "margin_right", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.right = margin; } else if (!strncmp(option, "margin_left", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.left = margin; } else if (!strncmp(option, "margin_top", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.top = margin; } else if (!strncmp(option, "margin_bottom", delim - option)) { - const char *value = delim + 1; - unsigned int margin; - - margin = simple_strtol(value, &sep, 10); - - /* Make sure we have parsed something */ - if (sep == value) + if (drm_mode_parse_cmdline_int(delim, &margin)) return -EINVAL; mode->tv_margins.bottom = margin; } else { return -EINVAL; } + sep = delim; } mode->rotation_reflection = rotation; From 83e14ea3a64f00897cc31974d3ae4e27e5a7405b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:23 +0100 Subject: [PATCH 08/73] drm/modes: parse_cmdline: Make various char pointers const We are not supposed to modify the passed in string, make char pointers used in drm_mode_parse_cmdline_options() const char * where possible. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-2-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 3c3c7435225f..654d4b6fecb3 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,15 +1591,15 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } -static int drm_mode_parse_cmdline_options(char *str, size_t len, +static int drm_mode_parse_cmdline_options(const char *str, size_t len, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { unsigned int deg, margin, rotation = 0; - char *sep = str; + const char *sep = str; while ((sep = strchr(sep, ','))) { - char *delim, *option; + const char *delim, *option; option = sep + 1; delim = strchr(option, '='); @@ -1718,8 +1718,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, bool named_mode = false, parse_extras = false; unsigned int bpp_off = 0, refresh_off = 0, options_off = 0; unsigned int mode_end = 0; - char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; - char *options_ptr = NULL; + const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; + const char *options_ptr = NULL; char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int ret; From c2ed3e941901810ad3d55ce1935fa22c5007fee4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:24 +0100 Subject: [PATCH 09/73] drm/modes: parse_cmdline: Stop parsing extras after bpp / refresh at ', ' Before this commit it was impossible to add an extra mode argument after a bpp or refresh specifier, combined with an option, e.g. video=HDMI-1:720x480-24e,rotate=180 would not work, either the "e" to force enable would need to be dropped or the ",rotate=180", otherwise the mode_option would not be accepted. This commit fixes this by fixing the length calculation if extras_ptr is set to stop the extra parsing at the start of the options (stop at the ',' options_ptr points to). Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-3-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 10 ++++--- .../gpu/drm/selftests/drm_cmdline_selftests.h | 1 + .../drm/selftests/test-drm_cmdline_parser.c | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 654d4b6fecb3..a8aa7955fd45 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1721,7 +1721,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; const char *options_ptr = NULL; char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; - int ret; + int i, len, ret; #ifdef CONFIG_FB if (!mode_option) @@ -1841,9 +1841,11 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, else if (refresh_ptr) extra_ptr = refresh_end_ptr; - if (extra_ptr && - extra_ptr != options_ptr) { - int len = strlen(name) - (extra_ptr - name); + if (extra_ptr) { + if (options_ptr) + len = options_ptr - extra_ptr; + else + len = strlen(extra_ptr); ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false, connector, mode); diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index 6d61a0eb5d64..ca1fc7a78953 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -60,3 +60,4 @@ cmdline_test(drm_cmdline_test_vmirror) cmdline_test(drm_cmdline_test_margin_options) cmdline_test(drm_cmdline_test_multiple_options) cmdline_test(drm_cmdline_test_invalid_option) +cmdline_test(drm_cmdline_test_bpp_extra_and_option) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index 013de9d27c35..5b8dea922257 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -992,6 +992,32 @@ static int drm_cmdline_test_invalid_option(void *ignored) return 0; } +static int drm_cmdline_test_bpp_extra_and_option(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24e,rotate=180", + &no_connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); + + FAIL_ON(mode.refresh_specified); + + FAIL_ON(!mode.bpp_specified); + FAIL_ON(mode.bpp != 24); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + #include "drm_selftest.c" static int __init test_drm_cmdline_init(void) From cfb0881b8f621b656a9e23b31944a5db94cf5842 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:25 +0100 Subject: [PATCH 10/73] drm/modes: parse_cmdline: Accept extras directly after mode combined with options Before this commit it was impossible to combine an extra mode argument specified directly after the resolution with an option, e.g. video=HDMI-1:720x480e,rotate=180 would not work, either the "e" to force enable would need to be dropped or the ",rotate=180", otherwise the mode_option would not be accepted. This commit fixes this by setting parse_extras to true in this case, so that drm_mode_parse_cmdline_res_mode() parses the extra arguments directly after the resolution. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-4-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 1 + .../gpu/drm/selftests/drm_cmdline_selftests.h | 1 + .../drm/selftests/test-drm_cmdline_parser.c | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index a8aa7955fd45..f49401124727 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1794,6 +1794,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, mode_end = refresh_off; } else if (options_ptr) { mode_end = options_off; + parse_extras = true; } else { mode_end = strlen(name); parse_extras = true; diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index ca1fc7a78953..003e2c3ffc39 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -61,3 +61,4 @@ cmdline_test(drm_cmdline_test_margin_options) cmdline_test(drm_cmdline_test_multiple_options) cmdline_test(drm_cmdline_test_invalid_option) cmdline_test(drm_cmdline_test_bpp_extra_and_option) +cmdline_test(drm_cmdline_test_extra_and_option) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index 5b8dea922257..bc4db017e993 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -1018,6 +1018,30 @@ static int drm_cmdline_test_bpp_extra_and_option(void *ignored) return 0; } +static int drm_cmdline_test_extra_and_option(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480e,rotate=180", + &no_connector, + &mode)); + FAIL_ON(!mode.specified); + FAIL_ON(mode.xres != 720); + FAIL_ON(mode.yres != 480); + FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180); + + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + #include "drm_selftest.c" static int __init test_drm_cmdline_init(void) From 739b200c2edcaaa7a86f37b0c11db57956433dfb Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:26 +0100 Subject: [PATCH 11/73] drm/modes: parse_cmdline: Rework drm_mode_parse_cmdline_options() Refactor drm_mode_parse_cmdline_options() so that it takes a pointer to the first option, rather then a pointer to the ',' before the first option. This is a preparation patch for allowing parsing of stand-alone options without a mode before them, e.g.: video=HDMI-1:margin_right=14,... Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-5-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index f49401124727..25e8edf4cfb8 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,23 +1591,21 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } -static int drm_mode_parse_cmdline_options(const char *str, size_t len, +static int drm_mode_parse_cmdline_options(const char *str, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { unsigned int deg, margin, rotation = 0; - const char *sep = str; + const char *delim, *option, *sep; - while ((sep = strchr(sep, ','))) { - const char *delim, *option; - - option = sep + 1; + option = str; + do { delim = strchr(option, '='); if (!delim) { delim = strchr(option, ','); if (!delim) - delim = str + len; + delim = option + strlen(option); } if (!strncmp(option, "rotate", delim - option)) { @@ -1661,8 +1659,9 @@ static int drm_mode_parse_cmdline_options(const char *str, size_t len, } else { return -EINVAL; } - sep = delim; - } + sep = strchr(delim, ','); + option = sep + 1; + } while (sep); mode->rotation_reflection = rotation; @@ -1855,9 +1854,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, } if (options_ptr) { - int len = strlen(name) - (options_ptr - name); - - ret = drm_mode_parse_cmdline_options(options_ptr, len, + ret = drm_mode_parse_cmdline_options(options_ptr + 1, connector, mode); if (ret) return false; From 99e2716e053734b70434502867be24d20a3e2d84 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:27 +0100 Subject: [PATCH 12/73] drm/modes: parse_cmdline: Add freestanding argument to drm_mode_parse_cmdline_options() Add a freestanding function argument to drm_mode_parse_cmdline_options() similar to how drm_mode_parse_cmdline_extra() already has this. This is a preparation patch for allowing parsing of stand-alone options without a mode before them, e.g.: video=HDMI-1:margin_right=14,... Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-6-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 25e8edf4cfb8..80cb247c83c7 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1592,6 +1592,7 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) } static int drm_mode_parse_cmdline_options(const char *str, + bool freestanding, const struct drm_connector *connector, struct drm_cmdline_mode *mode) { @@ -1663,6 +1664,9 @@ static int drm_mode_parse_cmdline_options(const char *str, option = sep + 1; } while (sep); + if (rotation && freestanding) + return -EINVAL; + mode->rotation_reflection = rotation; return 0; @@ -1855,6 +1859,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, if (options_ptr) { ret = drm_mode_parse_cmdline_options(options_ptr + 1, + false, connector, mode); if (ret) return false; From 6a2d163756545aa3180d7851d5f8322b865e72be Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:28 +0100 Subject: [PATCH 13/73] drm/modes: parse_cmdline: Set bpp/refresh_specified after successful parsing drm_connector_get_cmdline_mode() calls drm_mode_parse_command_line_for_connector() with &connector->cmdline_mode as mode argument, so anything which we store in the mode arguments gets kept even if we return false. Avoid storing a possibly false-postive bpp/refresh_specified setting in connector->cmdline_mode by moving the setting of these to after successful parsing of the bpp/refresh parts of the video= argument. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-7-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 80cb247c83c7..72828fa9fc91 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1771,10 +1771,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, /* Try to locate the bpp and refresh specifiers, if any */ bpp_ptr = strchr(name, '-'); - if (bpp_ptr) { + if (bpp_ptr) bpp_off = bpp_ptr - name; - mode->bpp_specified = true; - } refresh_ptr = strchr(name, '@'); if (refresh_ptr) { @@ -1782,7 +1780,6 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, return false; refresh_off = refresh_ptr - name; - mode->refresh_specified = true; } /* Locate the start of named options */ @@ -1825,6 +1822,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode); if (ret) return false; + + mode->bpp_specified = true; } if (refresh_ptr) { @@ -1832,6 +1831,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, &refresh_end_ptr, mode); if (ret) return false; + + mode->refresh_specified = true; } /* From 7b1cce760afe38b40f0989cdf10b2190dccf9815 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:29 +0100 Subject: [PATCH 14/73] drm/modes: parse_cmdline: Allow specifying stand-alone options Some options which can be specified on the commandline, such as margin_right=..., margin_left=..., etc. are applied not only to the specified mode, but to all modes. As such it would be nice if the user can simply say e.g. video=HDMI-1:margin_right=14,margin_left=24,margin_bottom=36,margin_top=42 This commit refactors drm_mode_parse_command_line_for_connector() to add support for this, and as a nice side effect also cleans up the function a bit. Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-8-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 92 +++++++------------ .../gpu/drm/selftests/drm_cmdline_selftests.h | 2 + .../drm/selftests/test-drm_cmdline_parser.c | 50 ++++++++++ 3 files changed, 86 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 72828fa9fc91..2e82603f5d0a 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1677,17 +1677,6 @@ static const char * const drm_named_modes_whitelist[] = { "PAL", }; -static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) - if (!strncmp(mode, drm_named_modes_whitelist[i], size)) - return true; - - return false; -} - /** * drm_mode_parse_command_line_for_connector - parse command line modeline for connector * @mode_option: optional per connector mode option @@ -1718,7 +1707,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, struct drm_cmdline_mode *mode) { const char *name; - bool named_mode = false, parse_extras = false; + bool freestanding = false, parse_extras = false; unsigned int bpp_off = 0, refresh_off = 0, options_off = 0; unsigned int mode_end = 0; const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; @@ -1738,49 +1727,14 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, name = mode_option; - /* - * This is a bit convoluted. To differentiate between the - * named modes and poorly formatted resolutions, we need a - * bunch of things: - * - We need to make sure that the first character (which - * would be our resolution in X) is a digit. - * - If not, then it's either a named mode or a force on/off. - * To distinguish between the two, we need to run the - * extra parsing function, and if not, then we consider it - * a named mode. - * - * If this isn't enough, we should add more heuristics here, - * and matching unit-tests. - */ - if (!isdigit(name[0]) && name[0] != 'x') { - unsigned int namelen = strlen(name); - - /* - * Only the force on/off options can be in that case, - * and they all take a single character. - */ - if (namelen == 1) { - ret = drm_mode_parse_cmdline_extra(name, namelen, true, - connector, mode); - if (!ret) - return true; - } - - named_mode = true; - } - /* Try to locate the bpp and refresh specifiers, if any */ bpp_ptr = strchr(name, '-'); if (bpp_ptr) bpp_off = bpp_ptr - name; refresh_ptr = strchr(name, '@'); - if (refresh_ptr) { - if (named_mode) - return false; - + if (refresh_ptr) refresh_off = refresh_ptr - name; - } /* Locate the start of named options */ options_ptr = strchr(name, ','); @@ -1800,23 +1754,45 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, parse_extras = true; } - if (named_mode) { - if (mode_end + 1 > DRM_DISPLAY_MODE_LEN) - return false; + /* First check for a named mode */ + for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) { + ret = str_has_prefix(name, drm_named_modes_whitelist[i]); + if (ret == mode_end) { + if (refresh_ptr) + return false; /* named + refresh is invalid */ - if (!drm_named_mode_is_in_whitelist(name, mode_end)) - return false; + strcpy(mode->name, drm_named_modes_whitelist[i]); + mode->specified = true; + break; + } + } - strscpy(mode->name, name, mode_end + 1); - } else { + /* No named mode? Check for a normal mode argument, e.g. 1024x768 */ + if (!mode->specified && isdigit(name[0])) { ret = drm_mode_parse_cmdline_res_mode(name, mode_end, parse_extras, connector, mode); if (ret) return false; + + mode->specified = true; + } + + /* No mode? Check for freestanding extras and/or options */ + if (!mode->specified) { + unsigned int len = strlen(mode_option); + + if (bpp_ptr || refresh_ptr) + return false; /* syntax error */ + + if (len == 1 || (len >= 2 && mode_option[1] == ',')) + extra_ptr = mode_option; + else + options_ptr = mode_option - 1; + + freestanding = true; } - mode->specified = true; if (bpp_ptr) { ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode); @@ -1852,7 +1828,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, else len = strlen(extra_ptr); - ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false, + ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding, connector, mode); if (ret) return false; @@ -1860,7 +1836,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, if (options_ptr) { ret = drm_mode_parse_cmdline_options(options_ptr + 1, - false, + freestanding, connector, mode); if (ret) return false; diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index 003e2c3ffc39..aee92ac2cc21 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -62,3 +62,5 @@ cmdline_test(drm_cmdline_test_multiple_options) cmdline_test(drm_cmdline_test_invalid_option) cmdline_test(drm_cmdline_test_bpp_extra_and_option) cmdline_test(drm_cmdline_test_extra_and_option) +cmdline_test(drm_cmdline_test_freestanding_options) +cmdline_test(drm_cmdline_test_freestanding_force_e_and_options) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index bc4db017e993..8248d4aa5aaa 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -1042,6 +1042,56 @@ static int drm_cmdline_test_extra_and_option(void *ignored) return 0; } +static int drm_cmdline_test_freestanding_options(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("margin_right=14,margin_left=24,margin_bottom=36,margin_top=42", + &no_connector, + &mode)); + FAIL_ON(mode.specified); + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.tv_margins.right != 14); + FAIL_ON(mode.tv_margins.left != 24); + FAIL_ON(mode.tv_margins.bottom != 36); + FAIL_ON(mode.tv_margins.top != 42); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + +static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42", + &no_connector, + &mode)); + FAIL_ON(mode.specified); + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.tv_margins.right != 14); + FAIL_ON(mode.tv_margins.left != 24); + FAIL_ON(mode.tv_margins.bottom != 36); + FAIL_ON(mode.tv_margins.top != 42); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_ON); + + return 0; +} + #include "drm_selftest.c" static int __init test_drm_cmdline_init(void) From 4e7a4a6fbdc669c44e6079f9d5eb25673749455f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:30 +0100 Subject: [PATCH 15/73] drm/modes: parse_cmdline: Add support for specifying panel_orientation (v2) Sometimes we want to override a connector's panel_orientation from the kernel commandline. Either for testing and for special cases, e.g. a kiosk like setup which uses a TV mounted in portrait mode. Users can already specify a "rotate" option through a video= kernel cmdline option. But that only supports 0/180 degrees (see drm_client_modeset TODO) and only works for in kernel modeset clients, not for userspace kms users. The "panel-orientation" connector property OTOH does support 90/270 degrees as it leaves dealing with the rotation up to userspace and this does work for userspace kms clients (at least those which support this property). Changes in v2: -Add missing ':' after @panel_orientation (reported by kbuild test robot) BugLink: https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/83 Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-9-hdegoede@redhat.com --- Documentation/fb/modedb.rst | 3 ++ drivers/gpu/drm/drm_modes.c | 32 +++++++++++++++++++ .../gpu/drm/selftests/drm_cmdline_selftests.h | 1 + .../drm/selftests/test-drm_cmdline_parser.c | 22 +++++++++++++ include/drm/drm_connector.h | 8 +++++ 5 files changed, 66 insertions(+) diff --git a/Documentation/fb/modedb.rst b/Documentation/fb/modedb.rst index 9c4e3fd39e6d..624d08fd2856 100644 --- a/Documentation/fb/modedb.rst +++ b/Documentation/fb/modedb.rst @@ -65,6 +65,9 @@ Valid options are:: - reflect_y (boolean): Perform an axial symmetry on the Y axis - rotate (integer): Rotate the initial framebuffer by x degrees. Valid values are 0, 90, 180 and 270. + - panel_orientation, one of "normal", "upside_down", "left_side_up", or + "right_side_up". For KMS drivers only, this sets the "panel orientation" + property on the kms connector as hint for kms users. ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2e82603f5d0a..119fed7ab815 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,6 +1591,33 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } +static int drm_mode_parse_panel_orientation(const char *delim, + struct drm_cmdline_mode *mode) +{ + const char *value; + + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + delim = strchr(value, ','); + if (!delim) + delim = value + strlen(value); + + if (!strncmp(value, "normal", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (!strncmp(value, "upside_down", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (!strncmp(value, "left_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else if (!strncmp(value, "right_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else + return -EINVAL; + + return 0; +} + static int drm_mode_parse_cmdline_options(const char *str, bool freestanding, const struct drm_connector *connector, @@ -1657,6 +1684,9 @@ static int drm_mode_parse_cmdline_options(const char *str, return -EINVAL; mode->tv_margins.bottom = margin; + } else if (!strncmp(option, "panel_orientation", delim - option)) { + if (drm_mode_parse_panel_orientation(delim, mode)) + return -EINVAL; } else { return -EINVAL; } @@ -1715,6 +1745,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int i, len, ret; + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + #ifdef CONFIG_FB if (!mode_option) mode_option = fb_mode_option; diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index aee92ac2cc21..ceac7af9a172 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -64,3 +64,4 @@ cmdline_test(drm_cmdline_test_bpp_extra_and_option) cmdline_test(drm_cmdline_test_extra_and_option) cmdline_test(drm_cmdline_test_freestanding_options) cmdline_test(drm_cmdline_test_freestanding_force_e_and_options) +cmdline_test(drm_cmdline_test_panel_orientation) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index 8248d4aa5aaa..520f3e66a384 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -1092,6 +1092,28 @@ static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored) return 0; } +static int drm_cmdline_test_panel_orientation(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down", + &no_connector, + &mode)); + FAIL_ON(mode.specified); + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + #include "drm_selftest.c" static int __init test_drm_cmdline_init(void) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 17b728d9c73d..221910948b37 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1069,6 +1069,14 @@ struct drm_cmdline_mode { */ unsigned int rotation_reflection; + /** + * @panel_orientation: + * + * drm-connector "panel orientation" property override value, + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set. + */ + enum drm_panel_orientation panel_orientation; + /** * @tv_margins: TV margins to apply to the mode. */ From 5b926617cdef41ce0696e09834991194b1759e28 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:31 +0100 Subject: [PATCH 16/73] drm/modes: parse_cmdline: Remove some unnecessary code (v2) fb_get_options() will return fb_mode_option if no video= argument is present on the kernel commandline, so there is no need to also do this in drm_mode_parse_command_line_for_connector() as our only caller uses fb_get_options() to get the mode_option argument. Changes in v2: -Split out the changes dealing with the initialization of the mode struct into a separate patch Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-10-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 119fed7ab815..beb764efe6b3 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1747,11 +1747,6 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; -#ifdef CONFIG_FB - if (!mode_option) - mode_option = fb_mode_option; -#endif - if (!mode_option) { mode->specified = false; return false; From d1fe276b5115f0d581c3cfe6154633b3547e8aab Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:32 +0100 Subject: [PATCH 17/73] drm/modes: parse_cmdline: Explicitly memset the passed in drm_cmdline_mode struct Instead of only setting mode->specified on false on an early exit and leaving e.g. mode->bpp_specified and mode->refresh_specified as is, lets be consistent and just zero out the entire passed in struct at the top of drm_mode_parse_command_line_for_connector() Changes in v3: -Drop "mode->specified = false;" line instead of the "return false;" (oops) This crasher was reported-by: kernel test robot Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-11-hdegoede@redhat.com --- drivers/gpu/drm/drm_modes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index beb764efe6b3..2a4eb619d7ad 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1745,12 +1745,11 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int i, len, ret; + memset(mode, 0, sizeof(*mode)); mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; - if (!mode_option) { - mode->specified = false; + if (!mode_option) return false; - } name = mode_option; From f2f7df4fbfb8fcfa8fd5900ef1e438ab400ab789 Mon Sep 17 00:00:00 2001 From: zhengbin Date: Mon, 16 Dec 2019 11:54:19 +0800 Subject: [PATCH 18/73] drm/bochs: Remove unneeded semicolon Fixes coccicheck warning: drivers/gpu/drm/bochs/bochs_hw.c:258:2-3: Unneeded semicolon Reported-by: Hulk Robot Signed-off-by: zhengbin Link: http://patchwork.freedesktop.org/patch/msgid/1576468459-67216-1-git-send-email-zhengbin13@huawei.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/bochs/bochs_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c index e567bdfa2ab8..b615b7dfdd9d 100644 --- a/drivers/gpu/drm/bochs/bochs_hw.c +++ b/drivers/gpu/drm/bochs/bochs_hw.c @@ -255,7 +255,7 @@ void bochs_hw_setformat(struct bochs_device *bochs, DRM_ERROR("%s: Huh? Got framebuffer format 0x%x", __func__, format->format); break; - }; + } } void bochs_hw_setbase(struct bochs_device *bochs, From 4ad7056a4014e1cbc77f7b0361398fa26d2817b1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 13 Dec 2019 18:26:10 +0100 Subject: [PATCH 19/73] drm/virtio: plane_state->fb iff plane_state->crtc Checking both is one too much, so wrap a WARN_ON around it to stope the copypasta. Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20191213172612.1514842-8-daniel.vetter@ffwll.ch Cc: David Airlie Cc: Gerd Hoffmann Cc: virtualization@lists.linux-foundation.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index bc4bc4475a8c..947e65b51555 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -88,7 +88,7 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, struct drm_crtc_state *crtc_state; int ret; - if (!state->fb || !state->crtc) + if (!state->fb || WARN_ON(!state->crtc)) return 0; crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); From 3954ff10e06e4fbc548fc02ff1fcaaac3228fed5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 12 Dec 2019 13:53:44 +0100 Subject: [PATCH 20/73] drm/virtio: skip set_scanout if framebuffer didn't change v2: also check src rect (Chia-I Wu). Signed-off-by: Gerd Hoffmann Reviewed-by: Chia-I Wu Link: http://patchwork.freedesktop.org/patch/msgid/20191212125346.8334-2-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_plane.c | 35 +++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 947e65b51555..32de6bd9893a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -151,20 +151,27 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, if (bo->dumb) virtio_gpu_update_dumb_bo(vgdev, bo, plane->state); - DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", - bo->hw_res_handle, - plane->state->crtc_w, plane->state->crtc_h, - plane->state->crtc_x, plane->state->crtc_y, - plane->state->src_w >> 16, - plane->state->src_h >> 16, - plane->state->src_x >> 16, - plane->state->src_y >> 16); - virtio_gpu_cmd_set_scanout(vgdev, output->index, - bo->hw_res_handle, - plane->state->src_w >> 16, - plane->state->src_h >> 16, - plane->state->src_x >> 16, - plane->state->src_y >> 16); + if (plane->state->fb != old_state->fb || + plane->state->src_w != old_state->src_w || + plane->state->src_h != old_state->src_h || + plane->state->src_x != old_state->src_x || + plane->state->src_y != old_state->src_y) { + DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", + bo->hw_res_handle, + plane->state->crtc_w, plane->state->crtc_h, + plane->state->crtc_x, plane->state->crtc_y, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->src_x >> 16, + plane->state->src_y >> 16); + virtio_gpu_cmd_set_scanout(vgdev, output->index, + bo->hw_res_handle, + plane->state->src_w >> 16, + plane->state->src_h >> 16, + plane->state->src_x >> 16, + plane->state->src_y >> 16); + } + virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, plane->state->src_x >> 16, plane->state->src_y >> 16, From 7082e7a438db2abf13e4e1fa904875034de88b6b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 12 Dec 2019 13:53:45 +0100 Subject: [PATCH 21/73] drm/virtio: batch display update commands. When the driver submits multiple commands in a row it makes sense to notify the host only after submitting the last one, so the host can process them all at once, with a single vmexit. Add functions to enable/disable notifications to allow that. Use the new functions for primary plane updates. Signed-off-by: Gerd Hoffmann Reviewed-by: Chia-I Wu Link: http://patchwork.freedesktop.org/patch/msgid/20191212125346.8334-3-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_drv.h | 6 ++++++ drivers/gpu/drm/virtio/virtgpu_plane.c | 4 ++++ drivers/gpu/drm/virtio/virtgpu_vq.c | 23 +++++++++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index eedae2a7b532..29cf005ed6b9 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -183,6 +183,9 @@ struct virtio_gpu_device { struct kmem_cache *vbufs; bool vqs_ready; + bool disable_notify; + bool pending_notify; + struct ida resource_ida; wait_queue_head_t resp_wq; @@ -335,6 +338,9 @@ void virtio_gpu_dequeue_ctrl_func(struct work_struct *work); void virtio_gpu_dequeue_cursor_func(struct work_struct *work); void virtio_gpu_dequeue_fence_func(struct work_struct *work); +void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev); +void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev); + /* virtio_gpu_display.c */ int virtio_gpu_framebuffer_init(struct drm_device *dev, struct virtio_gpu_framebuffer *vgfb, diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 32de6bd9893a..930860906536 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -146,6 +146,8 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, return; } + virtio_gpu_disable_notify(vgdev); + vgfb = to_virtio_gpu_framebuffer(plane->state->fb); bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); if (bo->dumb) @@ -177,6 +179,8 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, plane->state->src_y >> 16, plane->state->src_w >> 16, plane->state->src_h >> 16); + + virtio_gpu_enable_notify(vgdev); } static int virtio_gpu_cursor_prepare_fb(struct drm_plane *plane, diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 9274c4063c70..5914e79d3429 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -404,8 +404,12 @@ again: } notify = virtio_gpu_queue_ctrl_buffer_locked(vgdev, vbuf, vout); spin_unlock(&vgdev->ctrlq.qlock); - if (notify) - virtqueue_notify(vgdev->ctrlq.vq); + if (notify) { + if (vgdev->disable_notify) + vgdev->pending_notify = true; + else + virtqueue_notify(vgdev->ctrlq.vq); + } if (sgt) { sg_free_table(sgt); @@ -413,6 +417,21 @@ again: } } +void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev) +{ + vgdev->disable_notify = true; +} + +void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev) +{ + vgdev->disable_notify = false; + + if (!vgdev->pending_notify) + return; + vgdev->pending_notify = false; + virtqueue_notify(vgdev->ctrlq.vq); +} + static void virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev, struct virtio_gpu_vbuffer *vbuf) { From c096761718de0a6ac3205d80b12292c943235c4b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 12 Dec 2019 13:53:46 +0100 Subject: [PATCH 22/73] drm/virtio: use damage info for display updates. v2: remove shift by src_{x,y}, drm_atomic_helper_damage_merged() handles that for us (Chia-I Wu). Signed-off-by: Gerd Hoffmann Reviewed-by: Chia-I Wu Link: http://patchwork.freedesktop.org/patch/msgid/20191212125346.8334-4-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_plane.c | 41 +++++++++++++++----------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 930860906536..ac42c84d2d7f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -24,6 +24,7 @@ */ #include +#include #include #include @@ -103,22 +104,26 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane, } static void virtio_gpu_update_dumb_bo(struct virtio_gpu_device *vgdev, - struct virtio_gpu_object *bo, - struct drm_plane_state *state) + struct drm_plane_state *state, + struct drm_rect *rect) { + struct virtio_gpu_object *bo = + gem_to_virtio_gpu_obj(state->fb->obj[0]); struct virtio_gpu_object_array *objs; + uint32_t w = rect->x2 - rect->x1; + uint32_t h = rect->y2 - rect->y1; + uint32_t x = rect->x1; + uint32_t y = rect->y1; + uint32_t off = x * state->fb->format->cpp[0] + + y * state->fb->pitches[0]; objs = virtio_gpu_array_alloc(1); if (!objs) return; virtio_gpu_array_add_obj(objs, &bo->base.base); - virtio_gpu_cmd_transfer_to_host_2d - (vgdev, 0, - state->src_w >> 16, - state->src_h >> 16, - state->src_x >> 16, - state->src_y >> 16, - objs, NULL); + + virtio_gpu_cmd_transfer_to_host_2d(vgdev, off, w, h, x, y, + objs, NULL); } static void virtio_gpu_primary_plane_update(struct drm_plane *plane, @@ -127,8 +132,8 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, struct drm_device *dev = plane->dev; struct virtio_gpu_device *vgdev = dev->dev_private; struct virtio_gpu_output *output = NULL; - struct virtio_gpu_framebuffer *vgfb; struct virtio_gpu_object *bo; + struct drm_rect rect; if (plane->state->crtc) output = drm_crtc_to_virtio_gpu_output(plane->state->crtc); @@ -146,12 +151,14 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, return; } + if (!drm_atomic_helper_damage_merged(old_state, plane->state, &rect)) + return; + virtio_gpu_disable_notify(vgdev); - vgfb = to_virtio_gpu_framebuffer(plane->state->fb); - bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]); + bo = gem_to_virtio_gpu_obj(plane->state->fb->obj[0]); if (bo->dumb) - virtio_gpu_update_dumb_bo(vgdev, bo, plane->state); + virtio_gpu_update_dumb_bo(vgdev, plane->state, &rect); if (plane->state->fb != old_state->fb || plane->state->src_w != old_state->src_w || @@ -175,10 +182,10 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, } virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, - plane->state->src_x >> 16, - plane->state->src_y >> 16, - plane->state->src_w >> 16, - plane->state->src_h >> 16); + rect.x1, + rect.y1, + rect.x2 - rect.x1, + rect.y2 - rect.y1); virtio_gpu_enable_notify(vgdev); } From 7befe621ff81d8063c13d6452b04e6ebc92b22fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 13 Dec 2019 19:43:45 +0200 Subject: [PATCH 23/73] drm/edid: Abstract away cea_edid_modes[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're going to need two cea mode tables (one for VICs < 128, another one for VICs >= 193). To that end replace the direct edid_cea_modes[] lookups with a function call. And we'll rename the array to edid_cea_modes_0[] to indicate how it's to be indexed. v2: Fix typos (Tom) Drop the pointless NULL checks in the loops (Tom) Assign when declaring (Tom) Improve the comment for cea_modes_*[] to indicate that one should always use cea_mode_for_vic() (Tom) Cc: Tom Anderson Cc: Hans Verkuil Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213174348.27261-2-ville.syrjala@linux.intel.com Reviewed-by: Thomas Anderson --- drivers/gpu/drm/drm_edid.c | 67 +++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5b33b7cfd645..00a543b9daab 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -710,12 +710,11 @@ static const struct minimode extra_modes[] = { }; /* - * Probably taken from CEA-861 spec. - * This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c. + * From CEA/CTA-861 spec. * - * Index using the VIC. + * Do not access directly, instead always use cea_mode_for_vic(). */ -static const struct drm_display_mode edid_cea_modes[] = { +static const struct drm_display_mode edid_cea_modes_0[] = { /* 0 - dummy, VICs start at 1 */ { }, /* 1 - 640x480@60Hz 4:3 */ @@ -3071,6 +3070,25 @@ static u8 *drm_find_cea_extension(const struct edid *edid) return cea; } +static const struct drm_display_mode *cea_mode_for_vic(u8 vic) +{ + if (!vic) + return NULL; + if (vic < ARRAY_SIZE(edid_cea_modes_0)) + return &edid_cea_modes_0[vic]; + return NULL; +} + +static u8 cea_num_vics(void) +{ + return ARRAY_SIZE(edid_cea_modes_0); +} + +static u8 cea_next_vic(u8 vic) +{ + return vic + 1; +} + /* * Calculate the alternate clock for the CEA mode * (60Hz vs. 59.94Hz etc.) @@ -3108,14 +3126,14 @@ cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode) * get the other variants by simply increasing the * vertical front porch length. */ - BUILD_BUG_ON(edid_cea_modes[8].vtotal != 262 || - edid_cea_modes[9].vtotal != 262 || - edid_cea_modes[12].vtotal != 262 || - edid_cea_modes[13].vtotal != 262 || - edid_cea_modes[23].vtotal != 312 || - edid_cea_modes[24].vtotal != 312 || - edid_cea_modes[27].vtotal != 312 || - edid_cea_modes[28].vtotal != 312); + BUILD_BUG_ON(cea_mode_for_vic(8)->vtotal != 262 || + cea_mode_for_vic(9)->vtotal != 262 || + cea_mode_for_vic(12)->vtotal != 262 || + cea_mode_for_vic(13)->vtotal != 262 || + cea_mode_for_vic(23)->vtotal != 312 || + cea_mode_for_vic(24)->vtotal != 312 || + cea_mode_for_vic(27)->vtotal != 312 || + cea_mode_for_vic(28)->vtotal != 312); if (((vic == 8 || vic == 9 || vic == 12 || vic == 13) && mode->vtotal < 263) || @@ -3143,8 +3161,8 @@ static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_m if (to_match->picture_aspect_ratio) match_flags |= DRM_MODE_MATCH_ASPECT_RATIO; - for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) { - struct drm_display_mode cea_mode = edid_cea_modes[vic]; + for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) { + struct drm_display_mode cea_mode = *cea_mode_for_vic(vic); unsigned int clock1, clock2; /* Check both 60Hz and 59.94Hz */ @@ -3182,8 +3200,8 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match) if (to_match->picture_aspect_ratio) match_flags |= DRM_MODE_MATCH_ASPECT_RATIO; - for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) { - struct drm_display_mode cea_mode = edid_cea_modes[vic]; + for (vic = 1; vic < cea_num_vics(); vic = cea_next_vic(vic)) { + struct drm_display_mode cea_mode = *cea_mode_for_vic(vic); unsigned int clock1, clock2; /* Check both 60Hz and 59.94Hz */ @@ -3206,12 +3224,17 @@ EXPORT_SYMBOL(drm_match_cea_mode); static bool drm_valid_cea_vic(u8 vic) { - return vic > 0 && vic < ARRAY_SIZE(edid_cea_modes); + return cea_mode_for_vic(vic) != NULL; } static enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code) { - return edid_cea_modes[video_code].picture_aspect_ratio; + const struct drm_display_mode *mode = cea_mode_for_vic(video_code); + + if (mode) + return mode->picture_aspect_ratio; + + return HDMI_PICTURE_ASPECT_NONE; } static enum hdmi_picture_aspect drm_get_hdmi_aspect_ratio(const u8 video_code) @@ -3323,7 +3346,7 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) unsigned int clock1, clock2; if (drm_valid_cea_vic(vic)) { - cea_mode = &edid_cea_modes[vic]; + cea_mode = cea_mode_for_vic(vic); clock2 = cea_mode_alternate_clock(cea_mode); } else { vic = drm_match_hdmi_mode(mode); @@ -3398,7 +3421,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector, if (!drm_valid_cea_vic(vic)) return NULL; - newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]); + newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic)); if (!newmode) return NULL; @@ -3432,7 +3455,7 @@ static int do_y420vdb_modes(struct drm_connector *connector, if (!drm_valid_cea_vic(vic)) continue; - newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]); + newmode = drm_mode_duplicate(dev, cea_mode_for_vic(vic)); if (!newmode) break; bitmap_set(hdmi->y420_vdb_modes, vic, 1); @@ -4001,7 +4024,7 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode) vic = drm_match_cea_mode_clock_tolerance(mode, 5); if (drm_valid_cea_vic(vic)) { type = "CEA"; - cea_mode = &edid_cea_modes[vic]; + cea_mode = cea_mode_for_vic(vic); clock1 = cea_mode->clock; clock2 = cea_mode_alternate_clock(cea_mode); } else { From f7655d42fceefea7e4c2d07eb04381d086b7090e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 13 Dec 2019 19:43:46 +0200 Subject: [PATCH 24/73] drm/edid: Add CTA-861-G modes with VIC >= 193 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a second table to the cea modes with VIC >= 193. v2: Improve the comment for cea_modes_*[] to indicate that one should always use cea_mode_for_vic() (Tom) Cc: Hans Verkuil Reviewed-by: Manasi Navare Reviewed-by: Thomas Anderson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213174348.27261-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_edid.c | 151 ++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 00a543b9daab..2787ad0ef881 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1379,6 +1379,149 @@ static const struct drm_display_mode edid_cea_modes_0[] = { .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, }; +/* + * From CEA/CTA-861 spec. + * + * Do not access directly, instead always use cea_mode_for_vic(). + */ +static const struct drm_display_mode edid_cea_modes_193[] = { + /* 193 - 5120x2160@120Hz 64:27 */ + { DRM_MODE("5120x2160", DRM_MODE_TYPE_DRIVER, 1485000, 5120, 5284, + 5372, 5500, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 194 - 7680x4320@24Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232, + 10408, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 195 - 7680x4320@25Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032, + 10208, 10800, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 196 - 7680x4320@30Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232, + 8408, 9000, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 197 - 7680x4320@48Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232, + 10408, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 198 - 7680x4320@50Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032, + 10208, 10800, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 199 - 7680x4320@60Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232, + 8408, 9000, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 200 - 7680x4320@100Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792, + 9968, 10560, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 201 - 7680x4320@120Hz 16:9 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032, + 8208, 8800, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, }, + /* 202 - 7680x4320@24Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10232, + 10408, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 203 - 7680x4320@25Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 10032, + 10208, 10800, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 204 - 7680x4320@30Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 1188000, 7680, 8232, + 8408, 9000, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 205 - 7680x4320@48Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10232, + 10408, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 206 - 7680x4320@50Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 10032, + 10208, 10800, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 207 - 7680x4320@60Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 2376000, 7680, 8232, + 8408, 9000, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 208 - 7680x4320@100Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 9792, + 9968, 10560, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 209 - 7680x4320@120Hz 64:27 */ + { DRM_MODE("7680x4320", DRM_MODE_TYPE_DRIVER, 4752000, 7680, 8032, + 8208, 8800, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 210 - 10240x4320@24Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 11732, + 11908, 12500, 0, 4320, 4336, 4356, 4950, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 211 - 10240x4320@25Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 12732, + 12908, 13500, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 212 - 10240x4320@30Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 1485000, 10240, 10528, + 10704, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 213 - 10240x4320@48Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 11732, + 11908, 12500, 0, 4320, 4336, 4356, 4950, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 48, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 214 - 10240x4320@50Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 12732, + 12908, 13500, 0, 4320, 4336, 4356, 4400, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 215 - 10240x4320@60Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 2970000, 10240, 10528, + 10704, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 216 - 10240x4320@100Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 12432, + 12608, 13200, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 217 - 10240x4320@120Hz 64:27 */ + { DRM_MODE("10240x4320", DRM_MODE_TYPE_DRIVER, 5940000, 10240, 10528, + 10704, 11000, 0, 4320, 4336, 4356, 4500, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, + /* 218 - 4096x2160@100Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4896, + 4984, 5280, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, + /* 219 - 4096x2160@120Hz 256:135 */ + { DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 1188000, 4096, 4184, + 4272, 4400, 0, 2160, 2168, 2178, 2250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), + .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135, }, +}; + /* * HDMI 1.4 4k modes. Index using the VIC. */ @@ -3076,17 +3219,21 @@ static const struct drm_display_mode *cea_mode_for_vic(u8 vic) return NULL; if (vic < ARRAY_SIZE(edid_cea_modes_0)) return &edid_cea_modes_0[vic]; + if (vic >= 193 && vic < 193 + ARRAY_SIZE(edid_cea_modes_193)) + return &edid_cea_modes_193[vic - 193]; return NULL; } static u8 cea_num_vics(void) { - return ARRAY_SIZE(edid_cea_modes_0); + return 193 + ARRAY_SIZE(edid_cea_modes_193); } static u8 cea_next_vic(u8 vic) { - return vic + 1; + if (++vic == ARRAY_SIZE(edid_cea_modes_0)) + vic = 193; + return vic; } /* From 8c1b2bd9323855c03296d38d93deb2e470d8b7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 13 Dec 2019 19:43:47 +0200 Subject: [PATCH 25/73] drm/edid: Throw away the dummy VIC 0 cea mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the cea mode handling is not 100% tied to the single array the dummy VIC 0 mode is pretty much pointles. Throw it out. v2: Rebase Cc: Tom Anderson Cc: Hans Verkuil Cc: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213174348.27261-4-ville.syrjala@linux.intel.com Reviewed-by: Thomas Anderson --- drivers/gpu/drm/drm_edid.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 2787ad0ef881..8bc69da53c2e 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -714,9 +714,7 @@ static const struct minimode extra_modes[] = { * * Do not access directly, instead always use cea_mode_for_vic(). */ -static const struct drm_display_mode edid_cea_modes_0[] = { - /* 0 - dummy, VICs start at 1 */ - { }, +static const struct drm_display_mode edid_cea_modes_1[] = { /* 1 - 640x480@60Hz 4:3 */ { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, @@ -3215,10 +3213,8 @@ static u8 *drm_find_cea_extension(const struct edid *edid) static const struct drm_display_mode *cea_mode_for_vic(u8 vic) { - if (!vic) - return NULL; - if (vic < ARRAY_SIZE(edid_cea_modes_0)) - return &edid_cea_modes_0[vic]; + if (vic >= 1 && vic < 1 + ARRAY_SIZE(edid_cea_modes_1)) + return &edid_cea_modes_1[vic - 1]; if (vic >= 193 && vic < 193 + ARRAY_SIZE(edid_cea_modes_193)) return &edid_cea_modes_193[vic - 193]; return NULL; @@ -3231,7 +3227,7 @@ static u8 cea_num_vics(void) static u8 cea_next_vic(u8 vic) { - if (++vic == ARRAY_SIZE(edid_cea_modes_0)) + if (++vic == 1 + ARRAY_SIZE(edid_cea_modes_1)) vic = 193; return vic; } From 9212f8ee412012252d4d7c93ea262b415ced00e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 13 Dec 2019 19:43:48 +0200 Subject: [PATCH 26/73] drm/edid: Make sure the CEA mode arrays have the correct amount of modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We depend on a specific relationship between the VIC number and the index in the CEA mode arrays. Assert that the arrays have the expected size to make sure we've not accidentally left holes in them. v2: Pimp the BUILD_BUG_ON()s v3: Fix typos (Manasi) Cc: Hans Verkuil Reviewed-by: Manasi Navare Reviewed-by: Thomas Anderson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20191213174348.27261-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/drm_edid.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 8bc69da53c2e..ec5b88120428 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -3213,6 +3213,9 @@ static u8 *drm_find_cea_extension(const struct edid *edid) static const struct drm_display_mode *cea_mode_for_vic(u8 vic) { + BUILD_BUG_ON(1 + ARRAY_SIZE(edid_cea_modes_1) - 1 != 127); + BUILD_BUG_ON(193 + ARRAY_SIZE(edid_cea_modes_193) - 1 != 219); + if (vic >= 1 && vic < 1 + ARRAY_SIZE(edid_cea_modes_1)) return &edid_cea_modes_1[vic - 1]; if (vic >= 193 && vic < 193 + ARRAY_SIZE(edid_cea_modes_193)) From fb6c7ab8718eb2543695d77ad8302ff81e8e1e32 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 14:30:43 +0200 Subject: [PATCH 27/73] drm/print: introduce new struct drm_device based logging macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new struct drm_device based logging macros modeled after the core kernel device based logging macros. These would be preferred over the drm printk and struct device based macros in drm code, where possible. We have existing drm specific struct device based logging functions, but they are too verbose to use for two main reasons: * The names are unnecessarily long, for example DRM_DEV_DEBUG_KMS(). * The use of struct device over struct drm_device is too generic for most users, leading to an extra dereference. For example: DRM_DEV_DEBUG_KMS(drm->dev, "Hello, world\n"); vs. drm_dbg_kms(drm, "Hello, world\n"); It's a matter of taste, but the SHOUTING UPPERCASE has been argued to be less readable than lowercase. Some names are changed from old DRM names to be based on the core kernel logging functions. For example, NOTE -> notice, ERROR -> err, DEBUG -> dbg. Due to the conflation of DRM_DEBUG and DRM_DEBUG_DRIVER macro use (DRM_DEBUG is used widely in drivers though it's supposed to be a core debugging category), they are named as drm_dbg_core and drm_dbg, respectively. The drm_err and _once/_ratelimited variants no longer include the function name in order to be able to use the core device based logging macros. Arguably this is not a significant change; error messages should not be so common to be only distinguishable by the function name. Ratelimited debug logging macros are to be added later. Cc: Sam Ravnborg Acked-by: Ville Syrjälä Reviewed-by: Rodrigo Vivi Acked-by: Sean Paul Acked-by: Sam Ravnborg Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191210123050.8799-1-jani.nikula@intel.com --- include/drm/drm_print.h | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h index 085a9685270c..8f99d389792d 100644 --- a/include/drm/drm_print.h +++ b/include/drm/drm_print.h @@ -322,6 +322,8 @@ static inline bool drm_debug_enabled(enum drm_debug_category category) /* * struct device based logging + * + * Prefer drm_device based logging over device or prink based logging. */ __printf(3, 4) @@ -417,8 +419,71 @@ void drm_dev_dbg(const struct device *dev, enum drm_debug_category category, _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRM_UT_PRIME, \ fmt, ##__VA_ARGS__) +/* + * struct drm_device based logging + * + * Prefer drm_device based logging over device or prink based logging. + */ + +/* Helper for struct drm_device based logging. */ +#define __drm_printk(drm, level, type, fmt, ...) \ + dev_##level##type((drm)->dev, "[drm] " fmt, ##__VA_ARGS__) + + +#define drm_info(drm, fmt, ...) \ + __drm_printk((drm), info,, fmt, ##__VA_ARGS__) + +#define drm_notice(drm, fmt, ...) \ + __drm_printk((drm), notice,, fmt, ##__VA_ARGS__) + +#define drm_warn(drm, fmt, ...) \ + __drm_printk((drm), warn,, fmt, ##__VA_ARGS__) + +#define drm_err(drm, fmt, ...) \ + __drm_printk((drm), err,, "*ERROR* " fmt, ##__VA_ARGS__) + + +#define drm_info_once(drm, fmt, ...) \ + __drm_printk((drm), info, _once, fmt, ##__VA_ARGS__) + +#define drm_notice_once(drm, fmt, ...) \ + __drm_printk((drm), notice, _once, fmt, ##__VA_ARGS__) + +#define drm_warn_once(drm, fmt, ...) \ + __drm_printk((drm), warn, _once, fmt, ##__VA_ARGS__) + +#define drm_err_once(drm, fmt, ...) \ + __drm_printk((drm), err, _once, "*ERROR* " fmt, ##__VA_ARGS__) + + +#define drm_err_ratelimited(drm, fmt, ...) \ + __drm_printk((drm), err, _ratelimited, "*ERROR* " fmt, ##__VA_ARGS__) + + +#define drm_dbg_core(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_CORE, fmt, ##__VA_ARGS__) +#define drm_dbg(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_DRIVER, fmt, ##__VA_ARGS__) +#define drm_dbg_kms(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_KMS, fmt, ##__VA_ARGS__) +#define drm_dbg_prime(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_PRIME, fmt, ##__VA_ARGS__) +#define drm_dbg_atomic(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__) +#define drm_dbg_vbl(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_VBL, fmt, ##__VA_ARGS__) +#define drm_dbg_state(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_STATE, fmt, ##__VA_ARGS__) +#define drm_dbg_lease(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_LEASE, fmt, ##__VA_ARGS__) +#define drm_dbg_dp(drm, fmt, ...) \ + drm_dev_dbg((drm)->dev, DRM_UT_DP, fmt, ##__VA_ARGS__) + + /* * printk based logging + * + * Prefer drm_device based logging over device or prink based logging. */ __printf(2, 3) From b3b4346544b571c96d46be615b9db69a601ce4c8 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 16 Dec 2019 08:34:04 -0500 Subject: [PATCH 28/73] dma-buf: heaps: Use _IOCTL_ for userspace IOCTL identifier This is more consistent with the DMA and DRM frameworks convention. This patch is only a name change, no logic is changed. Signed-off-by: Andrew F. Davis Acked-by: John Stultz Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/20191216133405.1001-2-afd@ti.com --- drivers/dma-buf/dma-heap.c | 4 ++-- include/uapi/linux/dma-heap.h | 4 ++-- tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 4f04d104ae61..a24721496114 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -107,7 +107,7 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data) } unsigned int dma_heap_ioctl_cmds[] = { - DMA_HEAP_IOC_ALLOC, + DMA_HEAP_IOCTL_ALLOC, }; static long dma_heap_ioctl(struct file *file, unsigned int ucmd, @@ -153,7 +153,7 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, memset(kdata + in_size, 0, ksize - in_size); switch (kcmd) { - case DMA_HEAP_IOC_ALLOC: + case DMA_HEAP_IOCTL_ALLOC: ret = dma_heap_ioctl_allocate(file, kdata); break; default: diff --git a/include/uapi/linux/dma-heap.h b/include/uapi/linux/dma-heap.h index 73e7f66c1cae..6f84fa08e074 100644 --- a/include/uapi/linux/dma-heap.h +++ b/include/uapi/linux/dma-heap.h @@ -42,12 +42,12 @@ struct dma_heap_allocation_data { #define DMA_HEAP_IOC_MAGIC 'H' /** - * DOC: DMA_HEAP_IOC_ALLOC - allocate memory from pool + * DOC: DMA_HEAP_IOCTL_ALLOC - allocate memory from pool * * Takes a dma_heap_allocation_data struct and returns it with the fd field * populated with the dmabuf handle of the allocation. */ -#define DMA_HEAP_IOC_ALLOC _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\ +#define DMA_HEAP_IOCTL_ALLOC _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\ struct dma_heap_allocation_data) #endif /* _UAPI_LINUX_DMABUF_POOL_H */ diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c index 3e53ad331bdc..cd5e1f602ac9 100644 --- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c +++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c @@ -116,7 +116,7 @@ static int dmabuf_heap_alloc_fdflags(int fd, size_t len, unsigned int fd_flags, if (!dmabuf_fd) return -EINVAL; - ret = ioctl(fd, DMA_HEAP_IOC_ALLOC, &data); + ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data); if (ret < 0) return ret; *dmabuf_fd = (int)data.fd; From 263e38f82cbb35bf59727a2375099482dc3331da Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 16 Dec 2019 08:34:05 -0500 Subject: [PATCH 29/73] dma-buf: heaps: Remove redundant heap identifier from system heap name The heaps are already in a directory of heaps, adding _heap to a heap name is redundant. This patch is only a name change, no logic is changed. Signed-off-by: Andrew F. Davis Acked-by: John Stultz Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/20191216133405.1001-3-afd@ti.com --- drivers/dma-buf/heaps/system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 1aa01e98c595..0bf688e3c023 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -109,7 +109,7 @@ static int system_heap_create(void) struct dma_heap_export_info exp_info; int ret = 0; - exp_info.name = "system_heap"; + exp_info.name = "system"; exp_info.ops = &system_heap_ops; exp_info.priv = NULL; From 80f30930b6e9bfcb264e8b2e82b05abf3e1a8727 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Nov 2019 10:43:55 +0100 Subject: [PATCH 30/73] drm/msm: Use dma_resv locking wrappers I'll add more fancy logic to them soon, so everyone really has to use them. Plus they already provide some nice additional debug infrastructure on top of direct ww_mutex usage for the fences tracked by dma_resv. Reviewed-by: Eric Anholt Signed-off-by: Daniel Vetter Cc: Rob Clark Cc: Sean Paul Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Link: https://patchwork.freedesktop.org/patch/msgid/20191125094356.161941-4-daniel.vetter@ffwll.ch --- drivers/gpu/drm/msm/msm_gem_submit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 7d04c47d0023..385d4965a8d0 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -157,7 +157,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, msm_gem_unpin_iova(&msm_obj->base, submit->aspace); if (submit->bos[i].flags & BO_LOCKED) - ww_mutex_unlock(&msm_obj->base.resv->lock); + dma_resv_unlock(msm_obj->base.resv); if (backoff && !(submit->bos[i].flags & BO_VALID)) submit->bos[i].iova = 0; @@ -180,8 +180,8 @@ retry: contended = i; if (!(submit->bos[i].flags & BO_LOCKED)) { - ret = ww_mutex_lock_interruptible(&msm_obj->base.resv->lock, - &submit->ticket); + ret = dma_resv_lock_interruptible(msm_obj->base.resv, + &submit->ticket); if (ret) goto fail; submit->bos[i].flags |= BO_LOCKED; @@ -202,8 +202,8 @@ fail: if (ret == -EDEADLK) { struct msm_gem_object *msm_obj = submit->bos[contended].obj; /* we lost out in a seqno race, lock and retry.. */ - ret = ww_mutex_lock_slow_interruptible(&msm_obj->base.resv->lock, - &submit->ticket); + ret = dma_resv_lock_slow_interruptible(msm_obj->base.resv, + &submit->ticket); if (!ret) { submit->bos[contended].flags |= BO_LOCKED; slow_locked = contended; From 616b549b15f0e18f37641e7674b0c4658fedd424 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 25 Nov 2019 10:43:56 +0100 Subject: [PATCH 31/73] drm/vc4: Use dma_resv locking wrappers I'll add more fancy logic to them soon, so everyone really has to use them. Plus they already provide some nice additional debug infrastructure on top of direct ww_mutex usage for the fences tracked by dma_resv. Reviewed-by: Eric Anholt Cc: Eric Anholt Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191125094356.161941-5-daniel.vetter@ffwll.ch --- drivers/gpu/drm/vc4/vc4_gem.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 7a06cb6e31c5..e1cfc3ccd05a 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -568,7 +568,7 @@ vc4_unlock_bo_reservations(struct drm_device *dev, for (i = 0; i < exec->bo_count; i++) { struct drm_gem_object *bo = &exec->bo[i]->base; - ww_mutex_unlock(&bo->resv->lock); + dma_resv_unlock(bo->resv); } ww_acquire_fini(acquire_ctx); @@ -595,8 +595,7 @@ vc4_lock_bo_reservations(struct drm_device *dev, retry: if (contended_lock != -1) { bo = &exec->bo[contended_lock]->base; - ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, - acquire_ctx); + ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); if (ret) { ww_acquire_done(acquire_ctx); return ret; @@ -609,19 +608,19 @@ retry: bo = &exec->bo[i]->base; - ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx); + ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); if (ret) { int j; for (j = 0; j < i; j++) { bo = &exec->bo[j]->base; - ww_mutex_unlock(&bo->resv->lock); + dma_resv_unlock(bo->resv); } if (contended_lock != -1 && contended_lock >= i) { bo = &exec->bo[contended_lock]->base; - ww_mutex_unlock(&bo->resv->lock); + dma_resv_unlock(bo->resv); } if (ret == -EDEADLK) { From caa2a778109cf585d220bd9e78d2c49fbc20b15c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 14 Dec 2019 01:09:27 +0100 Subject: [PATCH 32/73] drm/etnaviv: Use dma_resv locking wrappers I'll add more fancy logic to them soon, so everyone really has to use them. Plus they already provide some nice additional debug infrastructure on top of direct ww_mutex usage for the fences tracked by dma_resv. v2: Fix the lost _interruptible (Michael) Acked-by: Michael J. Ruhl Reviewed-by: Lucas Stach Signed-off-by: Daniel Vetter Cc: Lucas Stach Cc: Russell King Cc: Christian Gmeiner Cc: etnaviv@lists.freedesktop.org Cc: "Ruhl, Michael J" Link: https://patchwork.freedesktop.org/patch/msgid/20191214000927.1616384-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index aa3e4c3b063a..3b0afa156d92 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -113,7 +113,7 @@ static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i) if (submit->bos[i].flags & BO_LOCKED) { struct drm_gem_object *obj = &submit->bos[i].obj->base; - ww_mutex_unlock(&obj->resv->lock); + dma_resv_unlock(obj->resv); submit->bos[i].flags &= ~BO_LOCKED; } } @@ -133,8 +133,7 @@ retry: contended = i; if (!(submit->bos[i].flags & BO_LOCKED)) { - ret = ww_mutex_lock_interruptible(&obj->resv->lock, - ticket); + ret = dma_resv_lock_interruptible(obj->resv, ticket); if (ret == -EALREADY) DRM_ERROR("BO at index %u already on submit list\n", i); @@ -161,8 +160,7 @@ fail: obj = &submit->bos[contended].obj->base; /* we lost out in a seqno race, lock and retry.. */ - ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock, - ticket); + ret = dma_resv_lock_slow_interruptible(obj->resv, ticket); if (!ret) { submit->bos[contended].flags |= BO_LOCKED; slow_locked = contended; From e529878e4bc156ea021791a840b2f43f8fe4840d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 13 Dec 2019 18:26:04 +0100 Subject: [PATCH 33/73] drm/malidp: plane_state->fb iff plane_state->crtc Checking both is one too much, so wrap a WARN_ON around it to stope the copypasta. Acked-by: Liviu Dudau Acked-by: Sam Ravnborg Signed-off-by: Daniel Vetter Cc: Liviu Dudau Cc: Brian Starkey Link: https://patchwork.freedesktop.org/patch/msgid/20191213172612.1514842-2-daniel.vetter@ffwll.ch --- drivers/gpu/drm/arm/malidp_planes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 3c70a53813bf..37715cc6064e 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -512,7 +512,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, int i, ret; unsigned int block_w, block_h; - if (!state->crtc || !state->fb) + if (!state->crtc || WARN_ON(!state->fb)) return 0; fb = state->fb; From 4f865a74c8f8a694eb9f6b6fdb8f5d8f475c8875 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 13 Dec 2019 18:26:07 +0100 Subject: [PATCH 34/73] drm/mediatek: plane_state->fb iff plane_state->crtc Checking both is one too much, so wrap a WARN_ON around it to stope the copypasta. Acked-by: CK Hu Acked-by: Sam Ravnborg Signed-off-by: Daniel Vetter Cc: CK Hu Cc: Philipp Zabel Cc: Matthias Brugger Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mediatek@lists.infradead.org Link: https://patchwork.freedesktop.org/patch/msgid/20191213172612.1514842-5-daniel.vetter@ffwll.ch --- drivers/gpu/drm/mediatek/mtk_drm_plane.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index fbcaf37defe6..e8a3493475cd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -87,7 +87,7 @@ static int mtk_plane_atomic_check(struct drm_plane *plane, if (!fb) return 0; - if (!state->crtc) + if (WARN_ON(!state->crtc)) return 0; crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); From 8b6fc114beeb9f1a270e5b6d25c30a5143801bf8 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Sun, 15 Dec 2019 13:43:44 -0600 Subject: [PATCH 35/73] drm: remove duplicate check on parent and avoid BUG_ON In drm_dev_init, parent is checked for NULL via assert after checked in devm_drm_dev_init(). The patch removes the duplicate check and replaces the assertion with WARN_ON. Further, it returns -EINVAL consistent with the usage in devm_drm_dev_init. Signed-off-by: Aditya Pakki Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191215194345.4679-1-pakki001@umn.edu --- drivers/gpu/drm/drm_drv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 1b9b40a1c7c9..7c18a980cd4b 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -622,7 +622,8 @@ int drm_dev_init(struct drm_device *dev, return -ENODEV; } - BUG_ON(!parent); + if (WARN_ON(!parent)) + return -EINVAL; kref_init(&dev->ref); dev->dev = get_device(parent); @@ -725,7 +726,7 @@ int devm_drm_dev_init(struct device *parent, { int ret; - if (WARN_ON(!parent || !driver->release)) + if (WARN_ON(!driver->release)) return -EINVAL; ret = drm_dev_init(dev, driver, parent); From f9d3b2c600075d1f79efcd5cdb1718c2f554c0f9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Dec 2019 16:10:59 +0000 Subject: [PATCH 36/73] dma-buf: fix resource leak on -ENOTTY error return path The -ENOTTY error return path does not free the allocated kdata as it returns directly. Fix this by returning via the error handling label err. Addresses-Coverity: ("Resource leak") Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework") Signed-off-by: Colin Ian King Acked-by: John Stultz Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/20191216161059.269492-1-colin.king@canonical.com --- drivers/dma-buf/dma-heap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index a24721496114..1886aee46131 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -157,7 +157,8 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, ret = dma_heap_ioctl_allocate(file, kdata); break; default: - return -ENOTTY; + ret = -ENOTTY; + goto err; } if (copy_to_user((void __user *)arg, kdata, out_size) != 0) From 7d411afe8444060454a53b1f9b70ee78b3e75ef1 Mon Sep 17 00:00:00 2001 From: zhong jiang Date: Wed, 18 Dec 2019 00:38:22 +0530 Subject: [PATCH 37/73] dma-heap: Make the symbol 'dma_heap_ioctl_cmds' static Fix the following sparse warning. drivers/dma-buf/dma-heap.c:109:14: warning: symbol 'dma_heap_ioctl_cmds' was not declared. Should it be static? Acked-by: Andrew F. Davis Acked-by: John Stultz Signed-off-by: zhong jiang Signed-off-by: Sumit Semwal [sumits: rebased over IOCTL rename patches] Link: https://patchwork.freedesktop.org/patch/msgid/20191217190822.1969-1-sumit.semwal@linaro.org --- drivers/dma-buf/dma-heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 1886aee46131..afd22c9dbdcf 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -106,7 +106,7 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data) return 0; } -unsigned int dma_heap_ioctl_cmds[] = { +static unsigned int dma_heap_ioctl_cmds[] = { DMA_HEAP_IOCTL_ALLOC, }; From 4a34a9dcec9405e29a0ad7f56400581fbd780691 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 17 Dec 2019 16:07:21 +0200 Subject: [PATCH 38/73] drm/drm_panel: Fix EXPORT of drm_panel_of_backlight() one more time The initial commit followed by the fix didn't take into consideration the case: CONFIG_DRM_PANEL=y CONFIG_BACKLIGHT_CLASS_DEVICE=m CONFIG_DRM_I915=y where symbol devm_of_find_backlight() is not reachable from DRM subsystem. Quick fix is to avoid drm_panel_of_backlight() from exporting in such case. Fixes: 907aa265fde6 ("drm/drm_panel: fix EXPORT of drm_panel_of_backlight") Reported-by: Randy Dunlap Acked-by: Randy Dunlap # build-tested Cc: Linus Walleij Cc: Sam Ravnborg Cc: Laurent Pinchart Cc: Thierry Reding Cc: Maarten Lankhorst Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: Maxime Ripard Cc: dri-devel@lists.freedesktop.org Signed-off-by: Andy Shevchenko Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191217140721.42432-1-andriy.shevchenko@linux.intel.com --- drivers/gpu/drm/drm_panel.c | 2 +- include/drm/drm_panel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 79ff3fdf6f6e..8c7bac85a793 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -302,7 +302,7 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) EXPORT_SYMBOL(of_drm_find_panel); #endif -#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) +#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE) /** * drm_panel_of_backlight - use backlight device node for backlight * @panel: DRM panel diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 5f27b693e1a0..121f7aabccd1 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -198,7 +198,7 @@ static inline struct drm_panel *of_drm_find_panel(const struct device_node *np) } #endif -#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) +#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE) int drm_panel_of_backlight(struct drm_panel *panel); #else static inline int drm_panel_of_backlight(struct drm_panel *panel) From c8d4a56082eebabbf96ddb86238808c30124f06b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 17 Dec 2019 16:09:59 +0100 Subject: [PATCH 39/73] drm/mcde: Some fixes to handling video mode The video DSI mode had not really been tested. These fixes makes it more likely to work on real hardware: - Put the active width (x width) in the right bits and the VSA (vertical sync active) in the right bits (those were swapped). - Calculate the packet sizes in bytes as in the vendor driver, rather than in bits. Test the calculations agains a spreadsheet and confirmed by debug prints to be reasonable. - Also verified the register values with relative confidence to register dumps from the Samsung GT-I8190 boot loader graphics. We are not identical but not off by far either. - Error out if the current mode and refresh frequency doesn't work out. (In the future we may simply want to scale down the vrefresh.) - Handle negative result in front/back/sync packages and fall back to zero like in the vendor driver. - Put in lots of clarifying comments and references to the documentation where the code is hard to understand. - Set the DSI_VID_VCA_SETTING2 field DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT to blkline_pck - 6 as in the vendor driver and mask the field properly. - Set the DSI_VID_VCA_SETTING1 field DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT to blkeol_pck - 6 to blkeol_duration - 6 as in the vendor driver. Cc: Stephan Gerhold Fixes: 5fc537bfd000 ("drm/mcde: Add new driver for ST-Ericsson MCDE") Link: https://patchwork.freedesktop.org/patch/msgid/20191217150959.17215-1-linus.walleij@linaro.org Reviewed-by: Stephan Gerhold Signed-off-by: Linus Walleij --- drivers/gpu/drm/mcde/mcde_dsi.c | 239 +++++++++++++++++++++------ drivers/gpu/drm/mcde/mcde_dsi_regs.h | 1 + 2 files changed, 192 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c index 42fff811653e..32e94bcb4a69 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi.c +++ b/drivers/gpu/drm/mcde/mcde_dsi.c @@ -388,13 +388,14 @@ void mcde_dsi_te_request(struct mipi_dsi_device *mdsi) static void mcde_dsi_setup_video_mode(struct mcde_dsi *d, const struct drm_display_mode *mode) { - u8 bpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format); + /* cpp, characters per pixel, number of bytes per pixel */ + u8 cpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format) / 8; + u64 pclk; u64 bpl; - u32 hfp; - u32 hbp; - u32 hsa; + int hfp; + int hbp; + int hsa; u32 blkline_pck, line_duration; - u32 blkeol_pck, blkeol_duration; u32 val; val = 0; @@ -431,11 +432,21 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d, return; } - /* TODO: TVG could be enabled here */ + /* TODO: TVG (test video generator) could be enabled here */ - /* Send blanking packet */ + /* + * During vertical blanking: go to LP mode + * Like with the EOL setting, if this is not set, the EOL area will be + * filled with NULL or blanking packets in the vblank area. + * FIXME: some Samsung phones and display panels such as s6e63m0 use + * DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_BLANKING here instead, + * figure out how to properly configure that from the panel. + */ val |= DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0; - /* Send EOL packet */ + /* + * During EOL: go to LP mode. If this is not set, the EOL area will be + * filled with NULL or blanking packets. + */ val |= DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0; /* Recovery mode 1 */ val |= 1 << DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT; @@ -443,13 +454,13 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d, writel(val, d->regs + DSI_VID_MAIN_CTL); /* Vertical frame parameters are pretty straight-forward */ - val = mode->vdisplay << DSI_VID_VSIZE_VSA_LENGTH_SHIFT; + val = mode->vdisplay << DSI_VID_VSIZE_VACT_LENGTH_SHIFT; /* vertical front porch */ val |= (mode->vsync_start - mode->vdisplay) << DSI_VID_VSIZE_VFP_LENGTH_SHIFT; /* vertical sync active */ val |= (mode->vsync_end - mode->vsync_start) - << DSI_VID_VSIZE_VACT_LENGTH_SHIFT; + << DSI_VID_VSIZE_VSA_LENGTH_SHIFT; /* vertical back porch */ val |= (mode->vtotal - mode->vsync_end) << DSI_VID_VSIZE_VBP_LENGTH_SHIFT; @@ -457,36 +468,54 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d, /* * Horizontal frame parameters: - * horizontal resolution is given in pixels and must be re-calculated - * into bytes since this is what the hardware expects. + * horizontal resolution is given in pixels but must be re-calculated + * into bytes since this is what the hardware expects, these registers + * define the payload size of the packet. + * + * hfp = horizontal front porch in bytes + * hbp = horizontal back porch in bytes + * hsa = horizontal sync active in bytes * * 6 + 2 is HFP header + checksum */ - hfp = (mode->hsync_start - mode->hdisplay) * bpp - 6 - 2; + hfp = (mode->hsync_start - mode->hdisplay) * cpp - 6 - 2; if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { /* + * Use sync pulse for sync: explicit HSA time * 6 is HBP header + checksum * 4 is RGB header + checksum */ - hbp = (mode->htotal - mode->hsync_end) * bpp - 4 - 6; + hbp = (mode->htotal - mode->hsync_end) * cpp - 4 - 6; /* * 6 is HBP header + checksum * 4 is HSW packet bytes * 4 is RGB header + checksum */ - hsa = (mode->hsync_end - mode->hsync_start) * bpp - 4 - 4 - 6; + hsa = (mode->hsync_end - mode->hsync_start) * cpp - 4 - 4 - 6; } else { /* - * HBP includes both back porch and sync + * Use event for sync: HBP includes both back porch and sync * 6 is HBP header + checksum * 4 is HSW packet bytes * 4 is RGB header + checksum */ - hbp = (mode->htotal - mode->hsync_start) * bpp - 4 - 4 - 6; - /* HSA is not considered in this mode and set to 0 */ + hbp = (mode->htotal - mode->hsync_start) * cpp - 4 - 4 - 6; + /* HSA is not present in this mode and set to 0 */ hsa = 0; } - dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u\n", + if (hfp < 0) { + dev_info(d->dev, "hfp negative, set to 0\n"); + hfp = 0; + } + if (hbp < 0) { + dev_info(d->dev, "hbp negative, set to 0\n"); + hbp = 0; + } + if (hsa < 0) { + dev_info(d->dev, "hsa negative, set to 0\n"); + hsa = 0; + } + dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u bytes\n", hfp, hbp, hsa); /* Frame parameters: horizontal sync active */ @@ -497,71 +526,185 @@ static void mcde_dsi_setup_video_mode(struct mcde_dsi *d, val |= hfp << DSI_VID_HSIZE1_HFP_LENGTH_SHIFT; writel(val, d->regs + DSI_VID_HSIZE1); - /* RGB data length (bytes on one scanline) */ - val = mode->hdisplay * (bpp / 8); + /* RGB data length (visible bytes on one scanline) */ + val = mode->hdisplay * cpp; writel(val, d->regs + DSI_VID_HSIZE2); - - /* TODO: further adjustments for TVG mode here */ + dev_dbg(d->dev, "RGB length, visible area on a line: %u bytes\n", val); /* - * EOL packet length from bits per line calculations: pixel clock - * is given in kHz, calculate the time between two pixels in - * picoseconds. + * Calculate the time between two pixels in picoseconds using + * the supplied refresh rate and total resolution including + * porches and sync. */ - bpl = mode->clock * mode->htotal; - bpl *= (d->hs_freq / 8); - do_div(bpl, 1000000); /* microseconds */ - do_div(bpl, 1000000); /* seconds */ + /* (ps/s) / (pixels/s) = ps/pixels */ + pclk = DIV_ROUND_UP_ULL(1000000000000, + (mode->vrefresh * mode->htotal * mode->vtotal)); + dev_dbg(d->dev, "picoseconds between two pixels: %llu\n", + pclk); + + /* + * How many bytes per line will this update frequency yield? + * + * Calculate the number of picoseconds for one scanline (1), then + * divide by 1000000000000 (2) to get in pixels per second we + * want to output. + * + * Multiply with number of bytes per second at this video display + * frequency (3) to get number of bytes transferred during this + * time. Notice that we use the frequency the display wants, + * not what we actually get from the DSI PLL, which is hs_freq. + * + * These arithmetics are done in a different order to avoid + * overflow. + */ + bpl = pclk * mode->htotal; /* (1) picoseconds per line */ + dev_dbg(d->dev, "picoseconds per line: %llu\n", bpl); + /* Multiply with bytes per second (3) */ + bpl *= (d->mdsi->hs_rate / 8); + /* Pixels per second (2) */ + bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000); /* microseconds */ + bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000); /* seconds */ + /* parallel transactions in all lanes */ bpl *= d->mdsi->lanes; - dev_dbg(d->dev, "calculated bytes per line: %llu\n", bpl); + dev_dbg(d->dev, + "calculated bytes per line: %llu @ %d Hz with HS %lu Hz\n", + bpl, mode->vrefresh, d->mdsi->hs_rate); + /* * 6 is header + checksum, header = 4 bytes, checksum = 2 bytes * 4 is short packet for vsync/hsync */ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { - /* Fixme: isn't the hsync width in pixels? */ + /* Set the event packet size to 0 (not used) */ + writel(0, d->regs + DSI_VID_BLKSIZE1); + /* + * FIXME: isn't the hsync width in pixels? The porch and + * sync area size is in pixels here, but this -6 + * seems to be for bytes. It looks like this in the vendor + * code though. Is it completely untested? + */ blkline_pck = bpl - (mode->hsync_end - mode->hsync_start) - 6; val = blkline_pck << DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT; writel(val, d->regs + DSI_VID_BLKSIZE2); } else { + /* Set the sync pulse packet size to 0 (not used) */ + writel(0, d->regs + DSI_VID_BLKSIZE2); + /* Specifying payload size in bytes (-4-6 from manual) */ blkline_pck = bpl - 4 - 6; + if (blkline_pck > 0x1FFF) + dev_err(d->dev, "blkline_pck too big %d bytes\n", + blkline_pck); val = blkline_pck << DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT; + val &= DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK; writel(val, d->regs + DSI_VID_BLKSIZE1); } - line_duration = (blkline_pck + 6) / d->mdsi->lanes; - dev_dbg(d->dev, "line duration %u\n", line_duration); + /* + * The line duration is used to scale back the frequency from + * the max frequency supported by the HS clock to the desired + * update frequency in vrefresh. + */ + line_duration = blkline_pck + 6; + /* + * The datasheet contains this complex condition to decreasing + * the line duration by 1 under very specific circumstances. + * Here we also imply that LP is used during burst EOL. + */ + if (d->mdsi->lanes == 2 && (hsa & 0x01) && (hfp & 0x01) + && (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) + line_duration--; + line_duration = DIV_ROUND_CLOSEST(line_duration, d->mdsi->lanes); + dev_dbg(d->dev, "line duration %u bytes\n", line_duration); val = line_duration << DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT; /* * This is the time to perform LP->HS on D-PHY * FIXME: nowhere to get this from: DT property on the DSI? + * The manual says this is "system dependent". + * values like 48 and 72 seen in the vendor code. */ - val |= 0 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT; + val |= 48 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT; writel(val, d->regs + DSI_VID_DPHY_TIME); - /* Calculate block end of line */ - blkeol_pck = bpl - mode->hdisplay * bpp - 6; - blkeol_duration = (blkeol_pck + 6) / d->mdsi->lanes; - dev_dbg(d->dev, "blkeol pck: %u, duration: %u\n", - blkeol_pck, blkeol_duration); - + /* + * See the manual figure 657 page 2203 for understanding the impact + * of the different burst mode settings. + */ if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { - /* Set up EOL clock for burst mode */ + int blkeol_pck, blkeol_duration; + /* + * Packet size at EOL for burst mode, this is only used + * if DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 is NOT set, + * but we instead send NULL or blanking packets at EOL. + * This is given in number of bytes. + * + * See the manual page 2198 for the 13 reg_blkeol_pck bits. + */ + blkeol_pck = bpl - (mode->htotal * cpp) - 6; + if (blkeol_pck < 0) { + dev_err(d->dev, "video block does not fit on line!\n"); + dev_err(d->dev, + "calculated bytes per line: %llu @ %d Hz\n", + bpl, mode->vrefresh); + dev_err(d->dev, + "bytes per line (blkline_pck) %u bytes\n", + blkline_pck); + dev_err(d->dev, + "blkeol_pck becomes %d bytes\n", blkeol_pck); + return; + } + dev_dbg(d->dev, "BLKEOL packet: %d bytes\n", blkeol_pck); + val = readl(d->regs + DSI_VID_BLKSIZE1); + val &= ~DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK; val |= blkeol_pck << DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT; writel(val, d->regs + DSI_VID_BLKSIZE1); - writel(blkeol_pck, d->regs + DSI_VID_VCA_SETTING2); + /* Use the same value for exact burst limit */ + val = blkeol_pck << + DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT; + val &= DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_MASK; + writel(val, d->regs + DSI_VID_VCA_SETTING2); + /* + * This BLKEOL duration is claimed to be the duration in clock + * cycles of the BLLP end-of-line (EOL) period for each line if + * DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0 is set. + * + * It is hard to trust the manuals' claim that this is in clock + * cycles as we mimic the behaviour of the vendor code, which + * appears to write a number of bytes that would have been + * transferred on a single lane. + * + * See the manual figure 657 page 2203 and page 2198 for the 13 + * reg_blkeol_duration bits. + * + * FIXME: should this also be set up also for non-burst mode + * according to figure 565 page 2202? + */ + blkeol_duration = DIV_ROUND_CLOSEST(blkeol_pck + 6, + d->mdsi->lanes); + dev_dbg(d->dev, "BLKEOL duration: %d clock cycles\n", + blkeol_duration); - writel(blkeol_duration, d->regs + DSI_VID_PCK_TIME); - writel(blkeol_duration - 6, d->regs + DSI_VID_VCA_SETTING1); + val = readl(d->regs + DSI_VID_PCK_TIME); + val &= ~DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK; + val |= blkeol_duration << + DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT; + writel(val, d->regs + DSI_VID_PCK_TIME); + + /* Max burst limit, this is given in bytes */ + val = readl(d->regs + DSI_VID_VCA_SETTING1); + val &= ~DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_MASK; + val |= (blkeol_pck - 6) << + DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT; + writel(val, d->regs + DSI_VID_VCA_SETTING1); } /* Maximum line limit */ val = readl(d->regs + DSI_VID_VCA_SETTING2); - val |= blkline_pck << - DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT; + val &= ~DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_MASK; + val |= (blkline_pck - 6) << + DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_SHIFT; writel(val, d->regs + DSI_VID_VCA_SETTING2); - + dev_dbg(d->dev, "blkline pck: %d bytes\n", blkline_pck - 6); } static void mcde_dsi_start(struct mcde_dsi *d) diff --git a/drivers/gpu/drm/mcde/mcde_dsi_regs.h b/drivers/gpu/drm/mcde/mcde_dsi_regs.h index 8089db805c57..16551af1089e 100644 --- a/drivers/gpu/drm/mcde/mcde_dsi_regs.h +++ b/drivers/gpu/drm/mcde/mcde_dsi_regs.h @@ -228,6 +228,7 @@ #define DSI_VID_PCK_TIME 0x000000A8 #define DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT 0 +#define DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK 0x00000FFF #define DSI_VID_DPHY_TIME 0x000000AC #define DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT 0 From 1ffe09590121fbb3786d6c860acdd200f7ab095c Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Tue, 17 Dec 2019 15:02:28 -0800 Subject: [PATCH 40/73] udmabuf: fix dma-buf cpu access I'm just going to put Chia's review comment here since it sums the issue rather nicely: "(1) Semantically, a dma-buf is in DMA domain. CPU access from the importer must be surrounded by {begin,end}_cpu_access. This gives the exporter a chance to move the buffer to the CPU domain temporarily. (2) When the exporter itself has other means to do CPU access, it is only reasonable for the exporter to move the buffer to the CPU domain before access, and to the DMA domain after access. The exporter can potentially reuse {begin,end}_cpu_access for that purpose. Because of (1), udmabuf does need to implement the {begin,end}_cpu_access hooks. But "begin" should mean dma_sync_sg_for_cpu and "end" should mean dma_sync_sg_for_device. Because of (2), if userspace wants to continuing accessing through the memfd mapping, it should call udmabuf's {begin,end}_cpu_access to avoid cache issues." Reported-by: Chia-I Wu Suggested-by: Chia-I Wu Fixes: 284562e1f348 ("udmabuf: implement begin_cpu_access/end_cpu_access hooks") Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191217230228.453-1-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/dma-buf/udmabuf.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 61b0a2cff874..acb26c627d27 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -122,9 +122,8 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, if (IS_ERR(ubuf->sg)) return PTR_ERR(ubuf->sg); } else { - dma_sync_sg_for_device(dev, ubuf->sg->sgl, - ubuf->sg->nents, - direction); + dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, + direction); } return 0; @@ -139,7 +138,7 @@ static int end_cpu_udmabuf(struct dma_buf *buf, if (!ubuf->sg) return -EINVAL; - dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); + dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); return 0; } From a7738c08cf269461da69f81db42279b57c68b2bb Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:20 +0000 Subject: [PATCH 41/73] dt-bindings: display: bridge: Convert lvds-transmitter binding to json-schema Convert the lvds-transmitter binding to DT schema format using json-schema. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-2-git-send-email-fabrizio.castro@bp.renesas.com --- .../display/bridge/lvds-transmitter.txt | 66 -------------- .../display/bridge/lvds-transmitter.yaml | 91 +++++++++++++++++++ 2 files changed, 91 insertions(+), 66 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt deleted file mode 100644 index 60091db5dfa5..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt +++ /dev/null @@ -1,66 +0,0 @@ -Parallel to LVDS Encoder ------------------------- - -This binding supports the parallel to LVDS encoders that don't require any -configuration. - -LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple -incompatible data link layers have been used over time to transmit image data -to LVDS panels. This binding targets devices compatible with the following -specifications only. - -[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February -1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) -[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National -Semiconductor -[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video -Electronics Standards Association (VESA) - -Those devices have been marketed under the FPD-Link and FlatLink brand names -among others. - - -Required properties: - -- compatible: Must be "lvds-encoder" - - Any encoder compatible with this generic binding, but with additional - properties not listed here, must list a device specific compatible first - followed by this generic compatible. - -Required nodes: - -This device has two video ports. Their connections are modeled using the OF -graph bindings specified in Documentation/devicetree/bindings/graph.txt. - -- Video port 0 for parallel input -- Video port 1 for LVDS output - - -Example -------- - -lvds-encoder { - compatible = "lvds-encoder"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint { - remote-endpoint = <&display_out_rgb>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint { - remote-endpoint = <&lvds_panel_in>; - }; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml new file mode 100644 index 000000000000..b5dd0da71394 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/lvds-transmitter.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Parallel to LVDS Encoder + +maintainers: + - Laurent Pinchart + +description: | + This binding supports the parallel to LVDS encoders that don't require any + configuration. + + LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple + incompatible data link layers have been used over time to transmit image data + to LVDS panels. This binding targets devices compatible with the following + specifications only. + + [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February + 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) + [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National + Semiconductor + [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video + Electronics Standards Association (VESA) + + Those devices have been marketed under the FPD-Link and FlatLink brand names + among others. + +properties: + compatible: + description: | + Any encoder compatible with this generic binding, but with additional + properties not listed here, must define its own binding and list a device + specific compatible first followed by the generic compatible. + enum: + - lvds-encoder + + ports: + type: object + description: | + This device has two video ports. Their connections are modeled using the + OF graph bindings specified in Documentation/devicetree/bindings/graph.txt + properties: + port@0: + type: object + description: | + Port 0 is for parallel input + + port@1: + type: object + description: | + Port 1 is for LVDS output + + required: + - port@0 + - port@1 + +required: + - compatible + - ports + +examples: + - | + lvds-encoder { + compatible = "lvds-encoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lvds_enc_in: endpoint { + remote-endpoint = <&display_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + + lvds_enc_out: endpoint { + remote-endpoint = <&lvds_panel_in>; + }; + }; + }; + }; + +... From 9acfa9d30ad71a64049b1f1b61c7f937e12531df Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:21 +0000 Subject: [PATCH 42/73] dt-bindings: display: bridge: lvds-transmitter: Document powerdown-gpios Add documentation for property powerdown-gpios. The property is optional. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-3-git-send-email-fabrizio.castro@bp.renesas.com --- .../devicetree/bindings/display/bridge/lvds-transmitter.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml index b5dd0da71394..2484737233f6 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -57,6 +57,11 @@ properties: - port@0 - port@1 + powerdown-gpios: + description: + The GPIO used to control the power down line of this device. + maxItems: 1 + required: - compatible - ports From 5240272d4323c20265329a6b85b799bddf9827df Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:22 +0000 Subject: [PATCH 43/73] dt-bindings: display: bridge: lvds-transmitter: Absorb ti, ds90c185.txt ti,ds90c185.txt documents LVDS encoders using the same driver as the one documented by lvds-transmitter.yaml. Since the properties listed in ti,ds90c185.txt are the same as the ones listed in lvds-transmitter.yaml, absorb the dt-binding into lvds-transmitter.yaml. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-4-git-send-email-fabrizio.castro@bp.renesas.com --- .../display/bridge/lvds-transmitter.yaml | 14 +++-- .../bindings/display/bridge/ti,ds90c185.txt | 55 ------------------- 2 files changed, 8 insertions(+), 61 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml index 2484737233f6..a8326ceec9fd 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -31,11 +31,13 @@ description: | properties: compatible: description: | - Any encoder compatible with this generic binding, but with additional - properties not listed here, must define its own binding and list a device - specific compatible first followed by the generic compatible. - enum: - - lvds-encoder + Must list the device specific compatible string first, followed by the + generic compatible string. + items: + - enum: + - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer + - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer + - const: lvds-encoder # Generic LVDS encoder compatible fallback ports: type: object @@ -69,7 +71,7 @@ required: examples: - | lvds-encoder { - compatible = "lvds-encoder"; + compatible = "ti,ds90c185", "lvds-encoder"; ports { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt b/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt deleted file mode 100644 index e575f996959a..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt +++ /dev/null @@ -1,55 +0,0 @@ -Texas Instruments FPD-Link (LVDS) Serializer --------------------------------------------- - -The DS90C185 and DS90C187 are low-power serializers for portable -battery-powered applications that reduces the size of the RGB -interface between the host GPU and the display. - -Required properties: - -- compatible: Should be - "ti,ds90c185", "lvds-encoder" for the TI DS90C185 FPD-Link Serializer - "ti,ds90c187", "lvds-encoder" for the TI DS90C187 FPD-Link Serializer - -Optional properties: - -- powerdown-gpios: Power down control GPIO (the PDB pin, active-low) - -Required nodes: - -The devices have two video ports. Their connections are modeled using the OF -graph bindings specified in Documentation/devicetree/bindings/graph.txt. - -- Video port 0 for parallel input -- Video port 1 for LVDS output - - -Example -------- - -lvds-encoder { - compatible = "ti,ds90c185", "lvds-encoder"; - - powerdown-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint { - remote-endpoint = <&lcdc_out_rgb>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint { - remote-endpoint = <&lvds_panel_in>; - }; - }; - }; -}; From 4788f4e11d1d3dc304b119b993d3ce39a5fd22c3 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:23 +0000 Subject: [PATCH 44/73] dt-bindings: display: bridge: lvds-transmitter: Document "ti, sn75lvds83" Compatible string "ti,sn75lvds83" is being used by device tree rk3188-bqedison2qc.dts, but it's not documented anywhere, therefore document it within lvds-transmitter.yaml. Signed-off-by: Fabrizio Castro Acked-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-5-git-send-email-fabrizio.castro@bp.renesas.com --- .../devicetree/bindings/display/bridge/lvds-transmitter.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml index a8326ceec9fd..27de616a1973 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -37,6 +37,7 @@ properties: - enum: - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer + - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter - const: lvds-encoder # Generic LVDS encoder compatible fallback ports: From 0d60131a3b5dcb4c6980eb30cbca3c6fb62d7b6f Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:24 +0000 Subject: [PATCH 45/73] drm/bridge: Repurpose lvds-encoder.c lvds-encoder.c implementation is also suitable for LVDS decoders, not just LVDS encoders. Instead of creating a new driver for addressing support for transparent LVDS decoders, repurpose lvds-encoder.c for the greater good with this patch. This patch only "rebrands" the lvds-encoder.c driver, to make it suitable for hosting LVDS decoders support. The actual support for LVDS decoders will come with a later patch. Signed-off-by: Fabrizio Castro Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-6-git-send-email-fabrizio.castro@bp.renesas.com --- drivers/gpu/drm/bridge/Kconfig | 8 +- drivers/gpu/drm/bridge/Makefile | 2 +- drivers/gpu/drm/bridge/lvds-codec.c | 154 +++++++++++++++++++++++++ drivers/gpu/drm/bridge/lvds-encoder.c | 155 -------------------------- 4 files changed, 159 insertions(+), 160 deletions(-) create mode 100644 drivers/gpu/drm/bridge/lvds-codec.c delete mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index ccc698c44f58..0b9ca5862455 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -35,14 +35,14 @@ config DRM_DUMB_VGA_DAC Support for non-programmable RGB to VGA DAC bridges, such as ADI ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs. -config DRM_LVDS_ENCODER - tristate "Transparent parallel to LVDS encoder support" +config DRM_LVDS_CODEC + tristate "Transparent LVDS encoders and decoders support" depends on OF select DRM_KMS_HELPER select DRM_PANEL_BRIDGE help - Support for transparent parallel to LVDS encoders that don't require - any configuration. + Support for transparent LVDS encoders and decoders that don't + require any configuration. config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW tristate "MegaChips stdp4028-ge-b850v3-fw and stdp2690-ge-b850v3-fw" diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index a6c7dd7727ea..cd16ce830270 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o -obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o +obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c new file mode 100644 index 000000000000..b5801a287a0a --- /dev/null +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2019 Renesas Electronics Corporation + * Copyright (C) 2016 Laurent Pinchart + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct lvds_codec { + struct drm_bridge bridge; + struct drm_bridge *panel_bridge; + struct gpio_desc *powerdown_gpio; +}; + +static int lvds_codec_attach(struct drm_bridge *bridge) +{ + struct lvds_codec *lvds_codec = container_of(bridge, + struct lvds_codec, bridge); + + return drm_bridge_attach(bridge->encoder, lvds_codec->panel_bridge, + bridge); +} + +static void lvds_codec_enable(struct drm_bridge *bridge) +{ + struct lvds_codec *lvds_codec = container_of(bridge, + struct lvds_codec, bridge); + + if (lvds_codec->powerdown_gpio) + gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 0); +} + +static void lvds_codec_disable(struct drm_bridge *bridge) +{ + struct lvds_codec *lvds_codec = container_of(bridge, + struct lvds_codec, bridge); + + if (lvds_codec->powerdown_gpio) + gpiod_set_value_cansleep(lvds_codec->powerdown_gpio, 1); +} + +static struct drm_bridge_funcs funcs = { + .attach = lvds_codec_attach, + .enable = lvds_codec_enable, + .disable = lvds_codec_disable, +}; + +static int lvds_codec_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *port; + struct device_node *endpoint; + struct device_node *panel_node; + struct drm_panel *panel; + struct lvds_codec *lvds_codec; + + lvds_codec = devm_kzalloc(dev, sizeof(*lvds_codec), GFP_KERNEL); + if (!lvds_codec) + return -ENOMEM; + + lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", + GPIOD_OUT_HIGH); + if (IS_ERR(lvds_codec->powerdown_gpio)) { + int err = PTR_ERR(lvds_codec->powerdown_gpio); + + if (err != -EPROBE_DEFER) + dev_err(dev, "powerdown GPIO failure: %d\n", err); + return err; + } + + /* Locate the panel DT node. */ + port = of_graph_get_port_by_id(dev->of_node, 1); + if (!port) { + dev_dbg(dev, "port 1 not found\n"); + return -ENXIO; + } + + endpoint = of_get_child_by_name(port, "endpoint"); + of_node_put(port); + if (!endpoint) { + dev_dbg(dev, "no endpoint for port 1\n"); + return -ENXIO; + } + + panel_node = of_graph_get_remote_port_parent(endpoint); + of_node_put(endpoint); + if (!panel_node) { + dev_dbg(dev, "no remote endpoint for port 1\n"); + return -ENXIO; + } + + panel = of_drm_find_panel(panel_node); + of_node_put(panel_node); + if (IS_ERR(panel)) { + dev_dbg(dev, "panel not found, deferring probe\n"); + return PTR_ERR(panel); + } + + lvds_codec->panel_bridge = + devm_drm_panel_bridge_add_typed(dev, panel, + DRM_MODE_CONNECTOR_LVDS); + if (IS_ERR(lvds_codec->panel_bridge)) + return PTR_ERR(lvds_codec->panel_bridge); + + /* + * The panel_bridge bridge is attached to the panel's of_node, + * but we need a bridge attached to our of_node for our user + * to look up. + */ + lvds_codec->bridge.of_node = dev->of_node; + lvds_codec->bridge.funcs = &funcs; + drm_bridge_add(&lvds_codec->bridge); + + platform_set_drvdata(pdev, lvds_codec); + + return 0; +} + +static int lvds_codec_remove(struct platform_device *pdev) +{ + struct lvds_codec *lvds_codec = platform_get_drvdata(pdev); + + drm_bridge_remove(&lvds_codec->bridge); + + return 0; +} + +static const struct of_device_id lvds_codec_match[] = { + { .compatible = "lvds-encoder" }, + { .compatible = "thine,thc63lvdm83d" }, + {}, +}; +MODULE_DEVICE_TABLE(of, lvds_codec_match); + +static struct platform_driver lvds_codec_driver = { + .probe = lvds_codec_probe, + .remove = lvds_codec_remove, + .driver = { + .name = "lvds-codec", + .of_match_table = lvds_codec_match, + }, +}; +module_platform_driver(lvds_codec_driver); + +MODULE_AUTHOR("Laurent Pinchart "); +MODULE_DESCRIPTION("LVDS encoders and decoders"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c deleted file mode 100644 index e2132a8d5106..000000000000 --- a/drivers/gpu/drm/bridge/lvds-encoder.c +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2016 Laurent Pinchart - */ - -#include -#include -#include -#include -#include - -#include -#include - -struct lvds_encoder { - struct drm_bridge bridge; - struct drm_bridge *panel_bridge; - struct gpio_desc *powerdown_gpio; -}; - -static int lvds_encoder_attach(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds_encoder = container_of(bridge, - struct lvds_encoder, - bridge); - - return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge, - bridge); -} - -static void lvds_encoder_enable(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds_encoder = container_of(bridge, - struct lvds_encoder, - bridge); - - if (lvds_encoder->powerdown_gpio) - gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 0); -} - -static void lvds_encoder_disable(struct drm_bridge *bridge) -{ - struct lvds_encoder *lvds_encoder = container_of(bridge, - struct lvds_encoder, - bridge); - - if (lvds_encoder->powerdown_gpio) - gpiod_set_value_cansleep(lvds_encoder->powerdown_gpio, 1); -} - -static struct drm_bridge_funcs funcs = { - .attach = lvds_encoder_attach, - .enable = lvds_encoder_enable, - .disable = lvds_encoder_disable, -}; - -static int lvds_encoder_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *port; - struct device_node *endpoint; - struct device_node *panel_node; - struct drm_panel *panel; - struct lvds_encoder *lvds_encoder; - - lvds_encoder = devm_kzalloc(dev, sizeof(*lvds_encoder), GFP_KERNEL); - if (!lvds_encoder) - return -ENOMEM; - - lvds_encoder->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", - GPIOD_OUT_HIGH); - if (IS_ERR(lvds_encoder->powerdown_gpio)) { - int err = PTR_ERR(lvds_encoder->powerdown_gpio); - - if (err != -EPROBE_DEFER) - dev_err(dev, "powerdown GPIO failure: %d\n", err); - return err; - } - - /* Locate the panel DT node. */ - port = of_graph_get_port_by_id(dev->of_node, 1); - if (!port) { - dev_dbg(dev, "port 1 not found\n"); - return -ENXIO; - } - - endpoint = of_get_child_by_name(port, "endpoint"); - of_node_put(port); - if (!endpoint) { - dev_dbg(dev, "no endpoint for port 1\n"); - return -ENXIO; - } - - panel_node = of_graph_get_remote_port_parent(endpoint); - of_node_put(endpoint); - if (!panel_node) { - dev_dbg(dev, "no remote endpoint for port 1\n"); - return -ENXIO; - } - - panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - if (IS_ERR(panel)) { - dev_dbg(dev, "panel not found, deferring probe\n"); - return PTR_ERR(panel); - } - - lvds_encoder->panel_bridge = - devm_drm_panel_bridge_add_typed(dev, panel, - DRM_MODE_CONNECTOR_LVDS); - if (IS_ERR(lvds_encoder->panel_bridge)) - return PTR_ERR(lvds_encoder->panel_bridge); - - /* The panel_bridge bridge is attached to the panel's of_node, - * but we need a bridge attached to our of_node for our user - * to look up. - */ - lvds_encoder->bridge.of_node = dev->of_node; - lvds_encoder->bridge.funcs = &funcs; - drm_bridge_add(&lvds_encoder->bridge); - - platform_set_drvdata(pdev, lvds_encoder); - - return 0; -} - -static int lvds_encoder_remove(struct platform_device *pdev) -{ - struct lvds_encoder *lvds_encoder = platform_get_drvdata(pdev); - - drm_bridge_remove(&lvds_encoder->bridge); - - return 0; -} - -static const struct of_device_id lvds_encoder_match[] = { - { .compatible = "lvds-encoder" }, - { .compatible = "thine,thc63lvdm83d" }, - {}, -}; -MODULE_DEVICE_TABLE(of, lvds_encoder_match); - -static struct platform_driver lvds_encoder_driver = { - .probe = lvds_encoder_probe, - .remove = lvds_encoder_remove, - .driver = { - .name = "lvds-encoder", - .of_match_table = lvds_encoder_match, - }, -}; -module_platform_driver(lvds_encoder_driver); - -MODULE_AUTHOR("Laurent Pinchart "); -MODULE_DESCRIPTION("Transparent parallel to LVDS encoder"); -MODULE_LICENSE("GPL"); From e6f607bb2ba8aac719cf6abdf1d9dd8dae0c63e5 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 18 Dec 2019 01:07:53 +0200 Subject: [PATCH 46/73] drm/bridge: lvds-codec: Add "lvds-decoder" support Add support for transparent LVDS decoders by adding a new compatible string ("lvds-decoder") to the driver. This patch also adds member connector_type to struct lvds_codec, and that's because LVDS decoders have a different connector type from LVDS encoders. We fill this new member up with the data matching the compatible string. Signed-off-by: Fabrizio Castro Reviewed-by: Laurent Pinchart [Fix pointer to int cast warning] Signed-off-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20191217230753.2999-1-laurent.pinchart+renesas@ideasonboard.com --- drivers/gpu/drm/bridge/lvds-codec.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index b5801a287a0a..d072a76b20d9 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ struct lvds_codec { struct drm_bridge bridge; struct drm_bridge *panel_bridge; struct gpio_desc *powerdown_gpio; + u32 connector_type; }; static int lvds_codec_attach(struct drm_bridge *bridge) @@ -65,6 +67,7 @@ static int lvds_codec_probe(struct platform_device *pdev) if (!lvds_codec) return -ENOMEM; + lvds_codec->connector_type = (uintptr_t)of_device_get_match_data(dev); lvds_codec->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); if (IS_ERR(lvds_codec->powerdown_gpio)) { @@ -105,7 +108,7 @@ static int lvds_codec_probe(struct platform_device *pdev) lvds_codec->panel_bridge = devm_drm_panel_bridge_add_typed(dev, panel, - DRM_MODE_CONNECTOR_LVDS); + lvds_codec->connector_type); if (IS_ERR(lvds_codec->panel_bridge)) return PTR_ERR(lvds_codec->panel_bridge); @@ -133,8 +136,18 @@ static int lvds_codec_remove(struct platform_device *pdev) } static const struct of_device_id lvds_codec_match[] = { - { .compatible = "lvds-encoder" }, - { .compatible = "thine,thc63lvdm83d" }, + { + .compatible = "lvds-decoder", + .data = (void *)DRM_MODE_CONNECTOR_DPI, + }, + { + .compatible = "lvds-encoder", + .data = (void *)DRM_MODE_CONNECTOR_LVDS, + }, + { + .compatible = "thine,thc63lvdm83d", + .data = (void *)DRM_MODE_CONNECTOR_LVDS, + }, {}, }; MODULE_DEVICE_TABLE(of, lvds_codec_match); From 319d8e9814c4da2c6ea0a8e080b3ffa517542daf Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:26 +0000 Subject: [PATCH 47/73] drm/bridge: lvds-codec: Simplify panel DT node localisation The probe function needs to get ahold of the panel device tree node, and it achieves that by using a combination of of_graph_get_port_by_id, of_get_child_by_name, and of_graph_get_remote_port_parent. We can achieve the same goal by replacing those calls with a call to of_graph_get_remote_node these days. Signed-off-by: Fabrizio Castro Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-8-git-send-email-fabrizio.castro@bp.renesas.com --- drivers/gpu/drm/bridge/lvds-codec.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c index d072a76b20d9..5f04cc11227e 100644 --- a/drivers/gpu/drm/bridge/lvds-codec.c +++ b/drivers/gpu/drm/bridge/lvds-codec.c @@ -57,8 +57,6 @@ static struct drm_bridge_funcs funcs = { static int lvds_codec_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *port; - struct device_node *endpoint; struct device_node *panel_node; struct drm_panel *panel; struct lvds_codec *lvds_codec; @@ -79,23 +77,9 @@ static int lvds_codec_probe(struct platform_device *pdev) } /* Locate the panel DT node. */ - port = of_graph_get_port_by_id(dev->of_node, 1); - if (!port) { - dev_dbg(dev, "port 1 not found\n"); - return -ENXIO; - } - - endpoint = of_get_child_by_name(port, "endpoint"); - of_node_put(port); - if (!endpoint) { - dev_dbg(dev, "no endpoint for port 1\n"); - return -ENXIO; - } - - panel_node = of_graph_get_remote_port_parent(endpoint); - of_node_put(endpoint); + panel_node = of_graph_get_remote_node(dev->of_node, 1, 0); if (!panel_node) { - dev_dbg(dev, "no remote endpoint for port 1\n"); + dev_dbg(dev, "panel DT node not found\n"); return -ENXIO; } From 575af8ecd1943d432ede9891e1419d001fa67c5d Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:27 +0000 Subject: [PATCH 48/73] dt-bindings: display: bridge: Repurpose lvds-encoder In an effort to repurpose lvds-encoder.c to also serve the function of LVDS decoders, we ended up defining a new "generic" compatible string ("lvds-decoder"), therefore adapt the dt schema to allow for the new compatible string. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart [narmstrong: fixed port descriptions as acked with lpinchart] Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-9-git-send-email-fabrizio.castro@bp.renesas.com --- ...{lvds-transmitter.yaml => lvds-codec.yaml} | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) rename Documentation/devicetree/bindings/display/bridge/{lvds-transmitter.yaml => lvds-codec.yaml} (61%) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml similarity index 61% rename from Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml rename to Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index 27de616a1973..f714fbd2814d 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -1,17 +1,17 @@ # SPDX-License-Identifier: GPL-2.0 %YAML 1.2 --- -$id: http://devicetree.org/schemas/display/bridge/lvds-transmitter.yaml# +$id: http://devicetree.org/schemas/display/bridge/lvds-codec.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Parallel to LVDS Encoder +title: Transparent LVDS encoders and decoders maintainers: - Laurent Pinchart description: | - This binding supports the parallel to LVDS encoders that don't require any - configuration. + This binding supports transparent LVDS encoders and decoders that don't + require any configuration. LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple incompatible data link layers have been used over time to transmit image data @@ -33,12 +33,14 @@ properties: description: | Must list the device specific compatible string first, followed by the generic compatible string. - items: - - enum: - - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer - - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer - - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter - - const: lvds-encoder # Generic LVDS encoder compatible fallback + oneOf: + - items: + - enum: + - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer + - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer + - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter + - const: lvds-encoder # Generic LVDS encoder compatible fallback + - const: lvds-decoder # Generic LVDS decoders compatible fallback ports: type: object @@ -49,12 +51,14 @@ properties: port@0: type: object description: | - Port 0 is for parallel input + For LVDS encoders, port 0 is the parallel input + For LVDS decoders, port 0 is the LVDS input port@1: type: object description: | - Port 1 is for LVDS output + For LVDS encoders, port 1 is the LVDS output + For LVDS decoders, port 1 is the parallel output required: - port@0 @@ -96,4 +100,30 @@ examples: }; }; + - | + lvds-decoder { + compatible = "lvds-decoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lvds_dec_in: endpoint { + remote-endpoint = <&display_out_lvds>; + }; + }; + + port@1 { + reg = <1>; + + lvds_dec_out: endpoint { + remote-endpoint = <&rgb_panel_in>; + }; + }; + }; + }; + ... From b7de4ba7dbe962d38768e0396f7acd11eff7628b Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:28 +0000 Subject: [PATCH 49/73] dt-bindings: display: bridge: lvds-codec: Document ti, ds90cf384a The DS90CF384A from TI is a transparent LVDS receiver (decoder), and therefore it is compatible with the lvds-codec driver and bindings. Document the ti,ds90cf384a compatible string with the dt-bindings. No driver change required. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-10-git-send-email-fabrizio.castro@bp.renesas.com --- .../devicetree/bindings/display/bridge/lvds-codec.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index f714fbd2814d..9f27d4d91a10 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -40,7 +40,10 @@ properties: - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter - const: lvds-encoder # Generic LVDS encoder compatible fallback - - const: lvds-decoder # Generic LVDS decoders compatible fallback + - items: + - enum: + - ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver + - const: lvds-decoder # Generic LVDS decoders compatible fallback ports: type: object @@ -102,7 +105,7 @@ examples: - | lvds-decoder { - compatible = "lvds-decoder"; + compatible = "ti,ds90cf384a", "lvds-decoder"; ports { #address-cells = <1>; From cad8c44a9ff0da507f1e225e0ad342d69dbbc4cd Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:32 +0000 Subject: [PATCH 50/73] dt-bindings: display: bridge: lvds-codec: Absorb thine, thc63lvdm83d.txt At this point in time, compatible string "thine,thc63lvdm83d" is backed by the lvds-codec driver, and the documentation contained in thine,thc63lvdm83d.txt is basically the same as the one contained in lvds-codec.yaml (generic fallback compatible string aside), therefore absorb thine,thc63lvdm83d.txt. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/ <1573660292-10629-14-git-send-email-fabrizio.castro@bp.renesas.com --- .../bindings/display/bridge/lvds-codec.yaml | 5 +- .../display/bridge/thine,thc63lvdm83d.txt | 50 ------------------- 2 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index 9f27d4d91a10..8f373029f5d2 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -30,9 +30,6 @@ description: | properties: compatible: - description: | - Must list the device specific compatible string first, followed by the - generic compatible string. oneOf: - items: - enum: @@ -44,6 +41,8 @@ properties: - enum: - ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver - const: lvds-decoder # Generic LVDS decoders compatible fallback + - enum: + - thine,thc63lvdm83d # For the THC63LVDM83D LVDS serializer ports: type: object diff --git a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt deleted file mode 100644 index fee3c88e1a17..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt +++ /dev/null @@ -1,50 +0,0 @@ -THine Electronics THC63LVDM83D LVDS serializer ----------------------------------------------- - -The THC63LVDM83D is an LVDS serializer designed to support pixel data -transmission between a host and a flat panel. - -Required properties: - -- compatible: Should be "thine,thc63lvdm83d" - -Optional properties: - -- powerdown-gpios: Power down control GPIO (the /PWDN pin, active low). - -Required nodes: - -The THC63LVDM83D has two video ports. Their connections are modeled using the -OFgraph bindings specified in Documentation/devicetree/bindings/graph.txt. - -- Video port 0 for CMOS/TTL input -- Video port 1 for LVDS output - - -Example -------- - - lvds_enc: encoder@0 { - compatible = "thine,thc63lvdm83d"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint@0 { - remote-endpoint = <&rgb_out>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint@0 { - remote-endpoint = <&panel_in>; - }; - }; - }; - }; From 974e65e384b441062004576c625ade3d54bb5d79 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Wed, 18 Dec 2019 16:57:28 -0800 Subject: [PATCH 51/73] drm/virtio: static-ify virtio_fence_signaled Not used anywhere else. Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191219005733.18960-1-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_drv.h | 1 - drivers/gpu/drm/virtio/virtgpu_fence.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 29cf005ed6b9..349c1dea61c7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -356,7 +356,6 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev, int index); /* virtio_gpu_fence.c */ -bool virtio_fence_signaled(struct dma_fence *f); struct virtio_gpu_fence *virtio_gpu_fence_alloc( struct virtio_gpu_device *vgdev); void virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev, diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index a4b9881ca1d3..5466aab7d39a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -37,7 +37,7 @@ static const char *virtio_get_timeline_name(struct dma_fence *f) return "controlq"; } -bool virtio_fence_signaled(struct dma_fence *f) +static bool virtio_fence_signaled(struct dma_fence *f) { struct virtio_gpu_fence *fence = to_virtio_fence(f); From 9567728ae28c6a8d93068f64642a7d9246ab917d Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Wed, 18 Dec 2019 16:57:29 -0800 Subject: [PATCH 52/73] drm/virtio: static-ify virtio_gpu_framebuffer_init Not used anywhere else. Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191219005733.18960-2-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_display.c | 2 +- drivers/gpu/drm/virtio/virtgpu_drv.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index e622485ae826..c76d69fecfeb 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -59,7 +59,7 @@ static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = { .dirty = drm_atomic_helper_dirtyfb, }; -int +static int virtio_gpu_framebuffer_init(struct drm_device *dev, struct virtio_gpu_framebuffer *vgfb, const struct drm_mode_fb_cmd2 *mode_cmd, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 349c1dea61c7..cf09e4af2fc5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -342,10 +342,6 @@ void virtio_gpu_disable_notify(struct virtio_gpu_device *vgdev); void virtio_gpu_enable_notify(struct virtio_gpu_device *vgdev); /* virtio_gpu_display.c */ -int virtio_gpu_framebuffer_init(struct drm_device *dev, - struct virtio_gpu_framebuffer *vgfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); void virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev); void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev); From 9e07d4617b0156cd93b71fbda2b2a0f15da83e94 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Wed, 18 Dec 2019 16:57:30 -0800 Subject: [PATCH 53/73] drm/virtio: get rid of drm_encoder_to_virtio_gpu_output Not used anywhere. Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191219005733.18960-3-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_drv.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index cf09e4af2fc5..3e0580a8d818 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -137,8 +137,6 @@ struct virtio_gpu_output { container_of(x, struct virtio_gpu_output, crtc) #define drm_connector_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, conn) -#define drm_encoder_to_virtio_gpu_output(x) \ - container_of(x, struct virtio_gpu_output, enc) struct virtio_gpu_framebuffer { struct drm_framebuffer base; From 093bd9cf5e2c775bac9031ea5974a38ee6cca09b Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Wed, 18 Dec 2019 16:57:31 -0800 Subject: [PATCH 54/73] drm/virtio: simplify getting fake offset This is a little simpler. Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191219005733.18960-4-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_drv.h | 8 +------- drivers/gpu/drm/virtio/virtgpu_gem.c | 4 +--- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 3e0580a8d818..578d5e42946e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -365,18 +365,12 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_params *params, struct virtio_gpu_object **bo_ptr, struct virtio_gpu_fence *fence); - /* virtgpu_prime.c */ struct drm_gem_object *virtgpu_gem_prime_import_sg_table( struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); -static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo) -{ - return drm_vma_node_offset_addr(&bo->base.base.vma_node); -} - -/* virgl debufs */ +/* virgl debugfs */ int virtio_gpu_debugfs_init(struct drm_minor *minor); #endif diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 4c1f579edfb3..0a2b62279647 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -96,14 +96,12 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, uint32_t handle, uint64_t *offset_p) { struct drm_gem_object *gobj; - struct virtio_gpu_object *obj; BUG_ON(!offset_p); gobj = drm_gem_object_lookup(file_priv, handle); if (gobj == NULL) return -ENOENT; - obj = gem_to_virtio_gpu_obj(gobj); - *offset_p = virtio_gpu_object_mmap_offset(obj); + *offset_p = drm_vma_node_offset_addr(&gobj->vma_node); drm_gem_object_put_unlocked(gobj); return 0; } From c91a1e2b5a6a72260dd2a116a6157cb9e740c35d Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Wed, 18 Dec 2019 16:57:32 -0800 Subject: [PATCH 55/73] drm/virtio: move to_virtio_fence inside virtgpu_fence That's the only file that uses it. Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191219005733.18960-5-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_drv.h | 2 -- drivers/gpu/drm/virtio/virtgpu_fence.c | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 578d5e42946e..b16e04bd67b7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -103,8 +103,6 @@ struct virtio_gpu_fence { struct virtio_gpu_fence_driver *drv; struct list_head node; }; -#define to_virtio_fence(x) \ - container_of(x, struct virtio_gpu_fence, f) struct virtio_gpu_vbuffer { char *buf; diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index 5466aab7d39a..5b2a4146c5bd 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -27,6 +27,9 @@ #include "virtgpu_drv.h" +#define to_virtio_fence(x) \ + container_of(x, struct virtio_gpu_fence, f) + static const char *virtio_get_driver_name(struct dma_fence *f) { return "virtio_gpu"; From 570c815698c4c1b2f750cbe9ea40111416671d8e Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Wed, 18 Dec 2019 16:57:33 -0800 Subject: [PATCH 56/73] drm/virtio: move drm_connector_to_virtio_gpu_output to virtgpu_display That's the only file that uses it. Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20191219005733.18960-6-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_display.c | 3 +++ drivers/gpu/drm/virtio/virtgpu_drv.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index c76d69fecfeb..0966208ec30d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -43,6 +43,9 @@ #define XRES_MAX 8192 #define YRES_MAX 8192 +#define drm_connector_to_virtio_gpu_output(x) \ + container_of(x, struct virtio_gpu_output, conn) + static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .destroy = drm_crtc_cleanup, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index b16e04bd67b7..7e69c06e168e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -133,8 +133,6 @@ struct virtio_gpu_output { }; #define drm_crtc_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, crtc) -#define drm_connector_to_virtio_gpu_output(x) \ - container_of(x, struct virtio_gpu_output, conn) struct virtio_gpu_framebuffer { struct drm_framebuffer base; From 41cb6603add2028b6763140fed835615da7d4729 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 14:30:44 +0200 Subject: [PATCH 57/73] drm/client: convert to drm device based logging Prefer drm_dbg_kms() and drm_err() over DRM_DEV_DEBUG_KMS() and DRM_DEV_ERROR(). Reviewed-by: Sam Ravnborg Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191210123050.8799-2-jani.nikula@intel.com --- drivers/gpu/drm/drm_client.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index d9a2e3695525..b031b45aa8ef 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -150,7 +150,7 @@ void drm_client_release(struct drm_client_dev *client) { struct drm_device *dev = client->dev; - DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name); + drm_dbg_kms(dev, "%s\n", client->name); drm_client_modeset_free(client); drm_client_close(client); @@ -203,7 +203,7 @@ void drm_client_dev_hotplug(struct drm_device *dev) continue; ret = client->funcs->hotplug(client); - DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret); + drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret); } mutex_unlock(&dev->clientlist_mutex); } @@ -223,7 +223,7 @@ void drm_client_dev_restore(struct drm_device *dev) continue; ret = client->funcs->restore(client); - DRM_DEV_DEBUG_KMS(dev->dev, "%s: ret=%d\n", client->name, ret); + drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret); if (!ret) /* The first one to return zero gets the privilege to restore */ break; } @@ -351,8 +351,8 @@ static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer) ret = drm_mode_rmfb(buffer->client->dev, buffer->fb->base.id, buffer->client->file); if (ret) - DRM_DEV_ERROR(buffer->client->dev->dev, - "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret); + drm_err(buffer->client->dev, + "Error removing FB:%u (%d)\n", buffer->fb->base.id, ret); buffer->fb = NULL; } From f33b9730cc5a33c6dd79ac8718ce2fbd9a75a3e3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 14:30:45 +0200 Subject: [PATCH 58/73] drm/fb-helper: convert to drm device based logging Prefer drm_dbg_kms(), drm_info(), and drm_err() over all other logging. This is about KMS so switch to the KMS category while at it. Reviewed-by: Sam Ravnborg Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191210123050.8799-3-jani.nikula@intel.com --- drivers/gpu/drm/drm_fb_helper.c | 36 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index fb9bff0f4581..f8e905192608 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -191,6 +191,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) { struct drm_fb_helper *helper = info->par; struct drm_client_dev *client = &helper->client; + struct drm_device *dev = helper->dev; struct drm_crtc *crtc; const struct drm_crtc_helper_funcs *funcs; struct drm_mode_set *mode_set; @@ -209,7 +210,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) continue; if (!fb) { - DRM_ERROR("no fb to restore??\n"); + drm_err(dev, "no fb to restore?\n"); continue; } @@ -1248,12 +1249,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, { struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; + struct drm_device *dev = fb_helper->dev; if (in_dbg_master()) return -EINVAL; if (var->pixclock != 0) { - DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n"); + drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n"); var->pixclock = 0; } @@ -1268,7 +1270,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, if (var->bits_per_pixel != fb->format->cpp[0] * 8 || var->xres > fb->width || var->yres > fb->height || var->xres_virtual > fb->width || var->yres_virtual > fb->height) { - DRM_DEBUG("fb requested width/height/bpp can't fit in current fb " + drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb " "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, var->xres_virtual, var->yres_virtual, @@ -1295,7 +1297,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, * so reject all pixel format changing requests. */ if (!drm_fb_pixel_format_equal(var, &info->var)) { - DRM_DEBUG("fbdev emulation doesn't support changing the pixel format\n"); + drm_dbg_kms(dev, "fbdev emulation doesn't support changing the pixel format\n"); return -EINVAL; } @@ -1320,7 +1322,7 @@ int drm_fb_helper_set_par(struct fb_info *info) return -EBUSY; if (var->pixclock != 0) { - DRM_ERROR("PIXEL CLOCK SET\n"); + drm_err(fb_helper->dev, "PIXEL CLOCK SET\n"); return -EINVAL; } @@ -1430,6 +1432,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int preferred_bpp) { struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; int ret = 0; int crtc_count = 0; struct drm_connector_list_iter conn_iter; @@ -1493,7 +1496,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, struct drm_plane *plane = crtc->primary; int j; - DRM_DEBUG("test CRTC %u primary plane\n", drm_crtc_index(crtc)); + drm_dbg_kms(dev, "test CRTC %u primary plane\n", drm_crtc_index(crtc)); for (j = 0; j < plane->format_count; j++) { const struct drm_format_info *fmt; @@ -1526,7 +1529,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, } } if (sizes.surface_depth != best_depth && best_depth) { - DRM_INFO("requested bpp %d, scaled depth down to %d", + drm_info(dev, "requested bpp %d, scaled depth down to %d", sizes.surface_bpp, best_depth); sizes.surface_depth = best_depth; } @@ -1574,7 +1577,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, mutex_unlock(&client->modeset_mutex); if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) { - DRM_INFO("Cannot find any crtc or sizes\n"); + drm_info(dev, "Cannot find any crtc or sizes\n"); /* First time: disable all crtc's.. */ if (!fb_helper->deferred_setup) @@ -1889,7 +1892,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) drm_master_internal_release(fb_helper->dev); - DRM_DEBUG_KMS("\n"); + drm_dbg_kms(fb_helper->dev, "\n"); drm_client_modeset_probe(&fb_helper->client, fb_helper->fb->width, fb_helper->fb->height); drm_setup_crtcs_fb(fb_helper); @@ -2026,15 +2029,16 @@ static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, struct drm_fb_helper_surface_size *sizes) { struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; struct drm_client_buffer *buffer; struct drm_framebuffer *fb; struct fb_info *fbi; u32 format; void *vaddr; - DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n", - sizes->surface_width, sizes->surface_height, - sizes->surface_bpp); + drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n", + sizes->surface_width, sizes->surface_height, + sizes->surface_bpp); format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); buffer = drm_client_framebuffer_create(client, sizes->surface_width, @@ -2118,7 +2122,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client) return drm_fb_helper_hotplug_event(dev->fb_helper); if (!dev->mode_config.num_connector) { - DRM_DEV_DEBUG(dev->dev, "No connectors found, will not create framebuffer!\n"); + drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n"); return 0; } @@ -2143,7 +2147,7 @@ err: fb_helper->dev = NULL; fb_helper->fbdev = NULL; - DRM_DEV_ERROR(dev->dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret); + drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret); return ret; } @@ -2200,7 +2204,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs); if (ret) { kfree(fb_helper); - DRM_DEV_ERROR(dev->dev, "Failed to register client: %d\n", ret); + drm_err(dev, "Failed to register client: %d\n", ret); return ret; } @@ -2212,7 +2216,7 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) ret = drm_fbdev_client_hotplug(&fb_helper->client); if (ret) - DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret); + drm_dbg_kms(dev, "client hotplug ret=%d\n", ret); drm_client_register(&fb_helper->client); From 24f03be4aa7922ef5c6067d2809c5d90dfe275c9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 14:30:46 +0200 Subject: [PATCH 59/73] drm/gem-fb-helper: convert to drm device based logging Prefer drm_dbg_kms() and drm_err() over all other logging. Reviewed-by: Sam Ravnborg Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20191210123050.8799-4-jani.nikula@intel.com --- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index b9bcd310ca2d..3a7ace19a902 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -74,8 +74,7 @@ drm_gem_fb_alloc(struct drm_device *dev, ret = drm_framebuffer_init(dev, fb, funcs); if (ret) { - DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n", - ret); + drm_err(dev, "Failed to init framebuffer: %d\n", ret); kfree(fb); return ERR_PTR(ret); } @@ -160,7 +159,7 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file, objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); if (!objs[i]) { - DRM_DEBUG_KMS("Failed to lookup GEM object\n"); + drm_dbg_kms(dev, "Failed to lookup GEM object\n"); ret = -ENOENT; goto err_gem_object_put; } From 7da5492739db745d935a7044288a7307a0fb7f29 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 16 Dec 2019 16:21:36 +0000 Subject: [PATCH 60/73] drm/gma500: fix null dereference of pointer fb before null check Pointer fb is being dereferenced when assigning dev before it is null checked. Fix this by only dereferencing dev after the null check. Fixes: 6b7ce2c4161a ("drm/gma500: Remove struct psb_fbdev") Signed-off-by: Colin Ian King Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20191216162136.270114-1-colin.king@canonical.com --- drivers/gpu/drm/gma500/accel_2d.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/gma500/accel_2d.c b/drivers/gpu/drm/gma500/accel_2d.c index b9e5a38632f7..adc0507545bf 100644 --- a/drivers/gpu/drm/gma500/accel_2d.c +++ b/drivers/gpu/drm/gma500/accel_2d.c @@ -228,8 +228,8 @@ static void psbfb_copyarea_accel(struct fb_info *info, { struct drm_fb_helper *fb_helper = info->par; struct drm_framebuffer *fb = fb_helper->fb; - struct drm_device *dev = fb->dev; - struct drm_psb_private *dev_priv = dev->dev_private; + struct drm_device *dev; + struct drm_psb_private *dev_priv; uint32_t offset; uint32_t stride; uint32_t src_format; @@ -238,6 +238,8 @@ static void psbfb_copyarea_accel(struct fb_info *info, if (!fb) return; + dev = fb->dev; + dev_priv = dev->dev_private; offset = to_gtt_range(fb->obj[0])->offset; stride = fb->pitches[0]; From 93ccfa9a4eca482216c5caf88be77e5ffa0d744a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 19 Dec 2019 17:17:22 +0100 Subject: [PATCH 61/73] drm/todo: Updating logging todo Jani has merged a new set of logging functions, which we hope to be the One True solution now, pinky promises: commit fb6c7ab8718eb2543695d77ad8302ff81e8e1e32 Author: Jani Nikula Date: Tue Dec 10 14:30:43 2019 +0200 drm/print: introduce new struct drm_device based logging macros Update the todo entry to match the new preference. v2: Fix spelling issue Sam noticed. Cc: Jani Nikula Cc: Sean Paul Cc: Wambui Karuga Acked-by: Jani Nikula Acked-by: Sam Ravnborg Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191219161722.2779994-1-daniel.vetter@ffwll.ch --- Documentation/gpu/todo.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 2d85f37284a1..bc869b23fc39 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -142,14 +142,14 @@ Contact: Daniel Vetter, respective driver maintainers Level: Advanced -Convert instances of dev_info/dev_err/dev_warn to their DRM_DEV_* equivalent ----------------------------------------------------------------------------- +Convert logging to drm_* functions with drm_device paramater +------------------------------------------------------------ For drivers which could have multiple instances, it is necessary to differentiate between which is which in the logs. Since DRM_INFO/WARN/ERROR don't do this, drivers used dev_info/warn/err to make this differentiation. We -now have DRM_DEV_* variants of the drm print macros, so we can start to convert -those drivers back to using drm-formwatted specific log messages. +now have drm_* variants of the drm print functions, so we can start to convert +those drivers back to using drm-formatted specific log messages. Before you start this conversion please contact the relevant maintainers to make sure your work will be merged - not everyone agrees that the DRM dmesg macros From f412af187ae1a0171f779b4666557c60130e1976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Fertr=C3=A9?= Date: Wed, 27 Nov 2019 11:23:38 +0100 Subject: [PATCH 62/73] drm/stm: ltdc: move pinctrl to encoder mode set The pin control must be set to default as soon as possible to establish a good video link between tv & bridge hdmi (encoder mode set is call before encoder enable). Signed-off-by: Yannick Fertre Acked-by: Philippe Cornu Signed-off-by: Benjamin Gaignard Link: https://patchwork.freedesktop.org/patch/msgid/1574850218-13257-1-git-send-email-yannick.fertre@st.com --- drivers/gpu/drm/stm/ltdc.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 5b51298921cf..c2815e8ae1da 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -437,9 +437,6 @@ static void ltdc_crtc_atomic_enable(struct drm_crtc *crtc, /* Commit shadow registers = update planes at next vblank */ reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR); - /* Enable LTDC */ - reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN); - drm_crtc_vblank_on(crtc); } @@ -453,9 +450,6 @@ static void ltdc_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_vblank_off(crtc); - /* disable LTDC */ - reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN); - /* disable IRQ */ reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE); @@ -1044,14 +1038,31 @@ static const struct drm_encoder_funcs ltdc_encoder_funcs = { static void ltdc_encoder_disable(struct drm_encoder *encoder) { struct drm_device *ddev = encoder->dev; + struct ltdc_device *ldev = ddev->dev_private; DRM_DEBUG_DRIVER("\n"); + /* Disable LTDC */ + reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN); + /* Set to sleep state the pinctrl whatever type of encoder */ pinctrl_pm_select_sleep_state(ddev->dev); } static void ltdc_encoder_enable(struct drm_encoder *encoder) +{ + struct drm_device *ddev = encoder->dev; + struct ltdc_device *ldev = ddev->dev_private; + + DRM_DEBUG_DRIVER("\n"); + + /* Enable LTDC */ + reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN); +} + +static void ltdc_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct drm_device *ddev = encoder->dev; @@ -1069,6 +1080,7 @@ static void ltdc_encoder_enable(struct drm_encoder *encoder) static const struct drm_encoder_helper_funcs ltdc_encoder_helper_funcs = { .disable = ltdc_encoder_disable, .enable = ltdc_encoder_enable, + .mode_set = ltdc_encoder_mode_set, }; static int ltdc_encoder_init(struct drm_device *ddev, struct drm_bridge *bridge) From dbe2d2bf79d2675e647d6a22fcb213e30a9b9706 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 6 Dec 2019 14:53:35 +0100 Subject: [PATCH 63/73] drm: Fix a couple of typos, punctation and whitespace issues These are just a couple of things that I came across as I was reading through the code and comments. v2: added one more hunk that ended up in the wrong patch Reviewed-by: Thomas Zimmermann Signed-off-by: Thierry Reding Link: https://patchwork.freedesktop.org/patch/msgid/20191206135336.2084564-1-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic_helper.c | 12 ++++++------ drivers/gpu/drm/drm_edid.c | 2 +- include/drm/drm_atomic.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 57a84555a6bd..766ecd3945f1 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -220,7 +220,7 @@ set_best_encoder(struct drm_atomic_state *state, crtc = conn_state->connector->state->crtc; /* A NULL crtc is an error here because we should have - * duplicated a NULL best_encoder when crtc was NULL. + * duplicated a NULL best_encoder when crtc was NULL. * As an exception restoring duplicated atomic state * during resume is allowed, so don't warn when * best_encoder is equal to encoder we intend to set. @@ -567,7 +567,7 @@ mode_valid(struct drm_atomic_state *state) * * 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder. * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state. - * 3. If it's determined a modeset is needed then all connectors on the affected crtc + * 3. If it's determined a modeset is needed then all connectors on the affected * crtc are added and &drm_connector_helper_funcs.atomic_check is run on them. * 4. &drm_encoder_helper_funcs.mode_valid, &drm_bridge_funcs.mode_valid and * &drm_crtc_helper_funcs.mode_valid are called on the affected components. @@ -1418,7 +1418,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); * @dev: DRM device * @old_state: atomic state object with old state structures * - * Helper to, after atomic commit, wait for vblanks on all effected + * Helper to, after atomic commit, wait for vblanks on all affected * crtcs (ie. before cleaning up old framebuffers using * drm_atomic_helper_cleanup_planes()). It will only wait on CRTCs where the * framebuffers have actually changed to optimize for the legacy cursor and @@ -1478,10 +1478,10 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); * @dev: DRM device * @old_state: atomic state object with old state structures * - * Helper to, after atomic commit, wait for page flips on all effected + * Helper to, after atomic commit, wait for page flips on all affected * crtcs (ie. before cleaning up old framebuffers using * drm_atomic_helper_cleanup_planes()). Compared to - * drm_atomic_helper_wait_for_vblanks() this waits for the completion of on all + * drm_atomic_helper_wait_for_vblanks() this waits for the completion on all * CRTCs, assuming that cursors-only updates are signalling their completion * immediately (or using a different path). * @@ -2195,7 +2195,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies); * drm_atomic_helper_fake_vblank - fake VBLANK events if needed * @old_state: atomic state object with old state structures * - * This function walks all CRTCs and fake VBLANK events on those with + * This function walks all CRTCs and fakes VBLANK events on those with * &drm_crtc_state.no_vblank set to true and &drm_crtc_state.event != NULL. * The primary use of this function is writeback connectors working in oneshot * mode and faking VBLANK events. In this case they only fake the VBLANK event diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ec5b88120428..99769d6c9f84 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -4746,7 +4746,7 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector, if (scdc->supported) { scdc->scrambling.supported = true; - /* Few sinks support scrambling for cloks < 340M */ + /* Few sinks support scrambling for clocks < 340M */ if ((hf_vsdb[6] & 0x8)) scdc->scrambling.low_rates = true; } diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 5923819dcd68..c552d2dc9717 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -35,7 +35,7 @@ * struct drm_crtc_commit - track modeset commits on a CRTC * * This structure is used to track pending modeset changes and atomic commit on - * a per-CRTC basis. Since updating the list should never block this structure + * a per-CRTC basis. Since updating the list should never block, this structure * is reference counted to allow waiters to safely wait on an event to complete, * without holding any locks. * From 42240c90e3b03deb52c224609e1b2b132ff40f8b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 6 Dec 2019 14:53:36 +0100 Subject: [PATCH 64/73] drm/atomic: Spell CRTC consistently CRTC is an abbreviation and should be all caps in prose. Update all kerneldoc comments to use a consistent spelling. v2: remove hunk unrelated to the CRTC spelling fixes Reviewed-by: Thomas Zimmermann Signed-off-by: Thierry Reding Link: https://patchwork.freedesktop.org/patch/msgid/20191206135336.2084564-2-thierry.reding@gmail.com --- drivers/gpu/drm/drm_atomic.c | 20 ++++----- drivers/gpu/drm/drm_atomic_helper.c | 64 ++++++++++++++--------------- drivers/gpu/drm/drm_atomic_uapi.c | 16 ++++---- include/drm/drm_atomic.h | 30 +++++++------- include/drm/drm_atomic_helper.h | 8 ++-- 5 files changed, 69 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index ab4508f25986..d33691512a8e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -251,7 +251,7 @@ EXPORT_SYMBOL(drm_atomic_state_clear); * @ref: This atomic state to deallocate * * This frees all memory associated with an atomic state, including all the - * per-object state for planes, crtcs and connectors. + * per-object state for planes, CRTCs and connectors. */ void __drm_atomic_state_free(struct kref *ref) { @@ -272,12 +272,12 @@ void __drm_atomic_state_free(struct kref *ref) EXPORT_SYMBOL(__drm_atomic_state_free); /** - * drm_atomic_get_crtc_state - get crtc state + * drm_atomic_get_crtc_state - get CRTC state * @state: global atomic state object - * @crtc: crtc to get state object for + * @crtc: CRTC to get state object for * - * This function returns the crtc state for the given crtc, allocating it if - * needed. It will also grab the relevant crtc lock to make sure that the state + * This function returns the CRTC state for the given CRTC, allocating it if + * needed. It will also grab the relevant CRTC lock to make sure that the state * is consistent. * * Returns: @@ -1018,14 +1018,14 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, } /** - * drm_atomic_add_affected_connectors - add connectors for crtc + * drm_atomic_add_affected_connectors - add connectors for CRTC * @state: atomic state - * @crtc: DRM crtc + * @crtc: DRM CRTC * * This function walks the current configuration and adds all connectors * currently using @crtc to the atomic configuration @state. Note that this * function must acquire the connection mutex. This can potentially cause - * unneeded seralization if the update is just for the planes on one crtc. Hence + * unneeded seralization if the update is just for the planes on one CRTC. Hence * drivers and helpers should only call this when really needed (e.g. when a * full modeset needs to happen due to some change). * @@ -1078,9 +1078,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state, EXPORT_SYMBOL(drm_atomic_add_affected_connectors); /** - * drm_atomic_add_affected_planes - add planes for crtc + * drm_atomic_add_affected_planes - add planes for CRTC * @state: atomic state - * @crtc: DRM crtc + * @crtc: DRM CRTC * * This function walks the current configuration and adds all planes * currently used by @crtc to the atomic configuration @state. This is useful diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 766ecd3945f1..57201e36b8b7 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -150,8 +150,8 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, * is not set, an error is returned. Userspace can provide a solution * through the atomic ioctl. * - * If the flag is set conflicting connectors are removed from the crtc - * and the crtc is disabled if no encoder is left. This preserves + * If the flag is set conflicting connectors are removed from the CRTC + * and the CRTC is disabled if no encoder is left. This preserves * compatibility with the legacy set_config behavior. */ drm_connector_list_iter_begin(state->dev, &conn_iter); @@ -561,27 +561,27 @@ mode_valid(struct drm_atomic_state *state) * @state: the driver state object * * Check the state object to see if the requested state is physically possible. - * This does all the crtc and connector related computations for an atomic + * This does all the CRTC and connector related computations for an atomic * update and adds any additional connectors needed for full modesets. It calls * the various per-object callbacks in the follow order: * * 1. &drm_connector_helper_funcs.atomic_best_encoder for determining the new encoder. * 2. &drm_connector_helper_funcs.atomic_check to validate the connector state. * 3. If it's determined a modeset is needed then all connectors on the affected - * crtc are added and &drm_connector_helper_funcs.atomic_check is run on them. + * CRTC are added and &drm_connector_helper_funcs.atomic_check is run on them. * 4. &drm_encoder_helper_funcs.mode_valid, &drm_bridge_funcs.mode_valid and * &drm_crtc_helper_funcs.mode_valid are called on the affected components. * 5. &drm_bridge_funcs.mode_fixup is called on all encoder bridges. * 6. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state. - * This function is only called when the encoder will be part of a configured crtc, + * This function is only called when the encoder will be part of a configured CRTC, * it must not be used for implementing connector property validation. * If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called * instead. - * 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints. + * 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with CRTC constraints. * * &drm_crtc_state.mode_changed is set when the input mode is changed. * &drm_crtc_state.connectors_changed is set when a connector is added or - * removed from the crtc. &drm_crtc_state.active_changed is set when + * removed from the CRTC. &drm_crtc_state.active_changed is set when * &drm_crtc_state.active changes, which is used for DPMS. * See also: drm_atomic_crtc_needs_modeset() * @@ -692,7 +692,7 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, /* * After all the routing has been prepared we need to add in any - * connector which is itself unchanged, but whose crtc changes its + * connector which is itself unchanged, but whose CRTC changes its * configuration. This must be done before calling mode_fixup in case a * crtc only changed its mode but has the same set of connectors. */ @@ -741,13 +741,13 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset); /** * drm_atomic_helper_check_plane_state() - Check plane state for validity * @plane_state: plane state to check - * @crtc_state: crtc state to check + * @crtc_state: CRTC state to check * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point * @can_position: is it legal to position the plane such that it - * doesn't cover the entire crtc? This will generally + * doesn't cover the entire CRTC? This will generally * only be false for primary planes. - * @can_update_disabled: can the plane be updated while the crtc + * @can_update_disabled: can the plane be updated while the CRTC * is disabled? * * Checks that a desired plane update is valid, and updates various @@ -844,7 +844,7 @@ EXPORT_SYMBOL(drm_atomic_helper_check_plane_state); * &drm_crtc_helper_funcs.atomic_check and &drm_plane_helper_funcs.atomic_check * hooks provided by the driver. * - * It also sets &drm_crtc_state.planes_changed to indicate that a crtc has + * It also sets &drm_crtc_state.planes_changed to indicate that a CRTC has * updated planes. * * RETURNS: @@ -908,7 +908,7 @@ EXPORT_SYMBOL(drm_atomic_helper_check_planes); * @state: the driver state object * * Check the state object to see if the requested state is physically possible. - * Only crtcs and planes have check callbacks, so for any additional (global) + * Only CRTCs and planes have check callbacks, so for any additional (global) * checking that a driver needs it can simply wrap that around this function. * Drivers without such needs can directly use this as their * &drm_mode_config_funcs.atomic_check callback. @@ -961,14 +961,14 @@ crtc_needs_disable(struct drm_crtc_state *old_state, struct drm_crtc_state *new_state) { /* - * No new_state means the crtc is off, so the only criteria is whether + * No new_state means the CRTC is off, so the only criteria is whether * it's currently active or in self refresh mode. */ if (!new_state) return drm_atomic_crtc_effectively_active(old_state); /* - * We need to run through the crtc_funcs->disable() function if the crtc + * We need to run through the crtc_funcs->disable() function if the CRTC * is currently on, if it's transitioning to self refresh mode, or if * it's in self refresh mode and needs to be fully disabled. */ @@ -1087,7 +1087,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) * @old_state: atomic state object with old state structures * * This function updates all the various legacy modeset state pointers in - * connectors, encoders and crtcs. It also updates the timestamping constants + * connectors, encoders and CRTCs. It also updates the timestamping constants * used for precise vblank timestamps by calling * drm_calc_timestamping_constants(). * @@ -1236,7 +1236,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state) * This function shuts down all the outputs that need to be shut down and * prepares them (if required) with the new mode. * - * For compatibility with legacy crtc helpers this should be called before + * For compatibility with legacy CRTC helpers this should be called before * drm_atomic_helper_commit_planes(), which is what the default commit function * does. But drivers with different needs can group the modeset commits together * and do the plane commits at the end. This is useful for drivers doing runtime @@ -1282,7 +1282,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev, * This function enables all the outputs with the new configuration which had to * be turned off for the update. * - * For compatibility with legacy crtc helpers this should be called after + * For compatibility with legacy CRTC helpers this should be called after * drm_atomic_helper_commit_planes(), which is what the default commit function * does. But drivers with different needs can group the modeset commits together * and do the plane commits at the end. This is useful for drivers doing runtime @@ -1414,12 +1414,12 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); /** - * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs + * drm_atomic_helper_wait_for_vblanks - wait for vblank on CRTCs * @dev: DRM device * @old_state: atomic state object with old state structures * * Helper to, after atomic commit, wait for vblanks on all affected - * crtcs (ie. before cleaning up old framebuffers using + * CRTCs (ie. before cleaning up old framebuffers using * drm_atomic_helper_cleanup_planes()). It will only wait on CRTCs where the * framebuffers have actually changed to optimize for the legacy cursor and * plane update use-case. @@ -2391,7 +2391,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state) * @flags: flags for committing plane state * * This function commits the new plane state using the plane and atomic helper - * functions for planes and crtcs. It assumes that the atomic state has already + * functions for planes and CRTCs. It assumes that the atomic state has already * been pushed into the relevant object state pointers, since this step can no * longer fail. * @@ -2512,15 +2512,15 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_commit_planes); /** - * drm_atomic_helper_commit_planes_on_crtc - commit plane state for a crtc - * @old_crtc_state: atomic state object with the old crtc state + * drm_atomic_helper_commit_planes_on_crtc - commit plane state for a CRTC + * @old_crtc_state: atomic state object with the old CRTC state * * This function commits the new plane state using the plane and atomic helper - * functions for planes on the specific crtc. It assumes that the atomic state + * functions for planes on the specific CRTC. It assumes that the atomic state * has already been pushed into the relevant object state pointers, since this * step can no longer fail. * - * This function is useful when plane updates should be done crtc-by-crtc + * This function is useful when plane updates should be done CRTC-by-CRTC * instead of one global step like drm_atomic_helper_commit_planes() does. * * This function can only be savely used when planes are not allowed to move @@ -2810,10 +2810,10 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state); * @plane: plane object to update * @crtc: owning CRTC of owning plane * @fb: framebuffer to flip onto plane - * @crtc_x: x offset of primary plane on crtc - * @crtc_y: y offset of primary plane on crtc - * @crtc_w: width of primary plane rectangle on crtc - * @crtc_h: height of primary plane rectangle on crtc + * @crtc_x: x offset of primary plane on @crtc + * @crtc_y: y offset of primary plane on @crtc + * @crtc_w: width of primary plane rectangle on @crtc + * @crtc_h: height of primary plane rectangle on @crtc * @src_x: x offset of @fb for panning * @src_y: y offset of @fb for panning * @src_w: width of source rectangle in @fb @@ -2919,7 +2919,7 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_plane); * @set: mode set configuration * @ctx: lock acquisition context * - * Provides a default crtc set_config handler using the atomic driver interface. + * Provides a default CRTC set_config handler using the atomic driver interface. * * NOTE: For backwards compatibility with old userspace this automatically * resets the "link-status" property to GOOD, to force any link @@ -3332,7 +3332,7 @@ static int page_flip_common(struct drm_atomic_state *state, /** * drm_atomic_helper_page_flip - execute a legacy page flip - * @crtc: DRM crtc + * @crtc: DRM CRTC * @fb: DRM framebuffer * @event: optional DRM event to signal upon completion * @flags: flip flags for non-vblank sync'ed updates @@ -3376,7 +3376,7 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip); /** * drm_atomic_helper_page_flip_target - do page flip on target vblank period. - * @crtc: DRM crtc + * @crtc: DRM CRTC * @fb: DRM framebuffer * @event: optional DRM event to signal upon completion * @flags: flip flags for non-vblank sync'ed updates diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 0d466d3b0809..a1e5e262bae2 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -160,12 +160,12 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); /** - * drm_atomic_set_crtc_for_plane - set crtc for plane + * drm_atomic_set_crtc_for_plane - set CRTC for plane * @plane_state: the plane whose incoming state to update - * @crtc: crtc to use for the plane + * @crtc: CRTC to use for the plane * - * Changing the assigned crtc for a plane requires us to grab the lock and state - * for the new crtc, as needed. This function takes care of all these details + * Changing the assigned CRTC for a plane requires us to grab the lock and state + * for the new CRTC, as needed. This function takes care of all these details * besides updating the pointer in the state object itself. * * Returns: @@ -279,12 +279,12 @@ drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, EXPORT_SYMBOL(drm_atomic_set_fence_for_plane); /** - * drm_atomic_set_crtc_for_connector - set crtc for connector + * drm_atomic_set_crtc_for_connector - set CRTC for connector * @conn_state: atomic state object for the connector - * @crtc: crtc to use for the connector + * @crtc: CRTC to use for the connector * - * Changing the assigned crtc for a connector requires us to grab the lock and - * state for the new crtc, as needed. This function takes care of all these + * Changing the assigned CRTC for a connector requires us to grab the lock and + * state for the new CRTC, as needed. This function takes care of all these * details besides updating the pointer in the state object itself. * * Returns: diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index c552d2dc9717..951dfb15c27b 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -363,7 +363,7 @@ struct drm_atomic_state { * When a connector or plane is not bound to any CRTC, it's still important * to preserve linearity to prevent the atomic states from being freed to early. * - * This commit (if set) is not bound to any crtc, but will be completed when + * This commit (if set) is not bound to any CRTC, but will be completed when * drm_atomic_helper_commit_hw_done() is called. */ struct drm_crtc_commit *fake_commit; @@ -476,12 +476,12 @@ drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state, struct drm_encoder *encoder); /** - * drm_atomic_get_existing_crtc_state - get crtc state, if it exists + * drm_atomic_get_existing_crtc_state - get CRTC state, if it exists * @state: global atomic state object - * @crtc: crtc to grab + * @crtc: CRTC to grab * - * This function returns the crtc state for the given crtc, or NULL - * if the crtc is not part of the global atomic state. + * This function returns the CRTC state for the given CRTC, or NULL + * if the CRTC is not part of the global atomic state. * * This function is deprecated, @drm_atomic_get_old_crtc_state or * @drm_atomic_get_new_crtc_state should be used instead. @@ -494,12 +494,12 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, } /** - * drm_atomic_get_old_crtc_state - get old crtc state, if it exists + * drm_atomic_get_old_crtc_state - get old CRTC state, if it exists * @state: global atomic state object - * @crtc: crtc to grab + * @crtc: CRTC to grab * - * This function returns the old crtc state for the given crtc, or - * NULL if the crtc is not part of the global atomic state. + * This function returns the old CRTC state for the given CRTC, or + * NULL if the CRTC is not part of the global atomic state. */ static inline struct drm_crtc_state * drm_atomic_get_old_crtc_state(struct drm_atomic_state *state, @@ -508,12 +508,12 @@ drm_atomic_get_old_crtc_state(struct drm_atomic_state *state, return state->crtcs[drm_crtc_index(crtc)].old_state; } /** - * drm_atomic_get_new_crtc_state - get new crtc state, if it exists + * drm_atomic_get_new_crtc_state - get new CRTC state, if it exists * @state: global atomic state object - * @crtc: crtc to grab + * @crtc: CRTC to grab * - * This function returns the new crtc state for the given crtc, or - * NULL if the crtc is not part of the global atomic state. + * This function returns the new CRTC state for the given CRTC, or + * NULL if the CRTC is not part of the global atomic state. */ static inline struct drm_crtc_state * drm_atomic_get_new_crtc_state(struct drm_atomic_state *state, @@ -978,11 +978,11 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state) } /** - * drm_atomic_crtc_effectively_active - compute whether crtc is actually active + * drm_atomic_crtc_effectively_active - compute whether CRTC is actually active * @state: &drm_crtc_state for the CRTC * * When in self refresh mode, the crtc_state->active value will be false, since - * the crtc is off. However in some cases we're interested in whether the crtc + * the CRTC is off. However in some cases we're interested in whether the CRTC * is active, or effectively active (ie: it's connected to an active display). * In these cases, use this function instead of just checking active. */ diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index bf4e07141d81..9db3cac48f4f 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -152,7 +152,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, /** * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC * @plane: the loop cursor - * @crtc: the crtc whose planes are iterated + * @crtc: the CRTC whose planes are iterated * * This iterates over the current state, useful (for example) when applying * atomic state after it has been checked and swapped. To iterate over the @@ -166,7 +166,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, /** * drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state * @plane: the loop cursor - * @crtc_state: the incoming crtc-state + * @crtc_state: the incoming CRTC state * * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be * attached if the specified state is applied. Useful during for example @@ -180,7 +180,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, * drm_crtc_atomic_state_for_each_plane_state - iterate over attached planes in new state * @plane: the loop cursor * @plane_state: loop cursor for the plane's state, must be const - * @crtc_state: the incoming crtc-state + * @crtc_state: the incoming CRTC state * * Similar to drm_crtc_for_each_plane(), but iterates the planes that will be * attached if the specified state is applied. Useful during for example @@ -189,7 +189,7 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, * * Compared to just drm_atomic_crtc_state_for_each_plane() this also fills in a * const plane_state. This is useful when a driver just wants to peek at other - * active planes on this crtc, but does not need to change it. + * active planes on this CRTC, but does not need to change it. */ #define drm_atomic_crtc_state_for_each_plane_state(plane, plane_state, crtc_state) \ drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask) \ From 624b4b48d9d870c2858c016d8709715495409654 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 29 Oct 2019 12:28:46 +0100 Subject: [PATCH 65/73] drm: sun4i: Add support for suspending the display driver Shut down the display engine during suspend. Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191029112846.3604925-1-megous@megous.com --- drivers/gpu/drm/sun4i/sun4i_drv.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index a5757b11b730..5ae67d526b1d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -346,6 +346,27 @@ static int sun4i_drv_add_endpoints(struct device *dev, return count; } +#ifdef CONFIG_PM_SLEEP +static int sun4i_drv_drm_sys_suspend(struct device *dev) +{ + struct drm_device *drm = dev_get_drvdata(dev); + + return drm_mode_config_helper_suspend(drm); +} + +static int sun4i_drv_drm_sys_resume(struct device *dev) +{ + struct drm_device *drm = dev_get_drvdata(dev); + + return drm_mode_config_helper_resume(drm); +} +#endif + +static const struct dev_pm_ops sun4i_drv_drm_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(sun4i_drv_drm_sys_suspend, + sun4i_drv_drm_sys_resume) +}; + static int sun4i_drv_probe(struct platform_device *pdev) { struct component_match *match = NULL; @@ -418,6 +439,7 @@ static struct platform_driver sun4i_drv_platform_driver = { .driver = { .name = "sun4i-drm", .of_match_table = sun4i_drv_of_table, + .pm = &sun4i_drv_drm_pm_ops, }, }; module_platform_driver(sun4i_drv_platform_driver); From fe5040f2843a638d847282520e5eeaa61a4769e2 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:23 +0530 Subject: [PATCH 66/73] dt-bindings: sun6i-dsi: Document A64 MIPI-DSI controller The MIPI DSI controller in Allwinner A64 is similar to A33. But unlike A33, A64 doesn't have DSI_SCLK gating so it is valid to have separate compatible for A64 on the same driver. DSI_SCLK uses mod clock-names on dt-bindings, so the same is not required for A64. On that note - A64 require minimum of 1 clock like the bus clock - A33 require minimum of 2 clocks like both bus, mod clocks So, update dt-bindings so-that it can document both A33, A64 bindings requirements. Reviewed-by: Rob Herring Signed-off-by: Jagan Teki Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-2-jagan@amarulasolutions.com --- .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml index dafc0980c4fa..d41ecb5e7f7c 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml @@ -15,7 +15,9 @@ properties: "#size-cells": true compatible: - const: allwinner,sun6i-a31-mipi-dsi + enum: + - allwinner,sun6i-a31-mipi-dsi + - allwinner,sun50i-a64-mipi-dsi reg: maxItems: 1 @@ -24,6 +26,8 @@ properties: maxItems: 1 clocks: + minItems: 1 + maxItems: 2 items: - description: Bus Clock - description: Module Clock @@ -63,13 +67,38 @@ required: - reg - interrupts - clocks - - clock-names - phys - phy-names - resets - vcc-dsi-supply - port +allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-mipi-dsi + + then: + properties: + clocks: + minItems: 2 + + required: + - clock-names + + - if: + properties: + compatible: + contains: + const: allwinner,sun50i-a64-mipi-dsi + + then: + properties: + clocks: + minItems: 1 + additionalProperties: false examples: From db08ca5a64d208645301600e79f34e441e5da986 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:24 +0530 Subject: [PATCH 67/73] dt-bindings: sun6i-dsi: Add A64 DPHY compatible (w/ A31 fallback) The MIPI DSI PHY controller on Allwinner A64 is similar on the one on A31. Add A64 compatible and append A31 compatible as fallback. Reviewed-by: Rob Herring Signed-off-by: Jagan Teki Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-3-jagan@amarulasolutions.com --- .../bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml index fa46670de299..8841938050b2 100644 --- a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml +++ b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml @@ -15,7 +15,11 @@ properties: const: 0 compatible: - const: allwinner,sun6i-a31-mipi-dphy + oneOf: + - const: allwinner,sun6i-a31-mipi-dphy + - items: + - const: allwinner,sun50i-a64-mipi-dphy + - const: allwinner,sun6i-a31-mipi-dphy reg: maxItems: 1 From 26a839b3c286060ff3a6d7b14194ae845ec5aa96 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:25 +0530 Subject: [PATCH 68/73] drm/sun4i: dsi: Get the mod clock for A31 As per the user manual, look like mod clock is not mandatory for all Allwinner MIPI DSI controllers, it is connected to CLK_DSI_SCLK for A31 and not available in A64. So, add compatible check for A31 and get mod clock accordingly. Tested-by: Merlijn Wajer Signed-off-by: Jagan Teki Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-4-jagan@amarulasolutions.com --- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index 4e8f634cc2db..9bb3222c95b9 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -1120,10 +1120,13 @@ static int sun6i_dsi_probe(struct platform_device *pdev) return PTR_ERR(dsi->reset); } - dsi->mod_clk = devm_clk_get(dev, "mod"); - if (IS_ERR(dsi->mod_clk)) { - dev_err(dev, "Couldn't get the DSI mod clock\n"); - return PTR_ERR(dsi->mod_clk); + if (of_device_is_compatible(dev->of_node, + "allwinner,sun6i-a31-mipi-dsi")) { + dsi->mod_clk = devm_clk_get(dev, "mod"); + if (IS_ERR(dsi->mod_clk)) { + dev_err(dev, "Couldn't get the DSI mod clock\n"); + return PTR_ERR(dsi->mod_clk); + } } /* From 66dbdc7c61627a3d3b50017a1d202dc637a10f53 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:26 +0530 Subject: [PATCH 69/73] drm/sun4i: dsi: Handle bus clock via regmap_mmio_attach_clk regmap has special API to enable the controller bus clock while initializing register space, and current driver is using devm_regmap_init_mmio_clk which require to specify bus clk_id argument as "bus" But, the usage of clocks are varies between different Allwinner DSI controllers. Clocking in A33 would need bus and mod clocks where as A64 would need only bus clock. Since A64 support only single bus clock, it is optional to specify the clock-names on the controller device tree node. So using NULL on clk_id would get the attached clock. To support clk_id as "bus" and "NULL" during clock enablement between controllers, this patch add generic code to handle the bus clock using regmap_mmio_attach_clk with associated regmap APIs. Signed-off-by: Jagan Teki Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-5-jagan@amarulasolutions.com --- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 37 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index 9bb3222c95b9..cdfec03bf1a4 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -1081,6 +1081,7 @@ static const struct component_ops sun6i_dsi_ops = { static int sun6i_dsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + const char *bus_clk_name = NULL; struct sun6i_dsi *dsi; struct resource *res; void __iomem *base; @@ -1094,6 +1095,10 @@ static int sun6i_dsi_probe(struct platform_device *pdev) dsi->host.ops = &sun6i_dsi_host_ops; dsi->host.dev = dev; + if (of_device_is_compatible(dev->of_node, + "allwinner,sun6i-a31-mipi-dsi")) + bus_clk_name = "bus"; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) { @@ -1107,25 +1112,35 @@ static int sun6i_dsi_probe(struct platform_device *pdev) return PTR_ERR(dsi->regulator); } - dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base, - &sun6i_dsi_regmap_config); - if (IS_ERR(dsi->regs)) { - dev_err(dev, "Couldn't create the DSI encoder regmap\n"); - return PTR_ERR(dsi->regs); - } - dsi->reset = devm_reset_control_get_shared(dev, NULL); if (IS_ERR(dsi->reset)) { dev_err(dev, "Couldn't get our reset line\n"); return PTR_ERR(dsi->reset); } + dsi->regs = devm_regmap_init_mmio(dev, base, &sun6i_dsi_regmap_config); + if (IS_ERR(dsi->regs)) { + dev_err(dev, "Couldn't init regmap\n"); + return PTR_ERR(dsi->regs); + } + + dsi->bus_clk = devm_clk_get(dev, bus_clk_name); + if (IS_ERR(dsi->bus_clk)) { + dev_err(dev, "Couldn't get the DSI bus clock\n"); + return PTR_ERR(dsi->bus_clk); + } + + ret = regmap_mmio_attach_clk(dsi->regs, dsi->bus_clk); + if (ret) + return ret; + if (of_device_is_compatible(dev->of_node, "allwinner,sun6i-a31-mipi-dsi")) { dsi->mod_clk = devm_clk_get(dev, "mod"); if (IS_ERR(dsi->mod_clk)) { dev_err(dev, "Couldn't get the DSI mod clock\n"); - return PTR_ERR(dsi->mod_clk); + ret = PTR_ERR(dsi->mod_clk); + goto err_attach_clk; } } @@ -1164,6 +1179,9 @@ err_pm_disable: pm_runtime_disable(dev); err_unprotect_clk: clk_rate_exclusive_put(dsi->mod_clk); +err_attach_clk: + if (!IS_ERR(dsi->bus_clk)) + regmap_mmio_detach_clk(dsi->regs); return ret; } @@ -1177,6 +1195,9 @@ static int sun6i_dsi_remove(struct platform_device *pdev) pm_runtime_disable(dev); clk_rate_exclusive_put(dsi->mod_clk); + if (!IS_ERR(dsi->bus_clk)) + regmap_mmio_detach_clk(dsi->regs); + return 0; } From 52028bfcb2330189c5e4ab943b3530b2117b8525 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:27 +0530 Subject: [PATCH 70/73] drm/sun4i: dsi: Add Allwinner A64 MIPI DSI support The MIPI DSI controller in Allwinner A64 is similar to A33. But unlike A33, A64 doesn't have DSI_SCLK gating so add compatible for Allwinner A64 with uninitialized has_mod_clk driver. Signed-off-by: Jagan Teki Tested-by: Merlijn Wajer Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-6-jagan@amarulasolutions.com --- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index cdfec03bf1a4..a75fcb113172 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -1256,6 +1256,7 @@ static const struct dev_pm_ops sun6i_dsi_pm_ops = { static const struct of_device_id sun6i_dsi_of_table[] = { { .compatible = "allwinner,sun6i-a31-mipi-dsi" }, + { .compatible = "allwinner,sun50i-a64-mipi-dsi" }, { } }; MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table); From 8f902dbd6ed2397ac16ab7f7f67e66f5ff1f8bba Mon Sep 17 00:00:00 2001 From: "james qian wang (Arm Technology China)" Date: Thu, 12 Dec 2019 07:27:55 +0000 Subject: [PATCH 71/73] drm/komeda: Add event handling for EMPTY/FULL EMPTY/FULL are HW input/output FIFO condition identifer, which are useful information for addressing the problem, so expose them. Signed-off-by: james qian wang (Arm Technology China) Reviewed-by: Mihail Atanassov Link: https://patchwork.freedesktop.org/patch/msgid/20191212072737.30116-1-james.qian.wang@arm.com --- drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c | 13 ++++++++++++- drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h | 3 +++ drivers/gpu/drm/arm/display/komeda/komeda_dev.h | 5 ++++- drivers/gpu/drm/arm/display/komeda/komeda_event.c | 2 ++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c index dd1ecf4276d3..00fa56c29b3e 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c @@ -20,8 +20,10 @@ static u64 get_lpu_event(struct d71_pipeline *d71_pipeline) evts |= KOMEDA_EVENT_IBSY; if (raw_status & LPU_IRQ_EOW) evts |= KOMEDA_EVENT_EOW; + if (raw_status & LPU_IRQ_OVR) + evts |= KOMEDA_EVENT_OVR; - if (raw_status & (LPU_IRQ_ERR | LPU_IRQ_IBSY)) { + if (raw_status & (LPU_IRQ_ERR | LPU_IRQ_IBSY | LPU_IRQ_OVR)) { u32 restore = 0, tbu_status; /* Check error of LPU status */ status = malidp_read32(reg, BLK_STATUS); @@ -45,6 +47,15 @@ static u64 get_lpu_event(struct d71_pipeline *d71_pipeline) restore |= LPU_STATUS_ACE3; evts |= KOMEDA_ERR_ACE3; } + if (status & LPU_STATUS_FEMPTY) { + restore |= LPU_STATUS_FEMPTY; + evts |= KOMEDA_EVENT_EMPTY; + } + if (status & LPU_STATUS_FFULL) { + restore |= LPU_STATUS_FFULL; + evts |= KOMEDA_EVENT_FULL; + } + if (restore != 0) malidp_write32_mask(reg, BLK_STATUS, restore, 0); diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h index 81de6a23e7f3..e80172a0b320 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_regs.h @@ -175,6 +175,7 @@ #define TBU_DOUTSTDCAPB_MASK 0x3F /* LPU_IRQ_BITS */ +#define LPU_IRQ_OVR BIT(9) #define LPU_IRQ_IBSY BIT(10) #define LPU_IRQ_ERR BIT(11) #define LPU_IRQ_EOW BIT(12) @@ -185,6 +186,8 @@ #define LPU_STATUS_AXIE BIT(4) #define LPU_STATUS_AXIRP BIT(5) #define LPU_STATUS_AXIWP BIT(6) +#define LPU_STATUS_FEMPTY BIT(11) +#define LPU_STATUS_FFULL BIT(14) #define LPU_STATUS_ACE0 BIT(16) #define LPU_STATUS_ACE1 BIT(17) #define LPU_STATUS_ACE2 BIT(18) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index 4a67a80d5fcf..ce27f2f27c24 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h @@ -20,6 +20,8 @@ #define KOMEDA_EVENT_OVR BIT_ULL(4) #define KOMEDA_EVENT_EOW BIT_ULL(5) #define KOMEDA_EVENT_MODE BIT_ULL(6) +#define KOMEDA_EVENT_FULL BIT_ULL(7) +#define KOMEDA_EVENT_EMPTY BIT_ULL(8) #define KOMEDA_ERR_TETO BIT_ULL(14) #define KOMEDA_ERR_TEMR BIT_ULL(15) @@ -49,7 +51,8 @@ KOMEDA_ERR_ZME | KOMEDA_ERR_MERR | KOMEDA_ERR_TCF |\ KOMEDA_ERR_TTNG | KOMEDA_ERR_TTF) -#define KOMEDA_WARN_EVENTS KOMEDA_ERR_CSCE +#define KOMEDA_WARN_EVENTS \ + (KOMEDA_ERR_CSCE | KOMEDA_EVENT_FULL | KOMEDA_EVENT_EMPTY) #define KOMEDA_INFO_EVENTS (0 \ | KOMEDA_EVENT_VSYNC \ diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_event.c b/drivers/gpu/drm/arm/display/komeda/komeda_event.c index 977c38d516da..53f944e66dfc 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_event.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_event.c @@ -78,6 +78,8 @@ static void evt_str(struct komeda_str *str, u64 events) /* LPU errors or events */ evt_sprintf(str, events & KOMEDA_EVENT_IBSY, "IBSY|"); + evt_sprintf(str, events & KOMEDA_EVENT_EMPTY, "EMPTY|"); + evt_sprintf(str, events & KOMEDA_EVENT_FULL, "FULL|"); evt_sprintf(str, events & KOMEDA_ERR_AXIE, "AXIE|"); evt_sprintf(str, events & KOMEDA_ERR_ACE0, "ACE0|"); evt_sprintf(str, events & KOMEDA_ERR_ACE1, "ACE1|"); From efb4650885187425f1da96460e5d2a84650f861a Mon Sep 17 00:00:00 2001 From: "james qian wang (Arm Technology China)" Date: Thu, 12 Dec 2019 07:48:13 +0000 Subject: [PATCH 72/73] drm/komeda: Add runtime_pm support - Add pm_runtime_get/put to crtc_enable/disable along with the real display usage - Add runtime_get/put to register_show, since register_show() will access register, need to wakeup HW. - For the case that PM is not enabled or configured, manually wakeup HW Signed-off-by: james qian wang (Arm Technology China) Reviewed-by: Mihail Atanassov Link: https://patchwork.freedesktop.org/patch/msgid/20191212074756.14678-1-james.qian.wang@arm.com --- .../gpu/drm/arm/display/komeda/komeda_crtc.c | 3 + .../gpu/drm/arm/display/komeda/komeda_dev.c | 55 +++++-------------- .../gpu/drm/arm/display/komeda/komeda_drv.c | 42 ++++++++++++-- .../gpu/drm/arm/display/komeda/komeda_kms.c | 6 -- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 1c452ea75999..56bd938961ee 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -5,6 +5,7 @@ * */ #include +#include #include #include @@ -274,6 +275,7 @@ static void komeda_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old) { + pm_runtime_get_sync(crtc->dev->dev); komeda_crtc_prepare(to_kcrtc(crtc)); drm_crtc_vblank_on(crtc); WARN_ON(drm_crtc_vblank_get(crtc)); @@ -372,6 +374,7 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc, drm_crtc_vblank_put(crtc); drm_crtc_vblank_off(crtc); komeda_crtc_unprepare(kcrtc); + pm_runtime_put(crtc->dev->dev); } static void diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c index 38b832804bad..1d767473ba8a 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #ifdef CONFIG_DEBUG_FS #include @@ -27,12 +28,16 @@ static int komeda_register_show(struct seq_file *sf, void *x) seq_puts(sf, "\n====== Komeda register dump =========\n"); + pm_runtime_get_sync(mdev->dev); + if (mdev->funcs->dump_register) mdev->funcs->dump_register(mdev, sf); for (i = 0; i < mdev->n_pipelines; i++) komeda_pipeline_dump_register(mdev->pipelines[i], sf); + pm_runtime_put(mdev->dev); + return 0; } @@ -263,15 +268,6 @@ struct komeda_dev *komeda_dev_create(struct device *dev) if (!mdev->iommu) DRM_INFO("continue without IOMMU support!\n"); - if (mdev->iommu && mdev->funcs->connect_iommu) { - err = mdev->funcs->connect_iommu(mdev); - if (err) { - DRM_ERROR("connect iommu failed.\n"); - mdev->iommu = NULL; - goto disable_clk; - } - } - clk_disable_unprepare(mdev->aclk); err = sysfs_create_group(&dev->kobj, &komeda_sysfs_attr_group); @@ -310,11 +306,6 @@ void komeda_dev_destroy(struct komeda_dev *mdev) if (mdev->aclk) clk_prepare_enable(mdev->aclk); - if (mdev->iommu && mdev->funcs->disconnect_iommu) - if (mdev->funcs->disconnect_iommu(mdev)) - DRM_ERROR("disconnect iommu failed.\n"); - mdev->iommu = NULL; - for (i = 0; i < mdev->n_pipelines; i++) { komeda_pipeline_destroy(mdev, mdev->pipelines[i]); mdev->pipelines[i] = NULL; @@ -343,44 +334,26 @@ void komeda_dev_destroy(struct komeda_dev *mdev) int komeda_dev_resume(struct komeda_dev *mdev) { - int ret = 0; - clk_prepare_enable(mdev->aclk); - if (mdev->iommu && mdev->funcs->connect_iommu) { - ret = mdev->funcs->connect_iommu(mdev); - if (ret < 0) { + mdev->funcs->enable_irq(mdev); + + if (mdev->iommu && mdev->funcs->connect_iommu) + if (mdev->funcs->connect_iommu(mdev)) DRM_ERROR("connect iommu failed.\n"); - goto disable_clk; - } - } - ret = mdev->funcs->enable_irq(mdev); - -disable_clk: - clk_disable_unprepare(mdev->aclk); - - return ret; + return 0; } int komeda_dev_suspend(struct komeda_dev *mdev) { - int ret = 0; - - clk_prepare_enable(mdev->aclk); - - if (mdev->iommu && mdev->funcs->disconnect_iommu) { - ret = mdev->funcs->disconnect_iommu(mdev); - if (ret < 0) { + if (mdev->iommu && mdev->funcs->disconnect_iommu) + if (mdev->funcs->disconnect_iommu(mdev)) DRM_ERROR("disconnect iommu failed.\n"); - goto disable_clk; - } - } - ret = mdev->funcs->disable_irq(mdev); + mdev->funcs->disable_irq(mdev); -disable_clk: clk_disable_unprepare(mdev->aclk); - return ret; + return 0; } diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index ad38bbc7431e..ea5cd1e17304 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -33,6 +33,12 @@ static void komeda_unbind(struct device *dev) return; komeda_kms_detach(mdrv->kms); + + if (pm_runtime_enabled(dev)) + pm_runtime_disable(dev); + else + komeda_dev_suspend(mdrv->mdev); + komeda_dev_destroy(mdrv->mdev); dev_set_drvdata(dev, NULL); @@ -54,6 +60,10 @@ static int komeda_bind(struct device *dev) goto free_mdrv; } + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) + komeda_dev_resume(mdrv->mdev); + mdrv->kms = komeda_kms_attach(mdrv->mdev); if (IS_ERR(mdrv->kms)) { err = PTR_ERR(mdrv->kms); @@ -65,6 +75,11 @@ static int komeda_bind(struct device *dev) return 0; destroy_mdev: + if (pm_runtime_enabled(dev)) + pm_runtime_disable(dev); + else + komeda_dev_suspend(mdrv->mdev); + komeda_dev_destroy(mdrv->mdev); free_mdrv: @@ -131,15 +146,29 @@ static const struct of_device_id komeda_of_match[] = { MODULE_DEVICE_TABLE(of, komeda_of_match); +static int komeda_rt_pm_suspend(struct device *dev) +{ + struct komeda_drv *mdrv = dev_get_drvdata(dev); + + return komeda_dev_suspend(mdrv->mdev); +} + +static int komeda_rt_pm_resume(struct device *dev) +{ + struct komeda_drv *mdrv = dev_get_drvdata(dev); + + return komeda_dev_resume(mdrv->mdev); +} + static int __maybe_unused komeda_pm_suspend(struct device *dev) { struct komeda_drv *mdrv = dev_get_drvdata(dev); - struct drm_device *drm = &mdrv->kms->base; int res; - res = drm_mode_config_helper_suspend(drm); + res = drm_mode_config_helper_suspend(&mdrv->kms->base); - komeda_dev_suspend(mdrv->mdev); + if (!pm_runtime_status_suspended(dev)) + komeda_dev_suspend(mdrv->mdev); return res; } @@ -147,15 +176,16 @@ static int __maybe_unused komeda_pm_suspend(struct device *dev) static int __maybe_unused komeda_pm_resume(struct device *dev) { struct komeda_drv *mdrv = dev_get_drvdata(dev); - struct drm_device *drm = &mdrv->kms->base; - komeda_dev_resume(mdrv->mdev); + if (!pm_runtime_status_suspended(dev)) + komeda_dev_resume(mdrv->mdev); - return drm_mode_config_helper_resume(drm); + return drm_mode_config_helper_resume(&mdrv->kms->base); } static const struct dev_pm_ops komeda_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(komeda_pm_suspend, komeda_pm_resume) + SET_RUNTIME_PM_OPS(komeda_rt_pm_suspend, komeda_rt_pm_resume, NULL) }; static struct platform_driver komeda_platform_driver = { diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index e30a5b43caa9..9a7dcf92591a 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -307,10 +307,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) if (err) goto free_component_binding; - err = mdev->funcs->enable_irq(mdev); - if (err) - goto free_component_binding; - drm->irq_enabled = true; drm_kms_helper_poll_init(drm); @@ -324,7 +320,6 @@ struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev) free_interrupts: drm_kms_helper_poll_fini(drm); drm->irq_enabled = false; - mdev->funcs->disable_irq(mdev); free_component_binding: component_unbind_all(mdev->dev, drm); cleanup_mode_config: @@ -346,7 +341,6 @@ void komeda_kms_detach(struct komeda_kms_dev *kms) drm_kms_helper_poll_fini(drm); drm_atomic_helper_shutdown(drm); drm->irq_enabled = false; - mdev->funcs->disable_irq(mdev); component_unbind_all(mdev->dev, drm); drm_mode_config_cleanup(drm); komeda_kms_cleanup_private_objs(kms); From 1ce0d5162b98bf6120db1b259d0f0706e69f15fd Mon Sep 17 00:00:00 2001 From: Wambui Karuga Date: Mon, 30 Dec 2019 22:56:09 +0300 Subject: [PATCH 73/73] drm/panel: declare variable as __be16 Declare the temp variable as __be16 to address the following sparse warning: drivers/gpu/drm/panel/panel-lg-lg4573.c:45:20: warning: incorrect type in initializer (different base types) drivers/gpu/drm/panel/panel-lg-lg4573.c:45:20: expected unsigned short [unsigned] [usertype] temp drivers/gpu/drm/panel/panel-lg-lg4573.c:45:20: got restricted __be16 [usertype] Signed-off-by: Wambui Karuga Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191230195609.12386-1-wambui.karugax@gmail.com --- drivers/gpu/drm/panel/panel-lg-lg4573.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c index 20235ff0bbc4..b262b53dbd85 100644 --- a/drivers/gpu/drm/panel/panel-lg-lg4573.c +++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c @@ -42,7 +42,7 @@ static int lg4573_spi_write_u16(struct lg4573 *ctx, u16 data) struct spi_transfer xfer = { .len = 2, }; - u16 temp = cpu_to_be16(data); + __be16 temp = cpu_to_be16(data); struct spi_message msg; dev_dbg(ctx->panel.dev, "writing data: %x\n", data);