All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/13] R-Car DU: Use drm bridge API
@ 2016-11-29  9:04 ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

Hello,

This patch series replaces the custom external encoders support implementation
in the R-Car DU driver with code based on the DRM bridge API.

While the overall diffstat isn't impressive, the rcar-du-drm driver gets
notably thinner in the process:

        9 files changed, 64 insertions(+), 384 deletions(-)

This is offset by a reusable driver for LVDS encoders along with the
corresponding DT bindings (+ 218 lines).

The series starts with a few cleanups. Patch 01/13 fixes all drivers to
include <drm/drm_encoder.h> where needed, allowing to remove inclusion of the
header from <drm/drm_crtc.h> (there are plenty of other headers that need
similar cleanup, volunteers are welcome). Patch 02/13 then includes
<drm/drm_crtc.h> in <drm/drm_encoder.h> to fix a compilation warning.

The next patche moves copied&pasted code from a large number of drivers to the
DRM bridge core drm_bridge_attach() function. The function now links bridges
to encoders or other bridges instead of letting the caller perform that
operation. Patch 04/13 can then detach bridges in the encoder cleanup
function, removing the need to call drm_bridge_detach() explicitly in drivers
(all but one of the drivers that use bridges were missing that call).

Patches 05/13 and 06/13 add DT bindings for LVDS encoders with a corresponding
driver. It supports "dumb" LVDS encoders only, similarly to the dumb-vga-dac
driver. One notable difference, though, is that LVDS encoders can't be purely
passive, and thus require at least one power supply (and usually multiple of
them) and have a few control GPIOs (most notably to control reset, power down,
clock polarity and/or LVDS slew rate). However, on many systems those encoders
are integrated in such a way that the control pins are pulled up or down
appropriately and the power supplies are either always on or shared with other
display components that make them operate as if they were always on. For that
reason a common drivers for those systems is useful, with simple DT bindings
that don't try to cover any device-specific control pin or power supply.

To ensure backward compatibility most LVDS encoders should *not* use the
common simple "lvds-encoder" compatible string, but should instead define a
device-specific compatible string that can then be added to the lvds-encoder
driver (patch 08/13). This way, when the need to control pins or supplies will
arise, a new driver can be developed matching on the device-specific
compatible string, which will then be removed from the simple driver. Existing
systems will migrate transparently without requiring a change to their device
tree.

A similar reasoning applies to VGA DACs, leading to the addition of the
"adi,adv7123" compatible string to the dumb-vga-dac driver's OF match table in
patch 07/13.

Patch 09/13 adds a new type field to the drm_bridge structure to inform bridge
users of the bridge type. This is useful for display driver to create a DRM
encoder of the appropriate type without having to resort to heuristics.
Patches 10/13 and 11/13 update all bridge drivers to initialize the new field
to the appropriate value.

Patches 12/13 and 13/13 finally migrate the rcar-du-drm driver to the DRM
bridge API, removing the custom VGA DAC implementation in patch 12/13 and the
table of bridge compatible strings used to find the encoder type in patch
13/13.

Changes since v2:

- Added patches 01/13 to 04/13.
- Rebased on top of latest DRM master branch

Changes since v1:

- The patches have been rebased on top of the "[PATCH v2 00/13] R-Car DU: Add
  support for LVDS mode selection" series.
- The LVDS encoder DT bindings have been split from the LVDS encoder driver
  into a separate patch.
- The wording of the DRM bridge documentation new property has been updated.

Laurent Pinchart (13):
  drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
  drm: Fix compilation warning caused by static inline forward
    declaration
  drm: bridge: Link encoder and bridge in core code
  drm: bridge: Detach bridge from encoder at encoder cleanup time
  drm: bridge: Add LVDS encoder DT bindings
  drm: bridge: Add LVDS encoder driver
  drm: bridge: vga-dac: Add adi,adv7123 compatible string
  drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string
  drm: Add encoder_type field to the drm_bridge structure
  drm: bridge: Set bridges' encoder type
  drm: Set on-chip bridges' encoder type
  drm: rcar-du: Replace manual bridge implementation with DRM bridge
  drm: rcar-du: Initialize encoder's type based on the bridge's type

 .../bindings/display/bridge/lvds-transmitter.txt   |  64 ++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   1 +
 drivers/gpu/drm/ast/ast_drv.h                      |   1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |   4 +-
 drivers/gpu/drm/bochs/bochs.h                      |   1 +
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       |   1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c          |   1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |   5 +-
 drivers/gpu/drm/bridge/dumb-vga-dac.c              |   2 +
 drivers/gpu/drm/bridge/dw-hdmi.c                   |   5 +-
 drivers/gpu/drm/bridge/lvds-encoder.c              | 218 +++++++++++++++++++++
 drivers/gpu/drm/bridge/nxp-ptn3460.c               |   2 +
 drivers/gpu/drm/bridge/parade-ps8622.c             |   2 +
 drivers/gpu/drm/bridge/sii902x.c                   |   2 +
 drivers/gpu/drm/bridge/tc358767.c                  |   2 +
 drivers/gpu/drm/cirrus/cirrus_drv.h                |   1 +
 drivers/gpu/drm/drm_bridge.c                       |  46 +++--
 drivers/gpu/drm/drm_connector.c                    |   1 +
 drivers/gpu/drm/drm_crtc_helper.c                  |   1 +
 drivers/gpu/drm/drm_edid.c                         |   1 +
 drivers/gpu/drm/drm_encoder.c                      |   3 +
 drivers/gpu/drm/drm_mode_config.c                  |   1 +
 drivers/gpu/drm/drm_of.c                           |   1 +
 drivers/gpu/drm/drm_plane_helper.c                 |   1 +
 drivers/gpu/drm/drm_simple_kms_helper.c            |   4 +-
 drivers/gpu/drm/exynos/exynos_dp.c                 |   5 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c            |   6 +-
 drivers/gpu/drm/exynos/exynos_drm_mic.c            |   2 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h          |   2 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |   5 +-
 drivers/gpu/drm/gma500/psb_intel_drv.h             |   1 +
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |   5 +-
 drivers/gpu/drm/i915/intel_drv.h                   |   1 +
 drivers/gpu/drm/imx/imx-ldb.c                      |   6 +-
 drivers/gpu/drm/imx/parallel-display.c             |   4 +-
 drivers/gpu/drm/mediatek/mtk_dpi.c                 |   8 +-
 drivers/gpu/drm/mediatek/mtk_dsi.c                 |  24 +--
 drivers/gpu/drm/mediatek/mtk_hdmi.c                |  13 +-
 drivers/gpu/drm/mgag200/mgag200_drv.h              |   1 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c              |  17 +-
 drivers/gpu/drm/msm/edp/edp_bridge.c               |   2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |   2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h        |   1 +
 drivers/gpu/drm/qxl/qxl_drv.h                      |   1 +
 drivers/gpu/drm/radeon/radeon_mode.h               |   1 +
 drivers/gpu/drm/rcar-du/Kconfig                    |   6 -
 drivers/gpu/drm/rcar-du/Makefile                   |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c          | 119 +++++------
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h          |   4 +-
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          | 137 -------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h          |  35 ----
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  37 +---
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c           |  82 --------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h           |  23 ---
 drivers/gpu/drm/shmobile/shmob_drm_crtc.h          |   1 +
 drivers/gpu/drm/sti/sti_dvo.c                      |   5 +-
 drivers/gpu/drm/sti/sti_hda.c                      |   3 +-
 drivers/gpu/drm/sti/sti_hdmi.c                     |   3 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                  |  13 +-
 drivers/gpu/drm/tegra/drm.h                        |   1 +
 drivers/gpu/drm/vc4/vc4_drv.h                      |   2 +
 drivers/gpu/drm/virtio/virtgpu_drv.h               |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h                |   1 +
 include/drm/drm_bridge.h                           |  11 +-
 include/drm/drm_crtc.h                             |   3 -
 include/drm/drm_encoder.h                          |   7 +-
 include/drm/drm_encoder_slave.h                    |   1 +
 include/drm/drm_modeset_helper_vtables.h           |   1 +
 70 files changed, 499 insertions(+), 489 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* [PATCH v3 00/13] R-Car DU: Use drm bridge API
@ 2016-11-29  9:04 ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Hello,

This patch series replaces the custom external encoders support implementation
in the R-Car DU driver with code based on the DRM bridge API.

While the overall diffstat isn't impressive, the rcar-du-drm driver gets
notably thinner in the process:

        9 files changed, 64 insertions(+), 384 deletions(-)

This is offset by a reusable driver for LVDS encoders along with the
corresponding DT bindings (+ 218 lines).

The series starts with a few cleanups. Patch 01/13 fixes all drivers to
include <drm/drm_encoder.h> where needed, allowing to remove inclusion of the
header from <drm/drm_crtc.h> (there are plenty of other headers that need
similar cleanup, volunteers are welcome). Patch 02/13 then includes
<drm/drm_crtc.h> in <drm/drm_encoder.h> to fix a compilation warning.

The next patche moves copied&pasted code from a large number of drivers to the
DRM bridge core drm_bridge_attach() function. The function now links bridges
to encoders or other bridges instead of letting the caller perform that
operation. Patch 04/13 can then detach bridges in the encoder cleanup
function, removing the need to call drm_bridge_detach() explicitly in drivers
(all but one of the drivers that use bridges were missing that call).

Patches 05/13 and 06/13 add DT bindings for LVDS encoders with a corresponding
driver. It supports "dumb" LVDS encoders only, similarly to the dumb-vga-dac
driver. One notable difference, though, is that LVDS encoders can't be purely
passive, and thus require at least one power supply (and usually multiple of
them) and have a few control GPIOs (most notably to control reset, power down,
clock polarity and/or LVDS slew rate). However, on many systems those encoders
are integrated in such a way that the control pins are pulled up or down
appropriately and the power supplies are either always on or shared with other
display components that make them operate as if they were always on. For that
reason a common drivers for those systems is useful, with simple DT bindings
that don't try to cover any device-specific control pin or power supply.

To ensure backward compatibility most LVDS encoders should *not* use the
common simple "lvds-encoder" compatible string, but should instead define a
device-specific compatible string that can then be added to the lvds-encoder
driver (patch 08/13). This way, when the need to control pins or supplies will
arise, a new driver can be developed matching on the device-specific
compatible string, which will then be removed from the simple driver. Existing
systems will migrate transparently without requiring a change to their device
tree.

A similar reasoning applies to VGA DACs, leading to the addition of the
"adi,adv7123" compatible string to the dumb-vga-dac driver's OF match table in
patch 07/13.

Patch 09/13 adds a new type field to the drm_bridge structure to inform bridge
users of the bridge type. This is useful for display driver to create a DRM
encoder of the appropriate type without having to resort to heuristics.
Patches 10/13 and 11/13 update all bridge drivers to initialize the new field
to the appropriate value.

Patches 12/13 and 13/13 finally migrate the rcar-du-drm driver to the DRM
bridge API, removing the custom VGA DAC implementation in patch 12/13 and the
table of bridge compatible strings used to find the encoder type in patch
13/13.

Changes since v2:

- Added patches 01/13 to 04/13.
- Rebased on top of latest DRM master branch

Changes since v1:

- The patches have been rebased on top of the "[PATCH v2 00/13] R-Car DU: Add
  support for LVDS mode selection" series.
- The LVDS encoder DT bindings have been split from the LVDS encoder driver
  into a separate patch.
- The wording of the DRM bridge documentation new property has been updated.

Laurent Pinchart (13):
  drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
  drm: Fix compilation warning caused by static inline forward
    declaration
  drm: bridge: Link encoder and bridge in core code
  drm: bridge: Detach bridge from encoder at encoder cleanup time
  drm: bridge: Add LVDS encoder DT bindings
  drm: bridge: Add LVDS encoder driver
  drm: bridge: vga-dac: Add adi,adv7123 compatible string
  drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string
  drm: Add encoder_type field to the drm_bridge structure
  drm: bridge: Set bridges' encoder type
  drm: Set on-chip bridges' encoder type
  drm: rcar-du: Replace manual bridge implementation with DRM bridge
  drm: rcar-du: Initialize encoder's type based on the bridge's type

 .../bindings/display/bridge/lvds-transmitter.txt   |  64 ++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h           |   1 +
 drivers/gpu/drm/ast/ast_drv.h                      |   1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |   4 +-
 drivers/gpu/drm/bochs/bochs.h                      |   1 +
 drivers/gpu/drm/bridge/Kconfig                     |   8 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       |   1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c          |   1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |   5 +-
 drivers/gpu/drm/bridge/dumb-vga-dac.c              |   2 +
 drivers/gpu/drm/bridge/dw-hdmi.c                   |   5 +-
 drivers/gpu/drm/bridge/lvds-encoder.c              | 218 +++++++++++++++++++++
 drivers/gpu/drm/bridge/nxp-ptn3460.c               |   2 +
 drivers/gpu/drm/bridge/parade-ps8622.c             |   2 +
 drivers/gpu/drm/bridge/sii902x.c                   |   2 +
 drivers/gpu/drm/bridge/tc358767.c                  |   2 +
 drivers/gpu/drm/cirrus/cirrus_drv.h                |   1 +
 drivers/gpu/drm/drm_bridge.c                       |  46 +++--
 drivers/gpu/drm/drm_connector.c                    |   1 +
 drivers/gpu/drm/drm_crtc_helper.c                  |   1 +
 drivers/gpu/drm/drm_edid.c                         |   1 +
 drivers/gpu/drm/drm_encoder.c                      |   3 +
 drivers/gpu/drm/drm_mode_config.c                  |   1 +
 drivers/gpu/drm/drm_of.c                           |   1 +
 drivers/gpu/drm/drm_plane_helper.c                 |   1 +
 drivers/gpu/drm/drm_simple_kms_helper.c            |   4 +-
 drivers/gpu/drm/exynos/exynos_dp.c                 |   5 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c            |   6 +-
 drivers/gpu/drm/exynos/exynos_drm_mic.c            |   2 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h          |   2 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |   5 +-
 drivers/gpu/drm/gma500/psb_intel_drv.h             |   1 +
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |   5 +-
 drivers/gpu/drm/i915/intel_drv.h                   |   1 +
 drivers/gpu/drm/imx/imx-ldb.c                      |   6 +-
 drivers/gpu/drm/imx/parallel-display.c             |   4 +-
 drivers/gpu/drm/mediatek/mtk_dpi.c                 |   8 +-
 drivers/gpu/drm/mediatek/mtk_dsi.c                 |  24 +--
 drivers/gpu/drm/mediatek/mtk_hdmi.c                |  13 +-
 drivers/gpu/drm/mgag200/mgag200_drv.h              |   1 +
 drivers/gpu/drm/msm/dsi/dsi_manager.c              |  17 +-
 drivers/gpu/drm/msm/edp/edp_bridge.c               |   2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |   2 +-
 drivers/gpu/drm/nouveau/nouveau_connector.h        |   1 +
 drivers/gpu/drm/qxl/qxl_drv.h                      |   1 +
 drivers/gpu/drm/radeon/radeon_mode.h               |   1 +
 drivers/gpu/drm/rcar-du/Kconfig                    |   6 -
 drivers/gpu/drm/rcar-du/Makefile                   |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c          | 119 +++++------
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h          |   4 +-
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          | 137 -------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h          |  35 ----
 drivers/gpu/drm/rcar-du/rcar_du_kms.c              |  37 +---
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c           |  82 --------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h           |  23 ---
 drivers/gpu/drm/shmobile/shmob_drm_crtc.h          |   1 +
 drivers/gpu/drm/sti/sti_dvo.c                      |   5 +-
 drivers/gpu/drm/sti/sti_hda.c                      |   3 +-
 drivers/gpu/drm/sti/sti_hdmi.c                     |   3 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                  |  13 +-
 drivers/gpu/drm/tegra/drm.h                        |   1 +
 drivers/gpu/drm/vc4/vc4_drv.h                      |   2 +
 drivers/gpu/drm/virtio/virtgpu_drv.h               |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h                |   1 +
 include/drm/drm_bridge.h                           |  11 +-
 include/drm/drm_crtc.h                             |   3 -
 include/drm/drm_encoder.h                          |   7 +-
 include/drm/drm_encoder_slave.h                    |   1 +
 include/drm/drm_modeset_helper_vtables.h           |   1 +
 70 files changed, 499 insertions(+), 489 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
  2016-11-29  9:04 ` Laurent Pinchart
  (?)
@ 2016-11-29  9:04 ` Laurent Pinchart
  2016-11-29  9:30     ` Daniel Vetter
  2016-12-02 21:21     ` Sinclair Yeh
  -1 siblings, 2 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Alex Deucher,
	Christian König, Stefan Agner, Alison Wang,
	Patrik Jakobsson, Daniel Vetter, Jani Nikula, Ben Skeggs,
	Thierry Reding, Eric Anholt, Sinclair Yeh, Thomas Hellstrom

<drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
now been split into separate files for each object type, but still
includes most other KMS headers to avoid breaking driver compilation.

As a step towards fixing that problem, remove the inclusion of
<drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
appropriate. Also remove the forward declarations of the drm_encoder and
drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
needed in the header.

<drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
forward declaration of struct drm_encoder in order to allow including it
as the first header in a compilation unit.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
 drivers/gpu/drm/ast/ast_drv.h               | 1 +
 drivers/gpu/drm/bochs/bochs.h               | 1 +
 drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
 drivers/gpu/drm/drm_connector.c             | 1 +
 drivers/gpu/drm/drm_crtc_helper.c           | 1 +
 drivers/gpu/drm/drm_edid.c                  | 1 +
 drivers/gpu/drm/drm_mode_config.c           | 1 +
 drivers/gpu/drm/drm_of.c                    | 1 +
 drivers/gpu/drm/drm_plane_helper.c          | 1 +
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
 drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
 drivers/gpu/drm/i915/intel_drv.h            | 1 +
 drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
 drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
 drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
 drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
 drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
 drivers/gpu/drm/tegra/drm.h                 | 1 +
 drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
 drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
 include/drm/drm_crtc.h                      | 3 ---
 include/drm/drm_encoder.h                   | 3 +++
 include/drm/drm_encoder_slave.h             | 1 +
 include/drm/drm_modeset_helper_vtables.h    | 1 +
 27 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 1e23334b07fb..fac06064a8f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -32,6 +32,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_fixed.h>
 #include <drm/drm_crtc_helper.h>
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 908011d2c8f5..6f3b6f50cf52 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -28,6 +28,7 @@
 #ifndef __AST_DRV_H__
 #define __AST_DRV_H__
 
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 
 #include <drm/ttm/ttm_bo_api.h>
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index 32dfe418cc98..f626bab7f5e3 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -4,6 +4,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 
 #include <drm/drm_gem.h>
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 2188d6b61b3e..b59aeef4635a 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -13,6 +13,7 @@
 
 #include <video/vga.h>
 
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 
 #include <drm/ttm/ttm_bo_api.h>
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b5c6a8ee831e..5f1e1f190d30 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -23,6 +23,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5d2cb138eba6..b3fc23313cc3 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -36,6 +36,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7eec18925b70..a9e3cc3990c1 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -35,6 +35,7 @@
 #include <linux/vga_switcheroo.h>
 #include <drm/drmP.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_displayid.h>
 
 #define version_greater(edid, maj, min) \
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 2735a5847ffa..09b1d8f267a6 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -20,6 +20,7 @@
  * OF THIS SOFTWARE.
  */
 
+#include <drm/drm_encoder.h>
 #include <drm/drm_mode_config.h>
 #include <drm/drmP.h>
 
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 47848ed8ca48..b5f2f0fece99 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -4,6 +4,7 @@
 #include <linux/of_graph.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_of.h>
 
 static void drm_release_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 7a7dddf604d7..191a5f095cf9 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -29,6 +29,7 @@
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_atomic_helper.h>
 
 #define SUBPIXEL_MASK 0xffff
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
index 3b371fe7491e..4c22edd4c746 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
@@ -12,6 +12,8 @@
 #ifndef __FSL_DCU_DRM_DRV_H__
 #define __FSL_DCU_DRM_DRV_H__
 
+#include <drm/drm_encoder.h>
+
 #include "fsl_dcu_drm_crtc.h"
 #include "fsl_dcu_drm_output.h"
 #include "fsl_dcu_drm_plane.h"
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
index 2a3b7c684db2..6a10215fc42d 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -23,6 +23,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
 #include <linux/gpio.h>
 #include "gma_display.h"
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 398195bf6dd1..7fb8ac824b01 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -32,6 +32,7 @@
 #include "i915_drv.h"
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_dp_dual_mode_helper.h>
 #include <drm/drm_dp_mst_helper.h>
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 3e02ac20777c..87e0934773de 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -15,6 +15,7 @@
 
 #include <video/vga.h>
 
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 096983c42a1f..a4d1a059bd3d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -30,6 +30,7 @@
 #include <nvif/notify.h>
 
 #include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
 #include "nouveau_crtc.h"
 
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 84995ebc6ffc..56df6b4ddbab 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -43,6 +43,7 @@
 #include <ttm/ttm_placement.h>
 #include <ttm/ttm_module.h>
 
+#include <drm/drm_encoder.h>
 #include <drm/drm_gem.h>
 
 /* just for ttm_validate_buffer */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index bb75201a24ba..7ceea8ffd0db 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -32,6 +32,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_fixed.h>
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 269fbab15907..b79b2f075a74 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -15,6 +15,7 @@
 #define __RCAR_DU_ENCODER_H__
 
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 
 struct drm_panel;
 struct rcar_du_device;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
index 38ed4ff8aaf2..818b31549ddc 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
@@ -16,6 +16,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 
 struct backlight_device;
 struct shmob_drm_device;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 0ddcce1b420d..5205790dd679 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -17,6 +17,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fixed.h>
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index fef172804345..f89a95cb98cf 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -9,6 +9,8 @@
 #include "drmP.h"
 #include "drm_gem_cma_helper.h"
 
+#include <drm/drm_encoder.h>
+
 struct vc4_dev {
 	struct drm_device *dev;
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index ec1ebdcfe80b..475ac93848c3 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -35,6 +35,7 @@
 #include <drm/drm_gem.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
 #include <ttm/ttm_bo_api.h>
 #include <ttm/ttm_bo_driver.h>
 #include <ttm/ttm_placement.h>
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index ff4803c107bc..5ee25fb07ea2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -30,6 +30,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
 #include "vmwgfx_drv.h"
 
 /**
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 946672f97e1e..9ef0ac0ce69f 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -39,7 +39,6 @@
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_modes.h>
 #include <drm/drm_connector.h>
-#include <drm/drm_encoder.h>
 #include <drm/drm_property.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_edid.h>
@@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
 }
 
 struct drm_crtc;
-struct drm_encoder;
 struct drm_pending_vblank_event;
 struct drm_plane;
 struct drm_bridge;
 struct drm_atomic_state;
 
 struct drm_crtc_helper_funcs;
-struct drm_encoder_helper_funcs;
 struct drm_plane_helper_funcs;
 
 /**
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index c7438ff0d609..cec6ac45c6cc 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -25,8 +25,11 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <drm/drm_mode.h>
 #include <drm/drm_mode_object.h>
 
+struct drm_encoder;
+
 /**
  * struct drm_encoder_funcs - encoder controls
  *
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
index 82cdf611393d..1107b4b1c599 100644
--- a/include/drm/drm_encoder_slave.h
+++ b/include/drm/drm_encoder_slave.h
@@ -29,6 +29,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 
 /**
  * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 72478cf82147..21d9823d4872 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -30,6 +30,7 @@
 #define __DRM_MODESET_HELPER_VTABLES_H__
 
 #include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
 
 /**
  * DOC: overview
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 02/13] drm: Fix compilation warning caused by static inline forward declaration
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

The drm_crtc_mask() function used in <drm/drm_encoder.h> is a static
inline defined in <drm/drm_crtc.h>. If the first header is included in a
compilation unit without the second one, the following compilation
warning will be issued.

In file included from <linux>/drivers/gpu/drm/drm_bridge.c:29:0:
<linux>/include/drm/drm_encoder.h:192:95: warning: ‘drm_crtc_mask’ used but never defined
 static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);

Fix this by including the header defining the function instead of using
a forward declaration.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 include/drm/drm_encoder.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index cec6ac45c6cc..5f58f65344e0 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_mode_object.h>
 
@@ -191,9 +192,6 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
 	return encoder->index;
 }
 
-/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
-static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
-
 /**
  * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
  * @encoder: encoder to test
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 02/13] drm: Fix compilation warning caused by static inline forward declaration
@ 2016-11-29  9:04   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The drm_crtc_mask() function used in <drm/drm_encoder.h> is a static
inline defined in <drm/drm_crtc.h>. If the first header is included in a
compilation unit without the second one, the following compilation
warning will be issued.

In file included from <linux>/drivers/gpu/drm/drm_bridge.c:29:0:
<linux>/include/drm/drm_encoder.h:192:95: warning: ‘drm_crtc_mask’ used but never defined
 static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);

Fix this by including the header defining the function instead of using
a forward declaration.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 include/drm/drm_encoder.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index cec6ac45c6cc..5f58f65344e0 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -25,6 +25,7 @@
 
 #include <linux/list.h>
 #include <linux/ctype.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_mode_object.h>
 
@@ -191,9 +192,6 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
 	return encoder->index;
 }
 
-/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
-static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
-
 /**
  * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
  * @encoder: encoder to test
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Boris Brezillon, Jingoo Han,
	Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Stefan Agner, Alison Wang, Xinliang Liu, Rongrong Zou,
	Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu, Rob Clark,
	Benjamin Gaignard, Vincent Abriou, Maxime Ripard

Instead of linking encoders and bridges in every driver (and getting it
wrong half of the time, as many drivers forget to set the drm_bridge
encoder pointer), do so in core code. The drm_bridge_attach() function
needs the encoder and optional previous bridge to perform that task,
update all the callers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
 drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
 drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
 drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
 drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
 drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
 drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
 drivers/gpu/drm/imx/parallel-display.c             |  4 +-
 drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
 drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
 drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
 drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
 drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
 drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
 drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
 drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
 include/drm/drm_bridge.h                           |  3 +-
 23 files changed, 83 insertions(+), 103 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 6119b5085501..e7799b6ee829 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 	of_node_put(np);
 
 	if (bridge) {
-		output->encoder.bridge = bridge;
-		bridge->encoder = &output->encoder;
-		ret = drm_bridge_attach(dev, bridge);
+		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
 		if (!ret)
 			return 0;
 	}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 6e0447f329a2..1835f1fdad19 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
 
 	dp->bridge = bridge;
 
-	dp->encoder->bridge = bridge;
 	bridge->driver_private = dp;
-	bridge->encoder = dp->encoder;
 	bridge->funcs = &analogix_dp_bridge_funcs;
 
-	ret = drm_bridge_attach(drm_dev, bridge);
+	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("failed to attach drm bridge\n");
 		return -EINVAL;
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index b71088dab268..432e0e3fff72 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
 	hdmi->bridge = bridge;
 	bridge->driver_private = hdmi;
 	bridge->funcs = &dw_hdmi_bridge_funcs;
-	ret = drm_bridge_attach(drm, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize bridge with drm\n");
 		return -EINVAL;
 	}
 
-	encoder->bridge = bridge;
 	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
 	drm_connector_helper_add(&hdmi->connector,
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 0ee052b7c21a..850bd6509ef1 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 
 #include <drm/drm_bridge.h>
+#include <drm/drm_encoder.h>
 
 /**
  * DOC: overview
@@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
 EXPORT_SYMBOL(drm_bridge_remove);
 
 /**
- * drm_bridge_attach - associate given bridge to our DRM device
+ * drm_bridge_attach - attach the bridge to an encoder's chain
  *
- * @dev: DRM device
- * @bridge: bridge control structure
+ * @encoder: DRM encoder
+ * @bridge: bridge to attach
+ * @previous: previous bridge in the chain (optional)
  *
- * Called by a kms driver to link one of our encoder/bridge to the given
- * bridge.
+ * Called by a kms driver to link the bridge to an encoder's chain. The previous
+ * argument specifies the previous bridge in the chain. If NULL, the bridge is
+ * linked directly at the encoder's output. Otherwise it is linked at the
+ * previous bridge's output.
  *
- * Note that setting up links between the bridge and our encoder/bridge
- * objects needs to be handled by the kms driver itself.
+ * If non-NULL the previous bridge must be already attached by a call to this
+ * function.
  *
  * RETURNS:
  * Zero on success, error code on failure
  */
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
+		      struct drm_bridge *previous)
 {
-	if (!dev || !bridge)
+	int ret;
+
+	if (!encoder || !bridge)
+		return -EINVAL;
+
+	if (previous && (!previous->dev || previous->encoder != encoder))
 		return -EINVAL;
 
 	if (bridge->dev)
 		return -EBUSY;
 
-	bridge->dev = dev;
+	bridge->dev = encoder->dev;
+	bridge->encoder = encoder;
+
+	if (bridge->funcs->attach) {
+		ret = bridge->funcs->attach(bridge);
+		if (ret < 0) {
+			bridge->dev = NULL;
+			bridge->encoder = NULL;
+			return ret;
+		}
+	}
 
-	if (bridge->funcs->attach)
-		return bridge->funcs->attach(bridge);
+	if (previous)
+		previous->next = bridge;
+	else
+		encoder->bridge = bridge;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 7bae08c2bf0a..ba7be6169339 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
 int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
 					  struct drm_bridge *bridge)
 {
-	bridge->encoder = &pipe->encoder;
-	pipe->encoder.bridge = bridge;
-	return drm_bridge_attach(pipe->encoder.dev, bridge);
+	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
 }
 EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
 
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 528229faffe4..1ef0be338b85 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
 				   struct drm_connector *connector)
 {
 	struct exynos_dp_device *dp = to_dp(plat_data);
-	struct drm_encoder *encoder = &dp->encoder;
 	int ret;
 
 	drm_connector_register(connector);
@@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
 
 	/* Pre-empt DP connector creation if there's a bridge */
 	if (dp->ptn_bridge) {
-		bridge->next = dp->ptn_bridge;
-		dp->ptn_bridge->encoder = encoder;
-		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
+		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
 		if (ret) {
 			DRM_ERROR("Failed to attach bridge to drm\n");
 			bridge->next = NULL;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index e07cb1fe4860..812e2ec0761d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	}
 
 	bridge = of_drm_find_bridge(dsi->bridge_node);
-	if (bridge) {
-		encoder->bridge = bridge;
-		drm_bridge_attach(drm_dev, bridge);
-	}
+	if (bridge)
+		drm_bridge_attach(encoder, bridge, NULL);
 
 	return mipi_dsi_host_register(&dsi->dsi_host);
 }
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index e1dd75b18118..3ad76423c60d 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
 	if (!bridge)
 		return -ENODEV;
 
-	fsl_dev->encoder.bridge = bridge;
-	bridge->encoder = &fsl_dev->encoder;
-
-	return drm_bridge_attach(fsl_dev->drm, bridge);
+	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
 }
 
 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 998452ad0fcb..1737e98bc10a 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
 	int ret;
 
 	/* associate the bridge to dsi encoder */
-	encoder->bridge = bridge;
-	bridge->encoder = encoder;
-
-	ret = drm_bridge_attach(dev, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("failed to attach external bridge\n");
 		return ret;
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index b300998dce7d..2fcb579f5489 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
 			 DRM_MODE_ENCODER_LVDS, NULL);
 
 	if (imx_ldb_ch->bridge) {
-		imx_ldb_ch->bridge->encoder = encoder;
-
-		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
-		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
+		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
+					imx_ldb_ch->bridge, NULL);
 		if (ret) {
 			DRM_ERROR("Failed to initialize bridge with drm\n");
 			return ret;
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index d796ada2a47a..2d80c769f56b 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
 		drm_panel_attach(imxpd->panel, &imxpd->connector);
 
 	if (imxpd->bridge) {
-		imxpd->bridge->encoder = encoder;
-		encoder->bridge = imxpd->bridge;
-		ret = drm_bridge_attach(drm, imxpd->bridge);
+		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
 		if (ret < 0) {
 			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
 				ret);
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 0186e500d2a5..3cced1c522fd 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
 struct mtk_dpi {
 	struct mtk_ddp_comp ddp_comp;
 	struct drm_encoder encoder;
+	struct drm_bridge *bridge;
 	void __iomem *regs;
 	struct device *dev;
 	struct clk *engine_clk;
@@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
 	/* Currently DPI0 is fixed to be driven by OVL1 */
 	dpi->encoder.possible_crtcs = BIT(1);
 
-	dpi->encoder.bridge->encoder = &dpi->encoder;
-	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
+	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
 	if (ret) {
 		dev_err(dev, "Failed to attach bridge: %d\n", ret);
 		goto err_cleanup;
@@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 
 	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
 
-	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
+	dpi->bridge = of_drm_find_bridge(bridge_node);
 	of_node_put(bridge_node);
-	if (!dpi->encoder.bridge)
+	if (!dpi->bridge)
 		return -EPROBE_DEFER;
 
 	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 28b2044ed9f2..2ac0f1abba86 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
 	.get_modes = mtk_dsi_connector_get_modes,
 };
 
-static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
-				 struct drm_encoder *encoder)
-{
-	int ret;
-
-	if (!bridge)
-		return -ENOENT;
-
-	encoder->bridge = bridge;
-	bridge->encoder = encoder;
-	ret = drm_bridge_attach(encoder->dev, bridge);
-	if (ret) {
-		DRM_ERROR("Failed to attach bridge to drm\n");
-		encoder->bridge = NULL;
-		bridge->encoder = NULL;
-	}
-
-	return ret;
-}
-
 static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
 {
 	int ret;
@@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
 	dsi->encoder.possible_crtcs = 1;
 
 	/* If there's a bridge, attach to it and let it create the connector */
-	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
+	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
 	if (ret) {
+		DRM_ERROR("Failed to attach bridge to drm\n");
+
 		/* Otherwise create our own connector and attach to a panel */
 		ret = mtk_dsi_create_connector(drm, dsi);
 		if (ret)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 71227deef21b..5ca1b0fbf937 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -149,6 +149,7 @@ struct hdmi_audio_param {
 
 struct mtk_hdmi {
 	struct drm_bridge bridge;
+	struct drm_bridge *next_bridge;
 	struct drm_connector conn;
 	struct device *dev;
 	struct phy *phy;
@@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
 		return ret;
 	}
 
-	if (bridge->next) {
-		bridge->next->encoder = bridge->encoder;
-		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
+	if (hdmi->next_bridge) {
+		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
+					bridge);
 		if (ret) {
 			dev_err(hdmi->dev,
 				"Failed to attach external bridge: %d\n", ret);
@@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 	of_node_put(ep);
 
 	if (!of_device_is_compatible(remote, "hdmi-connector")) {
-		hdmi->bridge.next = of_drm_find_bridge(remote);
-		if (!hdmi->bridge.next) {
+		hdmi->next_bridge = of_drm_find_bridge(remote);
+		if (!hdmi->next_bridge) {
 			dev_err(dev, "Waiting for external bridge\n");
 			of_node_put(remote);
 			return -EPROBE_DEFER;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index c8d1f19c9a6d..2bd8dad76105 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct drm_bridge *bridge = NULL;
 	struct dsi_bridge *dsi_bridge;
+	struct drm_encoder *encoder;
 	int ret;
 
 	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
@@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 
 	dsi_bridge->id = id;
 
+	/*
+	 * HACK: we may not know the external DSI bridge device's mode
+	 * flags here. We'll get to know them only when the device
+	 * attaches to the dsi host. For now, assume the bridge supports
+	 * DSI video mode
+	 */
+	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
+
 	bridge = &dsi_bridge->base;
 	bridge->funcs = &dsi_mgr_bridge_funcs;
 
-	ret = drm_bridge_attach(msm_dsi->dev, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret)
 		goto fail;
 
@@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
 	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
 
 	/* link the internal dsi bridge to the external bridge */
-	int_bridge->next = ext_bridge;
-	/* set the external bridge's encoder as dsi's encoder */
-	ext_bridge->encoder = encoder;
-
-	drm_bridge_attach(dev, ext_bridge);
+	drm_bridge_attach(encoder, ext_bridge, int_bridge);
 
 	/*
 	 * we need the drm_connector created by the external bridge
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
index 2bc73f82f3f5..931a5c97cccf 100644
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
@@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
 	bridge = &edp_bridge->base;
 	bridge->funcs = &edp_bridge_funcs;
 
-	ret = drm_bridge_attach(edp->dev, bridge);
+	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index bacbd5d8df0e..4e6d1bf27474 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
 	bridge = &hdmi_bridge->base;
 	bridge->funcs = &msm_hdmi_bridge_funcs;
 
-	ret = drm_bridge_attach(hdmi->dev, bridge);
+	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index a1a2c5e7822c..933a2547798e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
 	hdmienc->renc = renc;
 
 	/* Link the bridge to the encoder. */
-	bridge->encoder = encoder;
-	encoder->bridge = bridge;
-
-	ret = drm_bridge_attach(rcdu->ddev, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		drm_encoder_cleanup(encoder);
 		return ret;
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index e8c1ed08a9f7..411dc6ec976e 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 		return err;
 	}
 
-	err = drm_bridge_attach(drm_dev, bridge);
+	err = drm_bridge_attach(encoder, bridge, NULL);
 	if (err) {
 		DRM_ERROR("Failed to attach bridge\n");
 		return err;
 	}
 
 	dvo->bridge = bridge;
-	encoder->bridge = bridge;
 	connector->encoder = encoder;
 	dvo->encoder = encoder;
 
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index e7c243f70870..5b1855e44f87 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
 
 	bridge->driver_private = hda;
 	bridge->funcs = &sti_hda_bridge_funcs;
-	drm_bridge_attach(drm_dev, bridge);
+	drm_bridge_attach(encoder, bridge, NULL);
 
-	encoder->bridge = bridge;
 	connector->encoder = encoder;
 
 	drm_connector = (struct drm_connector *)connector;
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 376b0763c874..f0af1ae82ee9 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	bridge->driver_private = hdmi;
 	bridge->funcs = &sti_hdmi_bridge_funcs;
-	drm_bridge_attach(drm_dev, bridge);
+	drm_bridge_attach(encoder, bridge, NULL);
 
-	encoder->bridge = bridge;
 	connector->encoder = encoder;
 
 	drm_connector = (struct drm_connector *)connector;
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index c3ff10f559cc..ce071c17134b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sun4i_tcon *tcon = drv->tcon;
 	struct drm_encoder *encoder;
+	struct drm_bridge *bridge;
 	struct sun4i_rgb *rgb;
 	int ret;
 
@@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
 	encoder = &rgb->encoder;
 
 	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
-	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
-	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
+	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
+	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
 		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
 		return 0;
 	}
@@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
 		}
 	}
 
-	if (!IS_ERR(encoder->bridge)) {
-		encoder->bridge->encoder = &rgb->encoder;
-
-		ret = drm_bridge_attach(drm, encoder->bridge);
+	if (!IS_ERR(bridge)) {
+		ret = drm_bridge_attach(encoder, bridge, NULL);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
 			goto err_cleanup_connector;
 		}
-	} else {
-		encoder->bridge = NULL;
 	}
 
 	return 0;
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 530a1d6e8cde..94e5ee96b3b5 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -201,7 +201,8 @@ struct drm_bridge {
 int drm_bridge_add(struct drm_bridge *bridge);
 void drm_bridge_remove(struct drm_bridge *bridge);
 struct drm_bridge *of_drm_find_bridge(struct device_node *np);
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
+		      struct drm_bridge *previous);
 void drm_bridge_detach(struct drm_bridge *bridge);
 
 bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29  9:04   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Boris Brezillon, Jingoo Han,
	Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Stefan Agner, Alison Wang, Xinliang Liu, Rongrong Zou,
	Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu, Rob Clark,
	Benjamin Gaignard, Vincent Abriou, Ma

Instead of linking encoders and bridges in every driver (and getting it
wrong half of the time, as many drivers forget to set the drm_bridge
encoder pointer), do so in core code. The drm_bridge_attach() function
needs the encoder and optional previous bridge to perform that task,
update all the callers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
 drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
 drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
 drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
 drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
 drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
 drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
 drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
 drivers/gpu/drm/imx/parallel-display.c             |  4 +-
 drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
 drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
 drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
 drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
 drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
 drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
 drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
 drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
 drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
 include/drm/drm_bridge.h                           |  3 +-
 23 files changed, 83 insertions(+), 103 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index 6119b5085501..e7799b6ee829 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 	of_node_put(np);
 
 	if (bridge) {
-		output->encoder.bridge = bridge;
-		bridge->encoder = &output->encoder;
-		ret = drm_bridge_attach(dev, bridge);
+		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
 		if (!ret)
 			return 0;
 	}
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 6e0447f329a2..1835f1fdad19 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
 
 	dp->bridge = bridge;
 
-	dp->encoder->bridge = bridge;
 	bridge->driver_private = dp;
-	bridge->encoder = dp->encoder;
 	bridge->funcs = &analogix_dp_bridge_funcs;
 
-	ret = drm_bridge_attach(drm_dev, bridge);
+	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("failed to attach drm bridge\n");
 		return -EINVAL;
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index b71088dab268..432e0e3fff72 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
 	hdmi->bridge = bridge;
 	bridge->driver_private = hdmi;
 	bridge->funcs = &dw_hdmi_bridge_funcs;
-	ret = drm_bridge_attach(drm, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize bridge with drm\n");
 		return -EINVAL;
 	}
 
-	encoder->bridge = bridge;
 	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
 	drm_connector_helper_add(&hdmi->connector,
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 0ee052b7c21a..850bd6509ef1 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 
 #include <drm/drm_bridge.h>
+#include <drm/drm_encoder.h>
 
 /**
  * DOC: overview
@@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
 EXPORT_SYMBOL(drm_bridge_remove);
 
 /**
- * drm_bridge_attach - associate given bridge to our DRM device
+ * drm_bridge_attach - attach the bridge to an encoder's chain
  *
- * @dev: DRM device
- * @bridge: bridge control structure
+ * @encoder: DRM encoder
+ * @bridge: bridge to attach
+ * @previous: previous bridge in the chain (optional)
  *
- * Called by a kms driver to link one of our encoder/bridge to the given
- * bridge.
+ * Called by a kms driver to link the bridge to an encoder's chain. The previous
+ * argument specifies the previous bridge in the chain. If NULL, the bridge is
+ * linked directly at the encoder's output. Otherwise it is linked at the
+ * previous bridge's output.
  *
- * Note that setting up links between the bridge and our encoder/bridge
- * objects needs to be handled by the kms driver itself.
+ * If non-NULL the previous bridge must be already attached by a call to this
+ * function.
  *
  * RETURNS:
  * Zero on success, error code on failure
  */
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
+		      struct drm_bridge *previous)
 {
-	if (!dev || !bridge)
+	int ret;
+
+	if (!encoder || !bridge)
+		return -EINVAL;
+
+	if (previous && (!previous->dev || previous->encoder != encoder))
 		return -EINVAL;
 
 	if (bridge->dev)
 		return -EBUSY;
 
-	bridge->dev = dev;
+	bridge->dev = encoder->dev;
+	bridge->encoder = encoder;
+
+	if (bridge->funcs->attach) {
+		ret = bridge->funcs->attach(bridge);
+		if (ret < 0) {
+			bridge->dev = NULL;
+			bridge->encoder = NULL;
+			return ret;
+		}
+	}
 
-	if (bridge->funcs->attach)
-		return bridge->funcs->attach(bridge);
+	if (previous)
+		previous->next = bridge;
+	else
+		encoder->bridge = bridge;
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 7bae08c2bf0a..ba7be6169339 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
 int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
 					  struct drm_bridge *bridge)
 {
-	bridge->encoder = &pipe->encoder;
-	pipe->encoder.bridge = bridge;
-	return drm_bridge_attach(pipe->encoder.dev, bridge);
+	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
 }
 EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
 
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 528229faffe4..1ef0be338b85 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
 				   struct drm_connector *connector)
 {
 	struct exynos_dp_device *dp = to_dp(plat_data);
-	struct drm_encoder *encoder = &dp->encoder;
 	int ret;
 
 	drm_connector_register(connector);
@@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
 
 	/* Pre-empt DP connector creation if there's a bridge */
 	if (dp->ptn_bridge) {
-		bridge->next = dp->ptn_bridge;
-		dp->ptn_bridge->encoder = encoder;
-		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
+		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
 		if (ret) {
 			DRM_ERROR("Failed to attach bridge to drm\n");
 			bridge->next = NULL;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index e07cb1fe4860..812e2ec0761d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
 	}
 
 	bridge = of_drm_find_bridge(dsi->bridge_node);
-	if (bridge) {
-		encoder->bridge = bridge;
-		drm_bridge_attach(drm_dev, bridge);
-	}
+	if (bridge)
+		drm_bridge_attach(encoder, bridge, NULL);
 
 	return mipi_dsi_host_register(&dsi->dsi_host);
 }
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index e1dd75b18118..3ad76423c60d 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
 	if (!bridge)
 		return -ENODEV;
 
-	fsl_dev->encoder.bridge = bridge;
-	bridge->encoder = &fsl_dev->encoder;
-
-	return drm_bridge_attach(fsl_dev->drm, bridge);
+	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
 }
 
 int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 998452ad0fcb..1737e98bc10a 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
 	int ret;
 
 	/* associate the bridge to dsi encoder */
-	encoder->bridge = bridge;
-	bridge->encoder = encoder;
-
-	ret = drm_bridge_attach(dev, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("failed to attach external bridge\n");
 		return ret;
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index b300998dce7d..2fcb579f5489 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
 			 DRM_MODE_ENCODER_LVDS, NULL);
 
 	if (imx_ldb_ch->bridge) {
-		imx_ldb_ch->bridge->encoder = encoder;
-
-		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
-		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
+		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
+					imx_ldb_ch->bridge, NULL);
 		if (ret) {
 			DRM_ERROR("Failed to initialize bridge with drm\n");
 			return ret;
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index d796ada2a47a..2d80c769f56b 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
 		drm_panel_attach(imxpd->panel, &imxpd->connector);
 
 	if (imxpd->bridge) {
-		imxpd->bridge->encoder = encoder;
-		encoder->bridge = imxpd->bridge;
-		ret = drm_bridge_attach(drm, imxpd->bridge);
+		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
 		if (ret < 0) {
 			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
 				ret);
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 0186e500d2a5..3cced1c522fd 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
 struct mtk_dpi {
 	struct mtk_ddp_comp ddp_comp;
 	struct drm_encoder encoder;
+	struct drm_bridge *bridge;
 	void __iomem *regs;
 	struct device *dev;
 	struct clk *engine_clk;
@@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
 	/* Currently DPI0 is fixed to be driven by OVL1 */
 	dpi->encoder.possible_crtcs = BIT(1);
 
-	dpi->encoder.bridge->encoder = &dpi->encoder;
-	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
+	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
 	if (ret) {
 		dev_err(dev, "Failed to attach bridge: %d\n", ret);
 		goto err_cleanup;
@@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 
 	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
 
-	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
+	dpi->bridge = of_drm_find_bridge(bridge_node);
 	of_node_put(bridge_node);
-	if (!dpi->encoder.bridge)
+	if (!dpi->bridge)
 		return -EPROBE_DEFER;
 
 	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 28b2044ed9f2..2ac0f1abba86 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
 	.get_modes = mtk_dsi_connector_get_modes,
 };
 
-static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
-				 struct drm_encoder *encoder)
-{
-	int ret;
-
-	if (!bridge)
-		return -ENOENT;
-
-	encoder->bridge = bridge;
-	bridge->encoder = encoder;
-	ret = drm_bridge_attach(encoder->dev, bridge);
-	if (ret) {
-		DRM_ERROR("Failed to attach bridge to drm\n");
-		encoder->bridge = NULL;
-		bridge->encoder = NULL;
-	}
-
-	return ret;
-}
-
 static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
 {
 	int ret;
@@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
 	dsi->encoder.possible_crtcs = 1;
 
 	/* If there's a bridge, attach to it and let it create the connector */
-	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
+	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
 	if (ret) {
+		DRM_ERROR("Failed to attach bridge to drm\n");
+
 		/* Otherwise create our own connector and attach to a panel */
 		ret = mtk_dsi_create_connector(drm, dsi);
 		if (ret)
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 71227deef21b..5ca1b0fbf937 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -149,6 +149,7 @@ struct hdmi_audio_param {
 
 struct mtk_hdmi {
 	struct drm_bridge bridge;
+	struct drm_bridge *next_bridge;
 	struct drm_connector conn;
 	struct device *dev;
 	struct phy *phy;
@@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
 		return ret;
 	}
 
-	if (bridge->next) {
-		bridge->next->encoder = bridge->encoder;
-		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
+	if (hdmi->next_bridge) {
+		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
+					bridge);
 		if (ret) {
 			dev_err(hdmi->dev,
 				"Failed to attach external bridge: %d\n", ret);
@@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 	of_node_put(ep);
 
 	if (!of_device_is_compatible(remote, "hdmi-connector")) {
-		hdmi->bridge.next = of_drm_find_bridge(remote);
-		if (!hdmi->bridge.next) {
+		hdmi->next_bridge = of_drm_find_bridge(remote);
+		if (!hdmi->next_bridge) {
 			dev_err(dev, "Waiting for external bridge\n");
 			of_node_put(remote);
 			return -EPROBE_DEFER;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index c8d1f19c9a6d..2bd8dad76105 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct drm_bridge *bridge = NULL;
 	struct dsi_bridge *dsi_bridge;
+	struct drm_encoder *encoder;
 	int ret;
 
 	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
@@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
 
 	dsi_bridge->id = id;
 
+	/*
+	 * HACK: we may not know the external DSI bridge device's mode
+	 * flags here. We'll get to know them only when the device
+	 * attaches to the dsi host. For now, assume the bridge supports
+	 * DSI video mode
+	 */
+	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
+
 	bridge = &dsi_bridge->base;
 	bridge->funcs = &dsi_mgr_bridge_funcs;
 
-	ret = drm_bridge_attach(msm_dsi->dev, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret)
 		goto fail;
 
@@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
 	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
 
 	/* link the internal dsi bridge to the external bridge */
-	int_bridge->next = ext_bridge;
-	/* set the external bridge's encoder as dsi's encoder */
-	ext_bridge->encoder = encoder;
-
-	drm_bridge_attach(dev, ext_bridge);
+	drm_bridge_attach(encoder, ext_bridge, int_bridge);
 
 	/*
 	 * we need the drm_connector created by the external bridge
diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
index 2bc73f82f3f5..931a5c97cccf 100644
--- a/drivers/gpu/drm/msm/edp/edp_bridge.c
+++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
@@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
 	bridge = &edp_bridge->base;
 	bridge->funcs = &edp_bridge_funcs;
 
-	ret = drm_bridge_attach(edp->dev, bridge);
+	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index bacbd5d8df0e..4e6d1bf27474 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
 	bridge = &hdmi_bridge->base;
 	bridge->funcs = &msm_hdmi_bridge_funcs;
 
-	ret = drm_bridge_attach(hdmi->dev, bridge);
+	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
 	if (ret)
 		goto fail;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index a1a2c5e7822c..933a2547798e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
 	hdmienc->renc = renc;
 
 	/* Link the bridge to the encoder. */
-	bridge->encoder = encoder;
-	encoder->bridge = bridge;
-
-	ret = drm_bridge_attach(rcdu->ddev, bridge);
+	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		drm_encoder_cleanup(encoder);
 		return ret;
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index e8c1ed08a9f7..411dc6ec976e 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 		return err;
 	}
 
-	err = drm_bridge_attach(drm_dev, bridge);
+	err = drm_bridge_attach(encoder, bridge, NULL);
 	if (err) {
 		DRM_ERROR("Failed to attach bridge\n");
 		return err;
 	}
 
 	dvo->bridge = bridge;
-	encoder->bridge = bridge;
 	connector->encoder = encoder;
 	dvo->encoder = encoder;
 
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index e7c243f70870..5b1855e44f87 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
 
 	bridge->driver_private = hda;
 	bridge->funcs = &sti_hda_bridge_funcs;
-	drm_bridge_attach(drm_dev, bridge);
+	drm_bridge_attach(encoder, bridge, NULL);
 
-	encoder->bridge = bridge;
 	connector->encoder = encoder;
 
 	drm_connector = (struct drm_connector *)connector;
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 376b0763c874..f0af1ae82ee9 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	bridge->driver_private = hdmi;
 	bridge->funcs = &sti_hdmi_bridge_funcs;
-	drm_bridge_attach(drm_dev, bridge);
+	drm_bridge_attach(encoder, bridge, NULL);
 
-	encoder->bridge = bridge;
 	connector->encoder = encoder;
 
 	drm_connector = (struct drm_connector *)connector;
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index c3ff10f559cc..ce071c17134b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
 	struct sun4i_drv *drv = drm->dev_private;
 	struct sun4i_tcon *tcon = drv->tcon;
 	struct drm_encoder *encoder;
+	struct drm_bridge *bridge;
 	struct sun4i_rgb *rgb;
 	int ret;
 
@@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
 	encoder = &rgb->encoder;
 
 	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
-	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
-	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
+	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
+	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
 		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
 		return 0;
 	}
@@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
 		}
 	}
 
-	if (!IS_ERR(encoder->bridge)) {
-		encoder->bridge->encoder = &rgb->encoder;
-
-		ret = drm_bridge_attach(drm, encoder->bridge);
+	if (!IS_ERR(bridge)) {
+		ret = drm_bridge_attach(encoder, bridge, NULL);
 		if (ret) {
 			dev_err(drm->dev, "Couldn't attach our bridge\n");
 			goto err_cleanup_connector;
 		}
-	} else {
-		encoder->bridge = NULL;
 	}
 
 	return 0;
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 530a1d6e8cde..94e5ee96b3b5 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -201,7 +201,8 @@ struct drm_bridge {
 int drm_bridge_add(struct drm_bridge *bridge);
 void drm_bridge_remove(struct drm_bridge *bridge);
 struct drm_bridge *of_drm_find_bridge(struct device_node *np);
-int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
+int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
+		      struct drm_bridge *previous);
 void drm_bridge_detach(struct drm_bridge *bridge);
 
 bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

Most drivers that use bridges forgot to detach them at cleanup time.
Instead of fixing them one by one, detach the bridge in the core
drm_encoder_cleanup() function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/drm_encoder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 5c067719164d..9c1f99646e0d 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 	 * the indices on the drm_encoder after us in the encoder_list.
 	 */
 
+	if (encoder->bridge)
+		drm_bridge_detach(encoder->bridge);
+
 	drm_modeset_lock_all(dev);
 	drm_mode_object_unregister(dev, &encoder->base);
 	kfree(encoder->name);
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
@ 2016-11-29  9:04   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

Most drivers that use bridges forgot to detach them at cleanup time.
Instead of fixing them one by one, detach the bridge in the core
drm_encoder_cleanup() function.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/drm_encoder.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 5c067719164d..9c1f99646e0d 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 	 * the indices on the drm_encoder after us in the encoder_list.
 	 */
 
+	if (encoder->bridge)
+		drm_bridge_detach(encoder->bridge);
+
 	drm_modeset_lock_all(dev);
 	drm_mode_object_unregister(dev, &encoder->base);
 	kfree(encoder->name);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 05/13] drm: bridge: Add LVDS encoder DT bindings
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04     ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Archit Taneja,
	devicetree-u79uwXL29TY76Z2rM5mHXA

The DT bindings support parallel to LVDS encoders that don't require any
configuration, similarly to the dumb VGA DAC DT bindings.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 .../bindings/display/bridge/lvds-transmitter.txt   | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
new file mode 100644
index 000000000000..fd39ad34c383
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
@@ -0,0 +1,64 @@
+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"
+
+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";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	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>;
+			};
+		};
+	};
+};
-- 
Regards,

Laurent Pinchart

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 05/13] drm: bridge: Add LVDS encoder DT bindings
@ 2016-11-29  9:04     ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja, devicetree

The DT bindings support parallel to LVDS encoders that don't require any
configuration, similarly to the dumb VGA DAC DT bindings.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../bindings/display/bridge/lvds-transmitter.txt   | 64 ++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt

diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
new file mode 100644
index 000000000000..fd39ad34c383
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt
@@ -0,0 +1,64 @@
+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"
+
+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";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	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>;
+			};
+		};
+	};
+};
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2016-11-29  9:04 ` Laurent Pinchart
                   ` (5 preceding siblings ...)
  (?)
@ 2016-11-29  9:04 ` Laurent Pinchart
  2016-11-29  9:54   ` Daniel Vetter
  -1 siblings, 1 reply; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

The LVDS encoder driver is a DRM bridge driver that supports the
parallel to LVDS encoders that don't require any configuration. The
driver thus doesn't interact with the device, but creates an LVDS
connector for the panel and exposes its size and timing based on
information retrieved from DT.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/Kconfig        |   8 ++
 drivers/gpu/drm/bridge/Makefile       |   1 +
 drivers/gpu/drm/bridge/lvds-encoder.c | 217 ++++++++++++++++++++++++++++++++++
 3 files changed, 226 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/lvds-encoder.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index bd6acc829f97..a4d9657c9477 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -24,6 +24,14 @@ config DRM_DUMB_VGA_DAC
 	help
 	  Support for RGB to VGA DAC based bridges
 
+config DRM_LVDS_ENCODER
+	tristate "Transparent parallel to LVDS encoder support"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Support for transparent parallel to LVDS encoders that don't require
+	  any configuration.
+
 config DRM_DW_HDMI
 	tristate
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 97ed1a5fea9a..7e0bf849c30d 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -2,6 +2,7 @@ ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
+obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
new file mode 100644
index 000000000000..576770ea8d7e
--- /dev/null
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_panel.h>
+
+#include <linux/of_graph.h>
+
+struct lvds_encoder {
+	struct device *dev;
+
+	struct drm_bridge bridge;
+	struct drm_connector connector;
+	struct drm_panel *panel;
+};
+
+static inline struct lvds_encoder *
+drm_bridge_to_lvds_encoder(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct lvds_encoder, bridge);
+}
+
+static inline struct lvds_encoder *
+drm_connector_to_lvds_encoder(struct drm_connector *connector)
+{
+	return container_of(connector, struct lvds_encoder, connector);
+}
+
+static int lvds_connector_get_modes(struct drm_connector *connector)
+{
+	struct lvds_encoder *lvds = drm_connector_to_lvds_encoder(connector);
+
+	return drm_panel_get_modes(lvds->panel);
+}
+
+static const struct drm_connector_helper_funcs lvds_connector_helper_funcs = {
+	.get_modes = lvds_connector_get_modes,
+};
+
+static enum drm_connector_status
+lvds_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs lvds_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = lvds_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int lvds_encoder_attach(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+	struct drm_connector *connector = &lvds->connector;
+	int ret;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Missing encoder\n");
+		return -ENODEV;
+	}
+
+	drm_connector_helper_add(connector, &lvds_connector_helper_funcs);
+
+	ret = drm_connector_init(bridge->dev, connector, &lvds_connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&lvds->connector, bridge->encoder);
+
+	ret = drm_panel_attach(lvds->panel, &lvds->connector);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void lvds_encoder_detach(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+	drm_panel_detach(lvds->panel);
+}
+
+static void lvds_encoder_pre_enable(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+	drm_panel_prepare(lvds->panel);
+}
+
+static void lvds_encoder_enable(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+	drm_panel_enable(lvds->panel);
+}
+
+static void lvds_encoder_disable(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+	drm_panel_disable(lvds->panel);
+}
+
+static void lvds_encoder_post_disable(struct drm_bridge *bridge)
+{
+	struct lvds_encoder *lvds = drm_bridge_to_lvds_encoder(bridge);
+
+	drm_panel_unprepare(lvds->panel);
+}
+
+static const struct drm_bridge_funcs lvds_encoder_bridge_funcs = {
+	.attach = lvds_encoder_attach,
+	.detach = lvds_encoder_detach,
+	.pre_enable = lvds_encoder_pre_enable,
+	.enable = lvds_encoder_enable,
+	.disable = lvds_encoder_disable,
+	.post_disable = lvds_encoder_post_disable,
+};
+
+static int lvds_encoder_probe(struct platform_device *pdev)
+{
+	struct lvds_encoder *lvds;
+	struct device_node *port;
+	struct device_node *endpoint;
+	struct device_node *panel;
+
+	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
+	if (!lvds)
+		return -ENOMEM;
+
+	lvds->dev = &pdev->dev;
+	platform_set_drvdata(pdev, lvds);
+
+	lvds->bridge.funcs = &lvds_encoder_bridge_funcs;
+	lvds->bridge.of_node = pdev->dev.of_node;
+	lvds->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
+	/* Locate the panel DT node. */
+	port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
+	if (!port) {
+		dev_dbg(&pdev->dev, "port 1 not found\n");
+		return -ENXIO;
+	}
+
+	endpoint = of_get_child_by_name(port, "endpoint");
+	of_node_put(port);
+	if (!endpoint) {
+		dev_dbg(&pdev->dev, "no endpoint for port 1\n");
+		return -ENXIO;
+	}
+
+	panel = of_graph_get_remote_port_parent(endpoint);
+	of_node_put(endpoint);
+	if (!panel) {
+		dev_dbg(&pdev->dev, "no remote endpoint for port 1\n");
+		return -ENXIO;
+	}
+
+	lvds->panel = of_drm_find_panel(panel);
+	of_node_put(panel);
+	if (!lvds->panel) {
+		dev_dbg(&pdev->dev, "panel not found, deferring probe\n");
+		return -EPROBE_DEFER;
+	}
+
+	/* Register the bridge. */
+	return drm_bridge_add(&lvds->bridge);
+}
+
+static int lvds_encoder_remove(struct platform_device *pdev)
+{
+	struct lvds_encoder *encoder = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&encoder->bridge);
+
+	return 0;
+}
+
+static const struct of_device_id lvds_encoder_match[] = {
+	{ .compatible = "lvds-encoder" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvds_encoder_match);
+
+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 <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Transparent parallel to LVDS encoder");
+MODULE_LICENSE("GPL");
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 07/13] drm: bridge: vga-dac: Add adi,adv7123 compatible string
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja, Maxime Ripard

The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
controlled through a power save pin, and requires a power supply.
However, on most boards where the device is used neither the power save
signal nor the power supply are controllable.

To avoid developing a separate device-specific driver add an
"adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
allow supporting most ADV7123-based boards easily, while allowing future
development of an adv7123 driver when needed without breaking backward
compatibility.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index afec232185a7..b33e3f829e4f 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
 
 static const struct of_device_id dumb_vga_match[] = {
 	{ .compatible = "dumb-vga-dac" },
+	{ .compatible = "adi,adv7123" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dumb_vga_match);
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 07/13] drm: bridge: vga-dac: Add adi, adv7123 compatible string
@ 2016-11-29  9:04   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Maxime Ripard

The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
controlled through a power save pin, and requires a power supply.
However, on most boards where the device is used neither the power save
signal nor the power supply are controllable.

To avoid developing a separate device-specific driver add an
"adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
allow supporting most ADV7123-based boards easily, while allowing future
development of an adv7123 driver when needed without breaking backward
compatibility.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index afec232185a7..b33e3f829e4f 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -204,6 +204,7 @@ static int dumb_vga_remove(struct platform_device *pdev)
 
 static const struct of_device_id dumb_vga_match[] = {
 	{ .compatible = "dumb-vga-dac" },
+	{ .compatible = "adi,adv7123" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, dumb_vga_match);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 08/13] drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

The THC63LVDM83D is a transparent LVDS encoder. Unlike dumb LVDS
encoders it can be controlled through a few pins (power down, LVDS
swing, clock edge selection) and requires power supplies. However, on
several boards where the device is used neither the control pins nor the
power supply are controllable.

To avoid developing a separate device-specific driver add a
"thine,thc63lvdm83d" compatible entry to the lvds-encoder driver. This
will allow supporting many THC63LVDM83D-based boards easily, while
allowing future development of an thc63lvdm83d driver when needed
without breaking backward compatibility.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/lvds-encoder.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
index 576770ea8d7e..16c5ac77824a 100644
--- a/drivers/gpu/drm/bridge/lvds-encoder.c
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -198,6 +198,7 @@ static int lvds_encoder_remove(struct platform_device *pdev)
 
 static const struct of_device_id lvds_encoder_match[] = {
 	{ .compatible = "lvds-encoder" },
+	{ .compatible = "thine,thc63lvdm83d" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, lvds_encoder_match);
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 08/13] drm: bridge: lvds-encoder: Add thine, thc63lvdm83d compatible string
@ 2016-11-29  9:04   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc

The THC63LVDM83D is a transparent LVDS encoder. Unlike dumb LVDS
encoders it can be controlled through a few pins (power down, LVDS
swing, clock edge selection) and requires power supplies. However, on
several boards where the device is used neither the control pins nor the
power supply are controllable.

To avoid developing a separate device-specific driver add a
"thine,thc63lvdm83d" compatible entry to the lvds-encoder driver. This
will allow supporting many THC63LVDM83D-based boards easily, while
allowing future development of an thc63lvdm83d driver when needed
without breaking backward compatibility.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/lvds-encoder.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/bridge/lvds-encoder.c b/drivers/gpu/drm/bridge/lvds-encoder.c
index 576770ea8d7e..16c5ac77824a 100644
--- a/drivers/gpu/drm/bridge/lvds-encoder.c
+++ b/drivers/gpu/drm/bridge/lvds-encoder.c
@@ -198,6 +198,7 @@ static int lvds_encoder_remove(struct platform_device *pdev)
 
 static const struct of_device_id lvds_encoder_match[] = {
 	{ .compatible = "lvds-encoder" },
+	{ .compatible = "thine,thc63lvdm83d" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, lvds_encoder_match);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29  9:04 ` Laurent Pinchart
                   ` (8 preceding siblings ...)
  (?)
@ 2016-11-29  9:04 ` Laurent Pinchart
  2016-11-29  9:56   ` Daniel Vetter
  -1 siblings, 1 reply; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

The drm_bridge object models on- or off-chip hardware encoders and
provide an abstract control API to display drivers. In order to help
display drivers creating the right kind of drm_encoder object, expose
the type of the hardware encoder associated with each bridge.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
Changes since v1:

- Clarify documentation
---
 include/drm/drm_bridge.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 94e5ee96b3b5..0643b6ce27de 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -194,6 +194,14 @@ struct drm_bridge {
 #endif
 	struct list_head list;
 
+	/**
+	 * @encoder_type:
+	 *
+	 * Type of the hardware encoder modeled by the bridge as one of the
+	 * DRM_MODE_ENCODER_* types. For the last bridge in the chain this will
+	 * usually be identical to the bridge's &drm_encoder encoder_type.
+	 */
+	int encoder_type;
 	const struct drm_bridge_funcs *funcs;
 	void *driver_private;
 };
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 10/13] drm: bridge: Set bridges' encoder type
  2016-11-29  9:04 ` Laurent Pinchart
                   ` (9 preceding siblings ...)
  (?)
@ 2016-11-29  9:04 ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Boris Brezillon,
	Enric Balletbo i Serra, Tomeu Vizoso, Sean Paul, Inki Dae,
	Ajay Kumar

Initialize the new drm_bridge::encoder_type field to the right value for
all external bridge drivers.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       | 1 +
 drivers/gpu/drm/bridge/analogix-anx78xx.c          | 1 +
 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1 +
 drivers/gpu/drm/bridge/dumb-vga-dac.c              | 1 +
 drivers/gpu/drm/bridge/dw-hdmi.c                   | 2 ++
 drivers/gpu/drm/bridge/nxp-ptn3460.c               | 2 ++
 drivers/gpu/drm/bridge/parade-ps8622.c             | 2 ++
 drivers/gpu/drm/bridge/sii902x.c                   | 2 ++
 drivers/gpu/drm/bridge/tc358767.c                  | 2 ++
 9 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 8ed3906dd411..66bbd2073529 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1030,6 +1030,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 
 	adv7511->bridge.funcs = &adv7511_bridge_funcs;
 	adv7511->bridge.of_node = dev->of_node;
+	adv7511->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
 
 	ret = drm_bridge_add(&adv7511->bridge);
 	if (ret) {
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index a2a82366a771..62be93f7ffaa 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1437,6 +1437,7 @@ static int anx78xx_i2c_probe(struct i2c_client *client,
 	}
 
 	anx78xx->bridge.funcs = &anx78xx_bridge_funcs;
+	anx78xx->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
 
 	err = drm_bridge_add(&anx78xx->bridge);
 	if (err < 0) {
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 1835f1fdad19..f0f9c5024e3e 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1229,6 +1229,7 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
 
 	bridge->driver_private = dp;
 	bridge->funcs = &analogix_dp_bridge_funcs;
+	bridge->encoder_type = DRM_MODE_ENCODER_TMDS;
 
 	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
 	if (ret) {
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index b33e3f829e4f..036c54c849e6 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -182,6 +182,7 @@ static int dumb_vga_probe(struct platform_device *pdev)
 
 	vga->bridge.funcs = &dumb_vga_bridge_funcs;
 	vga->bridge.of_node = pdev->dev.of_node;
+	vga->bridge.encoder_type = DRM_MODE_ENCODER_DAC;
 
 	ret = drm_bridge_add(&vga->bridge);
 	if (ret && !IS_ERR(vga->ddc))
diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 432e0e3fff72..0ac28aa76017 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1841,6 +1841,8 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
 	hdmi->bridge = bridge;
 	bridge->driver_private = hdmi;
 	bridge->funcs = &dw_hdmi_bridge_funcs;
+	bridge->encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_attach(encoder, bridge, NULL);
 	if (ret) {
 		DRM_ERROR("Failed to initialize bridge with drm\n");
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index f1a99938e924..8be117cc024f 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -349,6 +349,8 @@ static int ptn3460_probe(struct i2c_client *client,
 
 	ptn_bridge->bridge.funcs = &ptn3460_bridge_funcs;
 	ptn_bridge->bridge.of_node = dev->of_node;
+	ptn_bridge->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	ret = drm_bridge_add(&ptn_bridge->bridge);
 	if (ret) {
 		DRM_ERROR("Failed to add bridge\n");
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index 6f7c2f9860d2..37ac7211139a 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -615,6 +615,8 @@ static int ps8622_probe(struct i2c_client *client,
 
 	ps8622->bridge.funcs = &ps8622_bridge_funcs;
 	ps8622->bridge.of_node = dev->of_node;
+	ps8622->bridge.encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	ret = drm_bridge_add(&ps8622->bridge);
 	if (ret) {
 		DRM_ERROR("Failed to add bridge\n");
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 9126d0306ab5..ad4663dea333 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -418,6 +418,8 @@ static int sii902x_probe(struct i2c_client *client,
 
 	sii902x->bridge.funcs = &sii902x_bridge_funcs;
 	sii902x->bridge.of_node = dev->of_node;
+	sii902x->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&sii902x->bridge);
 	if (ret) {
 		dev_err(dev, "Failed to add drm_bridge\n");
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 44d476ea6d2e..934333cb647b 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -1353,6 +1353,8 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	tc->bridge.funcs = &tc_bridge_funcs;
 	tc->bridge.of_node = dev->of_node;
+	tc->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&tc->bridge);
 	if (ret) {
 		dev_err(dev, "Failed to add drm_bridge: %d\n", ret);
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 11/13] drm: Set on-chip bridges' encoder type
  2016-11-29  9:04 ` Laurent Pinchart
@ 2016-11-29  9:04   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, CK Hu, Philipp Zabel,
	Benjamin Gaignard, Vincent Abriou

Initialize the new drm_bridge::encoder_type field to the right value for
all bridges that model on-SoC IP cores.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/exynos/exynos_drm_mic.c | 2 ++
 drivers/gpu/drm/mediatek/mtk_hdmi.c     | 2 ++
 drivers/gpu/drm/sti/sti_dvo.c           | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index a0def0be6d65..7175ecda36e8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -390,6 +390,8 @@ static int exynos_mic_bind(struct device *dev, struct device *master,
 	mic->bridge.funcs = &mic_bridge_funcs;
 	mic->bridge.of_node = dev->of_node;
 	mic->bridge.driver_private = mic;
+	mic->bridge.encoder_type = DRM_MODE_ENCODER_DSI;
+
 	ret = drm_bridge_add(&mic->bridge);
 	if (ret)
 		DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 5ca1b0fbf937..bb5cf594c721 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1712,6 +1712,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
 	hdmi->bridge.of_node = pdev->dev.of_node;
+	hdmi->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&hdmi->bridge);
 	if (ret) {
 		dev_err(dev, "failed to add bridge, ret = %d\n", ret);
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 411dc6ec976e..8912c932078f 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -472,6 +472,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 	bridge->driver_private = dvo;
 	bridge->funcs = &sti_dvo_bridge_funcs;
 	bridge->of_node = dvo->dev.of_node;
+	bridge->encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	err = drm_bridge_add(bridge);
 	if (err) {
 		DRM_ERROR("Failed to add bridge\n");
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 11/13] drm: Set on-chip bridges' encoder type
@ 2016-11-29  9:04   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: Seung-Woo Kim, linux-renesas-soc, Kyungmin Park, Vincent Abriou

Initialize the new drm_bridge::encoder_type field to the right value for
all bridges that model on-SoC IP cores.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/exynos/exynos_drm_mic.c | 2 ++
 drivers/gpu/drm/mediatek/mtk_hdmi.c     | 2 ++
 drivers/gpu/drm/sti/sti_dvo.c           | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index a0def0be6d65..7175ecda36e8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -390,6 +390,8 @@ static int exynos_mic_bind(struct device *dev, struct device *master,
 	mic->bridge.funcs = &mic_bridge_funcs;
 	mic->bridge.of_node = dev->of_node;
 	mic->bridge.driver_private = mic;
+	mic->bridge.encoder_type = DRM_MODE_ENCODER_DSI;
+
 	ret = drm_bridge_add(&mic->bridge);
 	if (ret)
 		DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 5ca1b0fbf937..bb5cf594c721 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1712,6 +1712,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
 	hdmi->bridge.of_node = pdev->dev.of_node;
+	hdmi->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
+
 	ret = drm_bridge_add(&hdmi->bridge);
 	if (ret) {
 		dev_err(dev, "failed to add bridge, ret = %d\n", ret);
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 411dc6ec976e..8912c932078f 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -472,6 +472,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
 	bridge->driver_private = dvo;
 	bridge->funcs = &sti_dvo_bridge_funcs;
 	bridge->of_node = dvo->dev.of_node;
+	bridge->encoder_type = DRM_MODE_ENCODER_LVDS;
+
 	err = drm_bridge_add(bridge);
 	if (err) {
 		DRM_ERROR("Failed to add bridge\n");
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 12/13] drm: rcar-du: Replace manual bridge implementation with DRM bridge
  2016-11-29  9:04 ` Laurent Pinchart
                   ` (11 preceding siblings ...)
  (?)
@ 2016-11-29  9:04 ` Laurent Pinchart
  2016-12-27 12:40     ` Geert Uytterhoeven
  -1 siblings, 1 reply; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

The rcar-du driver contains a manual implementation of HDMI and VGA
bridges. Use DRM bridges to replace it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig           |   6 --
 drivers/gpu/drm/rcar-du/Makefile          |   5 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 104 +++++++++++++----------
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h |   2 -
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 134 ------------------------------
 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h |  35 --------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c  |  82 ------------------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h  |  23 -----
 8 files changed, 60 insertions(+), 331 deletions(-)
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h

diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index 2bab449add76..06121eeba9e5 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -11,12 +11,6 @@ config DRM_RCAR_DU
 	  Choose this option if you have an R-Car chipset.
 	  If M is selected the module will be called rcar-du-drm.
 
-config DRM_RCAR_HDMI
-	bool "R-Car DU HDMI Encoder Support"
-	depends on DRM_RCAR_DU
-	help
-	  Enable support for external HDMI encoders.
-
 config DRM_RCAR_LVDS
 	bool "R-Car DU LVDS Encoder Support"
 	depends on DRM_RCAR_DU
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index d3b44651061a..a492e6858691 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -4,10 +4,7 @@ rcar-du-drm-y := rcar_du_crtc.o \
 		 rcar_du_group.o \
 		 rcar_du_kms.o \
 		 rcar_du_lvdscon.o \
-		 rcar_du_plane.o \
-		 rcar_du_vgacon.o
-
-rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI)	+= rcar_du_hdmienc.o
+		 rcar_du_plane.o
 
 rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)	+= rcar_du_lvdsenc.o
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 21262057ef08..d412dc622bfa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -20,11 +20,9 @@
 
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
-#include "rcar_du_hdmienc.h"
 #include "rcar_du_kms.h"
 #include "rcar_du_lvdscon.h"
 #include "rcar_du_lvdsenc.h"
-#include "rcar_du_vgacon.h"
 
 /* -----------------------------------------------------------------------------
  * Encoder
@@ -63,29 +61,35 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder,
 	struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
 	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
 	const struct drm_display_mode *mode = &crtc_state->mode;
-	const struct drm_display_mode *panel_mode;
 	struct drm_connector *connector = conn_state->connector;
 	struct drm_device *dev = encoder->dev;
 
-	/* DAC encoders have currently no restriction on the mode. */
-	if (encoder->encoder_type == DRM_MODE_ENCODER_DAC)
-		return 0;
+	/*
+	 * Only panel-related encoder types require validation here, everything
+	 * else is handled by the bridge drivers.
+	 */
+	if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
+		const struct drm_display_mode *panel_mode;
 
-	if (list_empty(&connector->modes)) {
-		dev_dbg(dev->dev, "encoder: empty modes list\n");
-		return -EINVAL;
-	}
+		if (list_empty(&connector->modes)) {
+			dev_dbg(dev->dev, "encoder: empty modes list\n");
+			return -EINVAL;
+		}
 
-	panel_mode = list_first_entry(&connector->modes,
-				      struct drm_display_mode, head);
+		panel_mode = list_first_entry(&connector->modes,
+					      struct drm_display_mode, head);
 
-	/* We're not allowed to modify the resolution. */
-	if (mode->hdisplay != panel_mode->hdisplay ||
-	    mode->vdisplay != panel_mode->vdisplay)
-		return -EINVAL;
+		/* We're not allowed to modify the resolution. */
+		if (mode->hdisplay != panel_mode->hdisplay ||
+		    mode->vdisplay != panel_mode->vdisplay)
+			return -EINVAL;
 
-	/* The flat panel mode is fixed, just copy it to the adjusted mode. */
-	drm_mode_copy(adjusted_mode, panel_mode);
+		/*
+		 * The flat panel mode is fixed, just copy it to the adjusted
+		 * mode.
+		 */
+		drm_mode_copy(adjusted_mode, panel_mode);
+	}
 
 	if (renc->lvds)
 		rcar_du_lvdsenc_atomic_check(renc->lvds, adjusted_mode);
@@ -159,6 +163,7 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 {
 	struct rcar_du_encoder *renc;
 	struct drm_encoder *encoder;
+	struct drm_bridge *bridge = NULL;
 	unsigned int encoder_type;
 	int ret;
 
@@ -182,6 +187,15 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
+	if (enc_node) {
+		/* Locate the DRM bridge from the encoder DT node. */
+		bridge = of_drm_find_bridge(enc_node);
+		if (!bridge) {
+			ret = -EPROBE_DEFER;
+			goto done;
+		}
+	}
+
 	switch (type) {
 	case RCAR_DU_ENCODER_VGA:
 		encoder_type = DRM_MODE_ENCODER_DAC;
@@ -199,35 +213,35 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
-	if (type == RCAR_DU_ENCODER_HDMI) {
-		ret = rcar_du_hdmienc_init(rcdu, renc, enc_node);
-		if (ret < 0)
-			goto done;
-	} else {
-		ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-				       encoder_type, NULL);
-		if (ret < 0)
-			goto done;
-
-		drm_encoder_helper_add(encoder, &encoder_helper_funcs);
-	}
-
-	switch (encoder_type) {
-	case DRM_MODE_ENCODER_LVDS:
-		ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
-		break;
-
-	case DRM_MODE_ENCODER_DAC:
-		ret = rcar_du_vga_connector_init(rcdu, renc);
-		break;
+	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
+			       encoder_type, NULL);
+	if (ret < 0)
+		goto done;
 
-	case DRM_MODE_ENCODER_TMDS:
-		/* connector managed by the bridge driver */
-		break;
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
 
-	default:
-		ret = -EINVAL;
-		break;
+	if (bridge) {
+		/*
+		 * Attach the bridge to the encoder. The bridge will create the
+		 * connector.
+		 */
+		ret = drm_bridge_attach(encoder, bridge, NULL);
+		if (ret) {
+			drm_encoder_cleanup(encoder);
+			return ret;
+		}
+	} else {
+		/* There's no bridge, create the connector manually. */
+		switch (output) {
+		case RCAR_DU_OUTPUT_LVDS0:
+		case RCAR_DU_OUTPUT_LVDS1:
+			ret = rcar_du_lvds_connector_init(rcdu, renc, con_node);
+			break;
+
+		default:
+			ret = -EINVAL;
+			break;
+		}
 	}
 
 done:
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index b79b2f075a74..c1cfbe0d54ce 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -19,7 +19,6 @@
 
 struct drm_panel;
 struct rcar_du_device;
-struct rcar_du_hdmienc;
 struct rcar_du_lvdsenc;
 
 enum rcar_du_encoder_type {
@@ -34,7 +33,6 @@ struct rcar_du_encoder {
 	struct drm_encoder base;
 	enum rcar_du_output output;
 	struct rcar_du_connector *connector;
-	struct rcar_du_hdmienc *hdmi;
 	struct rcar_du_lvdsenc *lvds;
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
deleted file mode 100644
index 933a2547798e..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * R-Car Display Unit HDMI Encoder
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/slab.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_hdmienc.h"
-#include "rcar_du_lvdsenc.h"
-
-struct rcar_du_hdmienc {
-	struct rcar_du_encoder *renc;
-	bool enabled;
-};
-
-#define to_rcar_hdmienc(e)	(to_rcar_encoder(e)->hdmi)
-
-static void rcar_du_hdmienc_disable(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
-				       false);
-
-	hdmienc->enabled = false;
-}
-
-static void rcar_du_hdmienc_enable(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_enable(hdmienc->renc->lvds, encoder->crtc,
-				       true);
-
-	hdmienc->enabled = true;
-}
-
-static int rcar_du_hdmienc_atomic_check(struct drm_encoder *encoder,
-					struct drm_crtc_state *crtc_state,
-					struct drm_connector_state *conn_state)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
-
-	if (hdmienc->renc->lvds)
-		rcar_du_lvdsenc_atomic_check(hdmienc->renc->lvds,
-					     adjusted_mode);
-
-	return 0;
-}
-
-
-static void rcar_du_hdmienc_mode_set(struct drm_encoder *encoder,
-				     struct drm_crtc_state *crtc_state,
-				     struct drm_connector_state *conn_state)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	rcar_du_crtc_route_output(crtc_state->crtc, hdmienc->renc->output);
-}
-
-static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
-	.atomic_mode_set = rcar_du_hdmienc_mode_set,
-	.disable = rcar_du_hdmienc_disable,
-	.enable = rcar_du_hdmienc_enable,
-	.atomic_check = rcar_du_hdmienc_atomic_check,
-};
-
-static void rcar_du_hdmienc_cleanup(struct drm_encoder *encoder)
-{
-	struct rcar_du_hdmienc *hdmienc = to_rcar_hdmienc(encoder);
-
-	if (hdmienc->enabled)
-		rcar_du_hdmienc_disable(encoder);
-
-	drm_encoder_cleanup(encoder);
-}
-
-static const struct drm_encoder_funcs encoder_funcs = {
-	.destroy = rcar_du_hdmienc_cleanup,
-};
-
-int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-			 struct rcar_du_encoder *renc, struct device_node *np)
-{
-	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
-	struct drm_bridge *bridge;
-	struct rcar_du_hdmienc *hdmienc;
-	int ret;
-
-	hdmienc = devm_kzalloc(rcdu->dev, sizeof(*hdmienc), GFP_KERNEL);
-	if (hdmienc == NULL)
-		return -ENOMEM;
-
-	/* Locate the DRM bridge from the HDMI encoder DT node. */
-	bridge = of_drm_find_bridge(np);
-	if (!bridge)
-		return -EPROBE_DEFER;
-
-	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
-			       DRM_MODE_ENCODER_TMDS, NULL);
-	if (ret < 0)
-		return ret;
-
-	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
-
-	renc->hdmi = hdmienc;
-	hdmienc->renc = renc;
-
-	/* Link the bridge to the encoder. */
-	ret = drm_bridge_attach(encoder, bridge, NULL);
-	if (ret) {
-		drm_encoder_cleanup(encoder);
-		return ret;
-	}
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
deleted file mode 100644
index 2ff0128ac8e1..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * R-Car Display Unit HDMI Encoder
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_HDMIENC_H__
-#define __RCAR_DU_HDMIENC_H__
-
-#include <linux/module.h>
-
-struct device_node;
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-#if IS_ENABLED(CONFIG_DRM_RCAR_HDMI)
-int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-			 struct rcar_du_encoder *renc, struct device_node *np);
-#else
-static inline int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
-				       struct rcar_du_encoder *renc,
-				       struct device_node *np)
-{
-	return -ENOSYS;
-}
-#endif
-
-#endif /* __RCAR_DU_HDMIENC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
deleted file mode 100644
index 8d6125c1c0f9..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * rcar_du_vgacon.c  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_vgacon.h"
-
-static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
-{
-	return 0;
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-	.get_modes = rcar_du_vga_connector_get_modes,
-};
-
-static enum drm_connector_status
-rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-	.dpms = drm_atomic_helper_connector_dpms,
-	.reset = drm_atomic_helper_connector_reset,
-	.detect = rcar_du_vga_connector_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = drm_connector_cleanup,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc)
-{
-	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
-	struct rcar_du_connector *rcon;
-	struct drm_connector *connector;
-	int ret;
-
-	rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
-	if (rcon == NULL)
-		return -ENOMEM;
-
-	connector = &rcon->connector;
-	connector->display_info.width_mm = 0;
-	connector->display_info.height_mm = 0;
-	connector->interlace_allowed = true;
-
-	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-				 DRM_MODE_CONNECTOR_VGA);
-	if (ret < 0)
-		return ret;
-
-	drm_connector_helper_add(connector, &connector_helper_funcs);
-
-	connector->dpms = DRM_MODE_DPMS_OFF;
-	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-	ret = drm_mode_connector_attach_encoder(connector, encoder);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
deleted file mode 100644
index 112f50316e01..000000000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * rcar_du_vgacon.h  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __RCAR_DU_VGACON_H__
-#define __RCAR_DU_VGACON_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc);
-
-#endif /* __RCAR_DU_VGACON_H__ */
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH v3 13/13] drm: rcar-du: Initialize encoder's type based on the bridge's type
  2016-11-29  9:04 ` Laurent Pinchart
                   ` (12 preceding siblings ...)
  (?)
@ 2016-11-29  9:04 ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:04 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-renesas-soc, Archit Taneja

Set the type of the DRM encoder that models the hardware encoders
(bridges) chain based on the type of the last bridge in the chain
instead of hardcoding encoder compatible strings in the display driver.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 17 ++------------
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h |  1 -
 drivers/gpu/drm/rcar-du/rcar_du_kms.c     | 37 ++-----------------------------
 3 files changed, 4 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index d412dc622bfa..1adf4a77904e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -156,7 +156,6 @@ static const struct drm_encoder_funcs encoder_funcs = {
 };
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
 			 enum rcar_du_output output,
 			 struct device_node *enc_node,
 			 struct device_node *con_node)
@@ -194,23 +193,11 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 			ret = -EPROBE_DEFER;
 			goto done;
 		}
-	}
 
-	switch (type) {
-	case RCAR_DU_ENCODER_VGA:
-		encoder_type = DRM_MODE_ENCODER_DAC;
-		break;
-	case RCAR_DU_ENCODER_LVDS:
-		encoder_type = DRM_MODE_ENCODER_LVDS;
-		break;
-	case RCAR_DU_ENCODER_HDMI:
-		encoder_type = DRM_MODE_ENCODER_TMDS;
-		break;
-	case RCAR_DU_ENCODER_NONE:
-	default:
+		encoder_type = bridge->encoder_type;
+	} else {
 		/* No external encoder, use the internal encoder type. */
 		encoder_type = rcdu->info->routes[output].encoder_type;
-		break;
 	}
 
 	ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index c1cfbe0d54ce..2b9036e7f6fe 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -51,7 +51,6 @@ struct rcar_du_connector {
 	container_of(c, struct rcar_du_connector, connector)
 
 int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
 			 enum rcar_du_output output,
 			 struct device_node *enc_node,
 			 struct device_node *con_node);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index b5d3f16cfa12..aa84689043ae 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -366,16 +366,6 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 				     enum rcar_du_output output,
 				     struct of_endpoint *ep)
 {
-	static const struct {
-		const char *compatible;
-		enum rcar_du_encoder_type type;
-	} encoders[] = {
-		{ "adi,adv7123", RCAR_DU_ENCODER_VGA },
-		{ "adi,adv7511w", RCAR_DU_ENCODER_HDMI },
-		{ "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS },
-	};
-
-	enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE;
 	struct device_node *connector = NULL;
 	struct device_node *encoder = NULL;
 	struct device_node *ep_node = NULL;
@@ -422,30 +412,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 
 	of_node_put(entity_ep_node);
 
-	if (encoder) {
-		/*
-		 * If an encoder has been found, get its type based on its
-		 * compatible string.
-		 */
-		unsigned int i;
-
-		for (i = 0; i < ARRAY_SIZE(encoders); ++i) {
-			if (of_device_is_compatible(encoder,
-						    encoders[i].compatible)) {
-				enc_type = encoders[i].type;
-				break;
-			}
-		}
-
-		if (i == ARRAY_SIZE(encoders)) {
-			dev_warn(rcdu->dev,
-				 "unknown encoder type for %s, skipping\n",
-				 encoder->full_name);
-			of_node_put(encoder);
-			of_node_put(connector);
-			return -EINVAL;
-		}
-	} else {
+	if (!encoder) {
 		/*
 		 * If no encoder has been found the entity must be the
 		 * connector.
@@ -453,7 +420,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
 		connector = entity;
 	}
 
-	ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
+	ret = rcar_du_encoder_init(rcdu, output, encoder, connector);
 	if (ret && ret != -EPROBE_DEFER)
 		dev_warn(rcdu->dev,
 			 "failed to initialize encoder %s on output %u (%d), skipping\n",
-- 
Regards,

Laurent Pinchart

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
  2016-11-29  9:04 ` [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h> Laurent Pinchart
@ 2016-11-29  9:30     ` Daniel Vetter
  2016-12-02 21:21     ` Sinclair Yeh
  1 sibling, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:30 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, Alison Wang, Thomas Hellstrom, linux-renesas-soc,
	Alex Deucher, Daniel Vetter, Christian König, Ben Skeggs

On Tue, Nov 29, 2016 at 11:04:31AM +0200, Laurent Pinchart wrote:
> <drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
> now been split into separate files for each object type, but still
> includes most other KMS headers to avoid breaking driver compilation.
> 
> As a step towards fixing that problem, remove the inclusion of
> <drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
> appropriate. Also remove the forward declarations of the drm_encoder and
> drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
> needed in the header.
> 
> <drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
> forward declaration of struct drm_encoder in order to allow including it
> as the first header in a compilation unit.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Assuming it all still compiles the various defconfigs we have (I didn't
check that, but lgtm otherwise):

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
>  drivers/gpu/drm/ast/ast_drv.h               | 1 +
>  drivers/gpu/drm/bochs/bochs.h               | 1 +
>  drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
>  drivers/gpu/drm/drm_connector.c             | 1 +
>  drivers/gpu/drm/drm_crtc_helper.c           | 1 +
>  drivers/gpu/drm/drm_edid.c                  | 1 +
>  drivers/gpu/drm/drm_mode_config.c           | 1 +
>  drivers/gpu/drm/drm_of.c                    | 1 +
>  drivers/gpu/drm/drm_plane_helper.c          | 1 +
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
>  drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
>  drivers/gpu/drm/i915/intel_drv.h            | 1 +
>  drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
>  drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
>  drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
>  drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
>  drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
>  drivers/gpu/drm/tegra/drm.h                 | 1 +
>  drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
>  drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
>  include/drm/drm_crtc.h                      | 3 ---
>  include/drm/drm_encoder.h                   | 3 +++
>  include/drm/drm_encoder_slave.h             | 1 +
>  include/drm/drm_modeset_helper_vtables.h    | 1 +
>  27 files changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 1e23334b07fb..fac06064a8f5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_fixed.h>
>  #include <drm/drm_crtc_helper.h>
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index 908011d2c8f5..6f3b6f50cf52 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -28,6 +28,7 @@
>  #ifndef __AST_DRV_H__
>  #define __AST_DRV_H__
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
> index 32dfe418cc98..f626bab7f5e3 100644
> --- a/drivers/gpu/drm/bochs/bochs.h
> +++ b/drivers/gpu/drm/bochs/bochs.h
> @@ -4,6 +4,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/drm_gem.h>
> diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
> index 2188d6b61b3e..b59aeef4635a 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> @@ -13,6 +13,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index b5c6a8ee831e..5f1e1f190d30 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -23,6 +23,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5d2cb138eba6..b3fc23313cc3 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -36,6 +36,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_fb_helper.h>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 7eec18925b70..a9e3cc3990c1 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -35,6 +35,7 @@
>  #include <linux/vga_switcheroo.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_displayid.h>
>  
>  #define version_greater(edid, maj, min) \
> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
> index 2735a5847ffa..09b1d8f267a6 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -20,6 +20,7 @@
>   * OF THIS SOFTWARE.
>   */
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_mode_config.h>
>  #include <drm/drmP.h>
>  
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b5f2f0fece99 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -4,6 +4,7 @@
>  #include <linux/of_graph.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 7a7dddf604d7..191a5f095cf9 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -29,6 +29,7 @@
>  #include <drm/drm_rect.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_atomic_helper.h>
>  
>  #define SUBPIXEL_MASK 0xffff
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> index 3b371fe7491e..4c22edd4c746 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> @@ -12,6 +12,8 @@
>  #ifndef __FSL_DCU_DRM_DRV_H__
>  #define __FSL_DCU_DRM_DRV_H__
>  
> +#include <drm/drm_encoder.h>
> +
>  #include "fsl_dcu_drm_crtc.h"
>  #include "fsl_dcu_drm_output.h"
>  #include "fsl_dcu_drm_plane.h"
> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
> index 2a3b7c684db2..6a10215fc42d 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> @@ -23,6 +23,7 @@
>  #include <linux/i2c-algo-bit.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <linux/gpio.h>
>  #include "gma_display.h"
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 398195bf6dd1..7fb8ac824b01 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -32,6 +32,7 @@
>  #include "i915_drv.h"
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_dp_dual_mode_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
> index 3e02ac20777c..87e0934773de 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> @@ -15,6 +15,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/ttm/ttm_bo_api.h>
>  #include <drm/ttm/ttm_bo_driver.h>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
> index 096983c42a1f..a4d1a059bd3d 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
> @@ -30,6 +30,7 @@
>  #include <nvif/notify.h>
>  
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include "nouveau_crtc.h"
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 84995ebc6ffc..56df6b4ddbab 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -43,6 +43,7 @@
>  #include <ttm/ttm_placement.h>
>  #include <ttm/ttm_module.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_gem.h>
>  
>  /* just for ttm_validate_buffer */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index bb75201a24ba..7ceea8ffd0db 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
>  #include <drm/drm_fixed.h>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> index 269fbab15907..b79b2f075a74 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> @@ -15,6 +15,7 @@
>  #define __RCAR_DU_ENCODER_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct drm_panel;
>  struct rcar_du_device;
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> index 38ed4ff8aaf2..818b31549ddc 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> @@ -16,6 +16,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct backlight_device;
>  struct shmob_drm_device;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 0ddcce1b420d..5205790dd679 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -17,6 +17,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_fixed.h>
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index fef172804345..f89a95cb98cf 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -9,6 +9,8 @@
>  #include "drmP.h"
>  #include "drm_gem_cma_helper.h"
>  
> +#include <drm/drm_encoder.h>
> +
>  struct vc4_dev {
>  	struct drm_device *dev;
>  
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
> index ec1ebdcfe80b..475ac93848c3 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> @@ -35,6 +35,7 @@
>  #include <drm/drm_gem.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <ttm/ttm_bo_api.h>
>  #include <ttm/ttm_bo_driver.h>
>  #include <ttm/ttm_placement.h>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index ff4803c107bc..5ee25fb07ea2 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -30,6 +30,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include "vmwgfx_drv.h"
>  
>  /**
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 946672f97e1e..9ef0ac0ce69f 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -39,7 +39,6 @@
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_modes.h>
>  #include <drm/drm_connector.h>
> -#include <drm/drm_encoder.h>
>  #include <drm/drm_property.h>
>  #include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
> @@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
>  }
>  
>  struct drm_crtc;
> -struct drm_encoder;
>  struct drm_pending_vblank_event;
>  struct drm_plane;
>  struct drm_bridge;
>  struct drm_atomic_state;
>  
>  struct drm_crtc_helper_funcs;
> -struct drm_encoder_helper_funcs;
>  struct drm_plane_helper_funcs;
>  
>  /**
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index c7438ff0d609..cec6ac45c6cc 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -25,8 +25,11 @@
>  
>  #include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <drm/drm_mode.h>
>  #include <drm/drm_mode_object.h>
>  
> +struct drm_encoder;
> +
>  /**
>   * struct drm_encoder_funcs - encoder controls
>   *
> diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
> index 82cdf611393d..1107b4b1c599 100644
> --- a/include/drm/drm_encoder_slave.h
> +++ b/include/drm/drm_encoder_slave.h
> @@ -29,6 +29,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 72478cf82147..21d9823d4872 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -30,6 +30,7 @@
>  #define __DRM_MODESET_HELPER_VTABLES_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
@ 2016-11-29  9:30     ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:30 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Thomas Hellstrom, Alison Wang, dri-devel, linux-renesas-soc,
	Ben Skeggs, Alex Deucher, Daniel Vetter, Christian König

On Tue, Nov 29, 2016 at 11:04:31AM +0200, Laurent Pinchart wrote:
> <drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
> now been split into separate files for each object type, but still
> includes most other KMS headers to avoid breaking driver compilation.
> 
> As a step towards fixing that problem, remove the inclusion of
> <drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
> appropriate. Also remove the forward declarations of the drm_encoder and
> drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
> needed in the header.
> 
> <drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
> forward declaration of struct drm_encoder in order to allow including it
> as the first header in a compilation unit.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Assuming it all still compiles the various defconfigs we have (I didn't
check that, but lgtm otherwise):

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
>  drivers/gpu/drm/ast/ast_drv.h               | 1 +
>  drivers/gpu/drm/bochs/bochs.h               | 1 +
>  drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
>  drivers/gpu/drm/drm_connector.c             | 1 +
>  drivers/gpu/drm/drm_crtc_helper.c           | 1 +
>  drivers/gpu/drm/drm_edid.c                  | 1 +
>  drivers/gpu/drm/drm_mode_config.c           | 1 +
>  drivers/gpu/drm/drm_of.c                    | 1 +
>  drivers/gpu/drm/drm_plane_helper.c          | 1 +
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
>  drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
>  drivers/gpu/drm/i915/intel_drv.h            | 1 +
>  drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
>  drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
>  drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
>  drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
>  drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
>  drivers/gpu/drm/tegra/drm.h                 | 1 +
>  drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
>  drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
>  include/drm/drm_crtc.h                      | 3 ---
>  include/drm/drm_encoder.h                   | 3 +++
>  include/drm/drm_encoder_slave.h             | 1 +
>  include/drm/drm_modeset_helper_vtables.h    | 1 +
>  27 files changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 1e23334b07fb..fac06064a8f5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_fixed.h>
>  #include <drm/drm_crtc_helper.h>
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index 908011d2c8f5..6f3b6f50cf52 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -28,6 +28,7 @@
>  #ifndef __AST_DRV_H__
>  #define __AST_DRV_H__
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
> index 32dfe418cc98..f626bab7f5e3 100644
> --- a/drivers/gpu/drm/bochs/bochs.h
> +++ b/drivers/gpu/drm/bochs/bochs.h
> @@ -4,6 +4,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/drm_gem.h>
> diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
> index 2188d6b61b3e..b59aeef4635a 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> @@ -13,6 +13,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index b5c6a8ee831e..5f1e1f190d30 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -23,6 +23,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5d2cb138eba6..b3fc23313cc3 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -36,6 +36,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_fb_helper.h>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 7eec18925b70..a9e3cc3990c1 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -35,6 +35,7 @@
>  #include <linux/vga_switcheroo.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_displayid.h>
>  
>  #define version_greater(edid, maj, min) \
> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
> index 2735a5847ffa..09b1d8f267a6 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -20,6 +20,7 @@
>   * OF THIS SOFTWARE.
>   */
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_mode_config.h>
>  #include <drm/drmP.h>
>  
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b5f2f0fece99 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -4,6 +4,7 @@
>  #include <linux/of_graph.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 7a7dddf604d7..191a5f095cf9 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -29,6 +29,7 @@
>  #include <drm/drm_rect.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_atomic_helper.h>
>  
>  #define SUBPIXEL_MASK 0xffff
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> index 3b371fe7491e..4c22edd4c746 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> @@ -12,6 +12,8 @@
>  #ifndef __FSL_DCU_DRM_DRV_H__
>  #define __FSL_DCU_DRM_DRV_H__
>  
> +#include <drm/drm_encoder.h>
> +
>  #include "fsl_dcu_drm_crtc.h"
>  #include "fsl_dcu_drm_output.h"
>  #include "fsl_dcu_drm_plane.h"
> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
> index 2a3b7c684db2..6a10215fc42d 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> @@ -23,6 +23,7 @@
>  #include <linux/i2c-algo-bit.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <linux/gpio.h>
>  #include "gma_display.h"
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 398195bf6dd1..7fb8ac824b01 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -32,6 +32,7 @@
>  #include "i915_drv.h"
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_dp_dual_mode_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
> index 3e02ac20777c..87e0934773de 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> @@ -15,6 +15,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/ttm/ttm_bo_api.h>
>  #include <drm/ttm/ttm_bo_driver.h>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
> index 096983c42a1f..a4d1a059bd3d 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
> @@ -30,6 +30,7 @@
>  #include <nvif/notify.h>
>  
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include "nouveau_crtc.h"
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 84995ebc6ffc..56df6b4ddbab 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -43,6 +43,7 @@
>  #include <ttm/ttm_placement.h>
>  #include <ttm/ttm_module.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_gem.h>
>  
>  /* just for ttm_validate_buffer */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index bb75201a24ba..7ceea8ffd0db 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
>  #include <drm/drm_fixed.h>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> index 269fbab15907..b79b2f075a74 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> @@ -15,6 +15,7 @@
>  #define __RCAR_DU_ENCODER_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct drm_panel;
>  struct rcar_du_device;
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> index 38ed4ff8aaf2..818b31549ddc 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> @@ -16,6 +16,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct backlight_device;
>  struct shmob_drm_device;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 0ddcce1b420d..5205790dd679 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -17,6 +17,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_fixed.h>
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index fef172804345..f89a95cb98cf 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -9,6 +9,8 @@
>  #include "drmP.h"
>  #include "drm_gem_cma_helper.h"
>  
> +#include <drm/drm_encoder.h>
> +
>  struct vc4_dev {
>  	struct drm_device *dev;
>  
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
> index ec1ebdcfe80b..475ac93848c3 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> @@ -35,6 +35,7 @@
>  #include <drm/drm_gem.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <ttm/ttm_bo_api.h>
>  #include <ttm/ttm_bo_driver.h>
>  #include <ttm/ttm_placement.h>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index ff4803c107bc..5ee25fb07ea2 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -30,6 +30,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include "vmwgfx_drv.h"
>  
>  /**
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 946672f97e1e..9ef0ac0ce69f 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -39,7 +39,6 @@
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_modes.h>
>  #include <drm/drm_connector.h>
> -#include <drm/drm_encoder.h>
>  #include <drm/drm_property.h>
>  #include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
> @@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
>  }
>  
>  struct drm_crtc;
> -struct drm_encoder;
>  struct drm_pending_vblank_event;
>  struct drm_plane;
>  struct drm_bridge;
>  struct drm_atomic_state;
>  
>  struct drm_crtc_helper_funcs;
> -struct drm_encoder_helper_funcs;
>  struct drm_plane_helper_funcs;
>  
>  /**
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index c7438ff0d609..cec6ac45c6cc 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -25,8 +25,11 @@
>  
>  #include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <drm/drm_mode.h>
>  #include <drm/drm_mode_object.h>
>  
> +struct drm_encoder;
> +
>  /**
>   * struct drm_encoder_funcs - encoder controls
>   *
> diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
> index 82cdf611393d..1107b4b1c599 100644
> --- a/include/drm/drm_encoder_slave.h
> +++ b/include/drm/drm_encoder_slave.h
> @@ -29,6 +29,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 72478cf82147..21d9823d4872 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -30,6 +30,7 @@
>  #define __DRM_MODESET_HELPER_VTABLES_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 02/13] drm: Fix compilation warning caused by static inline forward declaration
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-29  9:31     ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:31 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 11:04:32AM +0200, Laurent Pinchart wrote:
> The drm_crtc_mask() function used in <drm/drm_encoder.h> is a static
> inline defined in <drm/drm_crtc.h>. If the first header is included in a
> compilation unit without the second one, the following compilation
> warning will be issued.
> 
> In file included from <linux>/drivers/gpu/drm/drm_bridge.c:29:0:
> <linux>/include/drm/drm_encoder.h:192:95: warning: ‘drm_crtc_mask’ used but never defined
>  static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
> 
> Fix this by including the header defining the function instead of using
> a forward declaration.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  include/drm/drm_encoder.h | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index cec6ac45c6cc..5f58f65344e0 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -25,6 +25,7 @@
>  
>  #include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <drm/drm_crtc.h>
>  #include <drm/drm_mode.h>
>  #include <drm/drm_mode_object.h>
>  
> @@ -191,9 +192,6 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
>  	return encoder->index;
>  }
>  
> -/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
> -static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
> -
>  /**
>   * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
>   * @encoder: encoder to test
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 02/13] drm: Fix compilation warning caused by static inline forward declaration
@ 2016-11-29  9:31     ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:31 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel

On Tue, Nov 29, 2016 at 11:04:32AM +0200, Laurent Pinchart wrote:
> The drm_crtc_mask() function used in <drm/drm_encoder.h> is a static
> inline defined in <drm/drm_crtc.h>. If the first header is included in a
> compilation unit without the second one, the following compilation
> warning will be issued.
> 
> In file included from <linux>/drivers/gpu/drm/drm_bridge.c:29:0:
> <linux>/include/drm/drm_encoder.h:192:95: warning: ‘drm_crtc_mask’ used but never defined
>  static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
> 
> Fix this by including the header defining the function instead of using
> a forward declaration.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  include/drm/drm_encoder.h | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index cec6ac45c6cc..5f58f65344e0 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -25,6 +25,7 @@
>  
>  #include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <drm/drm_crtc.h>
>  #include <drm/drm_mode.h>
>  #include <drm/drm_mode_object.h>
>  
> @@ -191,9 +192,6 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
>  	return encoder->index;
>  }
>  
> -/* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */
> -static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc);
> -
>  /**
>   * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
>   * @encoder: encoder to test
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-29  9:35     ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, Alison Wang, Jingoo Han, Seung-Woo Kim, Xinwei Kong,
	linux-renesas-soc, Kyungmin Park, Xinliang Liu, Chen Feng,
	Rongrong Zou, Maxime Ripard, Vincent Abriou

On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>  	of_node_put(np);
>  
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>  
>  	dp->bridge = bridge;
>  
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>  
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;

Not sure we want to allow setting both encoder and bridge for chaining.
I'd kinda expect that for chained use-case the bridge doesn't care that
much who started the chain. And if not we can always create a helper to
look up the drm_encoder.

Also, should we convert these to WARN_ON, they're kinda glaring driver (or
well DT) bugs?

Otherwise looks all reasonable to me, but deferring to Archit for final
review.
-Daniel

>  
>  	if (bridge->dev)
>  		return -EBUSY;
>  
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>  
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	bridge->encoder = &pipe->encoder;
> -	pipe->encoder.bridge = bridge;
> -	return drm_bridge_attach(pipe->encoder.dev, bridge);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  				   struct drm_connector *connector)
>  {
>  	struct exynos_dp_device *dp = to_dp(plat_data);
> -	struct drm_encoder *encoder = &dp->encoder;
>  	int ret;
>  
>  	drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		bridge->next = dp->ptn_bridge;
> -		dp->ptn_bridge->encoder = encoder;
> -		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>  	}
>  
>  	bridge = of_drm_find_bridge(dsi->bridge_node);
> -	if (bridge) {
> -		encoder->bridge = bridge;
> -		drm_bridge_attach(drm_dev, bridge);
> -	}
> +	if (bridge)
> +		drm_bridge_attach(encoder, bridge, NULL);
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	fsl_dev->encoder.bridge = bridge;
> -	bridge->encoder = &fsl_dev->encoder;
> -
> -	return drm_bridge_attach(fsl_dev->drm, bridge);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>  
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -
> -	ret = drm_bridge_attach(dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>  			 DRM_MODE_ENCODER_LVDS, NULL);
>  
>  	if (imx_ldb_ch->bridge) {
> -		imx_ldb_ch->bridge->encoder = encoder;
> -
> -		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +					imx_ldb_ch->bridge, NULL);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		imxpd->bridge->encoder = encoder;
> -		encoder->bridge = imxpd->bridge;
> -		ret = drm_bridge_attach(drm, imxpd->bridge);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	dpi->encoder.bridge->encoder = &dpi->encoder;
> -	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  
>  	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>  
> -	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +	dpi->bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->encoder.bridge)
> +	if (!dpi->bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>  	.get_modes = mtk_dsi_connector_get_modes,
>  };
>  
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -				 struct drm_encoder *encoder)
> -{
> -	int ret;
> -
> -	if (!bridge)
> -		return -ENOENT;
> -
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -	ret = drm_bridge_attach(encoder->dev, bridge);
> -	if (ret) {
> -		DRM_ERROR("Failed to attach bridge to drm\n");
> -		encoder->bridge = NULL;
> -		bridge->encoder = NULL;
> -	}
> -
> -	return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>  	dsi->encoder.possible_crtcs = 1;
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
> -	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>  	if (ret) {
> +		DRM_ERROR("Failed to attach bridge to drm\n");
> +
>  		/* Otherwise create our own connector and attach to a panel */
>  		ret = mtk_dsi_create_connector(drm, dsi);
>  		if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>  
>  struct mtk_hdmi {
>  	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
>  	struct drm_connector conn;
>  	struct device *dev;
>  	struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>  		return ret;
>  	}
>  
> -	if (bridge->next) {
> -		bridge->next->encoder = bridge->encoder;
> -		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +	if (hdmi->next_bridge) {
> +		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +					bridge);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	of_node_put(ep);
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -		hdmi->bridge.next = of_drm_find_bridge(remote);
> -		if (!hdmi->bridge.next) {
> +		hdmi->next_bridge = of_drm_find_bridge(remote);
> +		if (!hdmi->next_bridge) {
>  			dev_err(dev, "Waiting for external bridge\n");
>  			of_node_put(remote);
>  			return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>  	struct drm_bridge *bridge = NULL;
>  	struct dsi_bridge *dsi_bridge;
> +	struct drm_encoder *encoder;
>  	int ret;
>  
>  	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  
>  	dsi_bridge->id = id;
>  
> +	/*
> +	 * HACK: we may not know the external DSI bridge device's mode
> +	 * flags here. We'll get to know them only when the device
> +	 * attaches to the dsi host. For now, assume the bridge supports
> +	 * DSI video mode
> +	 */
> +	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> @@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	int_bridge->next = ext_bridge;
> -	/* set the external bridge's encoder as dsi's encoder */
> -	ext_bridge->encoder = encoder;
> -
> -	drm_bridge_attach(dev, ext_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->dev, bridge);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->dev, bridge);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>  	hdmienc->renc = renc;
>  
>  	/* Link the bridge to the encoder. */
> -	bridge->encoder = encoder;
> -	encoder->bridge = bridge;
> -
> -	ret = drm_bridge_attach(rcdu->ddev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  		return err;
>  	}
>  
> -	err = drm_bridge_attach(drm_dev, bridge);
> +	err = drm_bridge_attach(encoder, bridge, NULL);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
>  	}
>  
>  	dvo->bridge = bridge;
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  	dvo->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sun4i_tcon *tcon = drv->tcon;
>  	struct drm_encoder *encoder;
> +	struct drm_bridge *bridge;
>  	struct sun4i_rgb *rgb;
>  	int ret;
>  
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	encoder = &rgb->encoder;
>  
>  	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>  		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>  		return 0;
>  	}
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> -		encoder->bridge->encoder = &rgb->encoder;
> -
> -		ret = drm_bridge_attach(drm, encoder->bridge);
> +	if (!IS_ERR(bridge)) {
> +		ret = drm_bridge_attach(encoder, bridge, NULL);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29  9:35     ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Xinliang Liu, Alison Wang, Jingoo Han, Seung-Woo Kim,
	Kyungmin Park, dri-devel, linux-renesas-soc, Xinwei Kong,
	Chen Feng, Rongrong Zou, Maxime Ripard, Vincent Abriou

On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>  	of_node_put(np);
>  
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>  
>  	dp->bridge = bridge;
>  
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>  
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;

Not sure we want to allow setting both encoder and bridge for chaining.
I'd kinda expect that for chained use-case the bridge doesn't care that
much who started the chain. And if not we can always create a helper to
look up the drm_encoder.

Also, should we convert these to WARN_ON, they're kinda glaring driver (or
well DT) bugs?

Otherwise looks all reasonable to me, but deferring to Archit for final
review.
-Daniel

>  
>  	if (bridge->dev)
>  		return -EBUSY;
>  
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>  
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	bridge->encoder = &pipe->encoder;
> -	pipe->encoder.bridge = bridge;
> -	return drm_bridge_attach(pipe->encoder.dev, bridge);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  				   struct drm_connector *connector)
>  {
>  	struct exynos_dp_device *dp = to_dp(plat_data);
> -	struct drm_encoder *encoder = &dp->encoder;
>  	int ret;
>  
>  	drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		bridge->next = dp->ptn_bridge;
> -		dp->ptn_bridge->encoder = encoder;
> -		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>  	}
>  
>  	bridge = of_drm_find_bridge(dsi->bridge_node);
> -	if (bridge) {
> -		encoder->bridge = bridge;
> -		drm_bridge_attach(drm_dev, bridge);
> -	}
> +	if (bridge)
> +		drm_bridge_attach(encoder, bridge, NULL);
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	fsl_dev->encoder.bridge = bridge;
> -	bridge->encoder = &fsl_dev->encoder;
> -
> -	return drm_bridge_attach(fsl_dev->drm, bridge);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>  
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -
> -	ret = drm_bridge_attach(dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>  			 DRM_MODE_ENCODER_LVDS, NULL);
>  
>  	if (imx_ldb_ch->bridge) {
> -		imx_ldb_ch->bridge->encoder = encoder;
> -
> -		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +					imx_ldb_ch->bridge, NULL);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		imxpd->bridge->encoder = encoder;
> -		encoder->bridge = imxpd->bridge;
> -		ret = drm_bridge_attach(drm, imxpd->bridge);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	dpi->encoder.bridge->encoder = &dpi->encoder;
> -	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  
>  	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>  
> -	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +	dpi->bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->encoder.bridge)
> +	if (!dpi->bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>  	.get_modes = mtk_dsi_connector_get_modes,
>  };
>  
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -				 struct drm_encoder *encoder)
> -{
> -	int ret;
> -
> -	if (!bridge)
> -		return -ENOENT;
> -
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -	ret = drm_bridge_attach(encoder->dev, bridge);
> -	if (ret) {
> -		DRM_ERROR("Failed to attach bridge to drm\n");
> -		encoder->bridge = NULL;
> -		bridge->encoder = NULL;
> -	}
> -
> -	return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>  	dsi->encoder.possible_crtcs = 1;
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
> -	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>  	if (ret) {
> +		DRM_ERROR("Failed to attach bridge to drm\n");
> +
>  		/* Otherwise create our own connector and attach to a panel */
>  		ret = mtk_dsi_create_connector(drm, dsi);
>  		if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>  
>  struct mtk_hdmi {
>  	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
>  	struct drm_connector conn;
>  	struct device *dev;
>  	struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>  		return ret;
>  	}
>  
> -	if (bridge->next) {
> -		bridge->next->encoder = bridge->encoder;
> -		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +	if (hdmi->next_bridge) {
> +		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +					bridge);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	of_node_put(ep);
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -		hdmi->bridge.next = of_drm_find_bridge(remote);
> -		if (!hdmi->bridge.next) {
> +		hdmi->next_bridge = of_drm_find_bridge(remote);
> +		if (!hdmi->next_bridge) {
>  			dev_err(dev, "Waiting for external bridge\n");
>  			of_node_put(remote);
>  			return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>  	struct drm_bridge *bridge = NULL;
>  	struct dsi_bridge *dsi_bridge;
> +	struct drm_encoder *encoder;
>  	int ret;
>  
>  	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  
>  	dsi_bridge->id = id;
>  
> +	/*
> +	 * HACK: we may not know the external DSI bridge device's mode
> +	 * flags here. We'll get to know them only when the device
> +	 * attaches to the dsi host. For now, assume the bridge supports
> +	 * DSI video mode
> +	 */
> +	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> @@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	int_bridge->next = ext_bridge;
> -	/* set the external bridge's encoder as dsi's encoder */
> -	ext_bridge->encoder = encoder;
> -
> -	drm_bridge_attach(dev, ext_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->dev, bridge);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->dev, bridge);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>  	hdmienc->renc = renc;
>  
>  	/* Link the bridge to the encoder. */
> -	bridge->encoder = encoder;
> -	encoder->bridge = bridge;
> -
> -	ret = drm_bridge_attach(rcdu->ddev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  		return err;
>  	}
>  
> -	err = drm_bridge_attach(drm_dev, bridge);
> +	err = drm_bridge_attach(encoder, bridge, NULL);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
>  	}
>  
>  	dvo->bridge = bridge;
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  	dvo->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sun4i_tcon *tcon = drv->tcon;
>  	struct drm_encoder *encoder;
> +	struct drm_bridge *bridge;
>  	struct sun4i_rgb *rgb;
>  	int ret;
>  
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	encoder = &rgb->encoder;
>  
>  	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>  		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>  		return 0;
>  	}
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> -		encoder->bridge->encoder = &rgb->encoder;
> -
> -		ret = drm_bridge_attach(drm, encoder->bridge);
> +	if (!IS_ERR(bridge)) {
> +		ret = drm_bridge_attach(encoder, bridge, NULL);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
  2016-11-29  9:30     ` Daniel Vetter
@ 2016-11-29  9:37       ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:37 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Laurent Pinchart, dri-devel, Alison Wang, Thomas Hellstrom,
	linux-renesas-soc, Alex Deucher, Daniel Vetter,
	Christian König, Ben Skeggs

Hi Daniel,

On Tuesday 29 Nov 2016 10:30:36 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:31AM +0200, Laurent Pinchart wrote:
> > <drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
> > now been split into separate files for each object type, but still
> > includes most other KMS headers to avoid breaking driver compilation.
> > 
> > As a step towards fixing that problem, remove the inclusion of
> > <drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
> > appropriate. Also remove the forward declarations of the drm_encoder and
> > drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
> > needed in the header.
> > 
> > <drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
> > forward declaration of struct drm_encoder in order to allow including it
> > as the first header in a compilation unit.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Assuming it all still compiles the various defconfigs we have (I didn't
> check that, but lgtm otherwise):

I've done my best to try and compile all affected drivers. 0day hasn't 
complained either so far, so we should be good.

> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > ---
> > 
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
> >  drivers/gpu/drm/ast/ast_drv.h               | 1 +
> >  drivers/gpu/drm/bochs/bochs.h               | 1 +
> >  drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
> >  drivers/gpu/drm/drm_connector.c             | 1 +
> >  drivers/gpu/drm/drm_crtc_helper.c           | 1 +
> >  drivers/gpu/drm/drm_edid.c                  | 1 +
> >  drivers/gpu/drm/drm_mode_config.c           | 1 +
> >  drivers/gpu/drm/drm_of.c                    | 1 +
> >  drivers/gpu/drm/drm_plane_helper.c          | 1 +
> >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
> >  drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
> >  drivers/gpu/drm/i915/intel_drv.h            | 1 +
> >  drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
> >  drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
> >  drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
> >  drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
> >  drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
> >  drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
> >  drivers/gpu/drm/tegra/drm.h                 | 1 +
> >  drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
> >  drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
> >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
> >  include/drm/drm_crtc.h                      | 3 ---
> >  include/drm/drm_encoder.h                   | 3 +++
> >  include/drm/drm_encoder_slave.h             | 1 +
> >  include/drm/drm_modeset_helper_vtables.h    | 1 +
> >  27 files changed, 30 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index
> > 1e23334b07fb..fac06064a8f5 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > @@ -32,6 +32,7 @@
> > 
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_dp_helper.h>
> >  #include <drm/drm_fixed.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> > index 908011d2c8f5..6f3b6f50cf52 100644
> > --- a/drivers/gpu/drm/ast/ast_drv.h
> > +++ b/drivers/gpu/drm/ast/ast_drv.h
> > @@ -28,6 +28,7 @@
> > 
> >  #ifndef __AST_DRV_H__
> >  #define __AST_DRV_H__
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  
> >  #include <drm/ttm/ttm_bo_api.h>
> > 
> > diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
> > index 32dfe418cc98..f626bab7f5e3 100644
> > --- a/drivers/gpu/drm/bochs/bochs.h
> > +++ b/drivers/gpu/drm/bochs/bochs.h
> > @@ -4,6 +4,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  
> >  #include <drm/drm_gem.h>
> > 
> > diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h
> > b/drivers/gpu/drm/cirrus/cirrus_drv.h index 2188d6b61b3e..b59aeef4635a
> > 100644
> > --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> > +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> > @@ -13,6 +13,7 @@
> > 
> >  #include <video/vga.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  
> >  #include <drm/ttm/ttm_bo_api.h>
> > 
> > diff --git a/drivers/gpu/drm/drm_connector.c
> > b/drivers/gpu/drm/drm_connector.c index b5c6a8ee831e..5f1e1f190d30 100644
> > --- a/drivers/gpu/drm/drm_connector.c
> > +++ b/drivers/gpu/drm/drm_connector.c
> > @@ -23,6 +23,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_connector.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include "drm_crtc_internal.h"
> >  #include "drm_internal.h"
> > 
> > diff --git a/drivers/gpu/drm/drm_crtc_helper.c
> > b/drivers/gpu/drm/drm_crtc_helper.c index 5d2cb138eba6..b3fc23313cc3
> > 100644
> > --- a/drivers/gpu/drm/drm_crtc_helper.c
> > +++ b/drivers/gpu/drm/drm_crtc_helper.c
> > @@ -36,6 +36,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fourcc.h>
> >  #include <drm/drm_crtc_helper.h>
> >  #include <drm/drm_fb_helper.h>
> > 
> > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> > index 7eec18925b70..a9e3cc3990c1 100644
> > --- a/drivers/gpu/drm/drm_edid.c
> > +++ b/drivers/gpu/drm/drm_edid.c
> > @@ -35,6 +35,7 @@
> > 
> >  #include <linux/vga_switcheroo.h>
> >  #include <drm/drmP.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_displayid.h>
> >  
> >  #define version_greater(edid, maj, min) \
> > 
> > diff --git a/drivers/gpu/drm/drm_mode_config.c
> > b/drivers/gpu/drm/drm_mode_config.c index 2735a5847ffa..09b1d8f267a6
> > 100644
> > --- a/drivers/gpu/drm/drm_mode_config.c
> > +++ b/drivers/gpu/drm/drm_mode_config.c
> > @@ -20,6 +20,7 @@
> > 
> >   * OF THIS SOFTWARE.
> >   */
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_mode_config.h>
> >  #include <drm/drmP.h>
> > 
> > diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> > index 47848ed8ca48..b5f2f0fece99 100644
> > --- a/drivers/gpu/drm/drm_of.c
> > +++ b/drivers/gpu/drm/drm_of.c
> > @@ -4,6 +4,7 @@
> > 
> >  #include <linux/of_graph.h>
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_of.h>
> >  
> >  static void drm_release_of(struct device *dev, void *data)
> > 
> > diff --git a/drivers/gpu/drm/drm_plane_helper.c
> > b/drivers/gpu/drm/drm_plane_helper.c index 7a7dddf604d7..191a5f095cf9
> > 100644
> > --- a/drivers/gpu/drm/drm_plane_helper.c
> > +++ b/drivers/gpu/drm/drm_plane_helper.c
> > @@ -29,6 +29,7 @@
> > 
> >  #include <drm/drm_rect.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_atomic_helper.h>
> >  
> >  #define SUBPIXEL_MASK 0xffff
> > 
> > diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> > b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h index
> > 3b371fe7491e..4c22edd4c746 100644
> > --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> > +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> > @@ -12,6 +12,8 @@
> > 
> >  #ifndef __FSL_DCU_DRM_DRV_H__
> >  #define __FSL_DCU_DRM_DRV_H__
> > 
> > +#include <drm/drm_encoder.h>
> > +
> > 
> >  #include "fsl_dcu_drm_crtc.h"
> >  #include "fsl_dcu_drm_output.h"
> >  #include "fsl_dcu_drm_plane.h"
> > 
> > diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h
> > b/drivers/gpu/drm/gma500/psb_intel_drv.h index 2a3b7c684db2..6a10215fc42d
> > 100644
> > --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> > +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> > @@ -23,6 +23,7 @@
> > 
> >  #include <linux/i2c-algo-bit.h>
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <linux/gpio.h>
> >  #include "gma_display.h"
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h index 398195bf6dd1..7fb8ac824b01
> > 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -32,6 +32,7 @@
> > 
> >  #include "i915_drv.h"
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/drm_dp_dual_mode_helper.h>
> >  #include <drm/drm_dp_mst_helper.h>
> > 
> > diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h
> > b/drivers/gpu/drm/mgag200/mgag200_drv.h index 3e02ac20777c..87e0934773de
> > 100644
> > --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> > +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> > @@ -15,6 +15,7 @@
> > 
> >  #include <video/vga.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/ttm/ttm_bo_api.h>
> >  #include <drm/ttm/ttm_bo_driver.h>
> > 
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h
> > b/drivers/gpu/drm/nouveau/nouveau_connector.h index
> > 096983c42a1f..a4d1a059bd3d 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
> > +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
> > @@ -30,6 +30,7 @@
> > 
> >  #include <nvif/notify.h>
> >  
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_dp_helper.h>
> >  #include "nouveau_crtc.h"
> > 
> > diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> > index 84995ebc6ffc..56df6b4ddbab 100644
> > --- a/drivers/gpu/drm/qxl/qxl_drv.h
> > +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> > @@ -43,6 +43,7 @@
> > 
> >  #include <ttm/ttm_placement.h>
> >  #include <ttm/ttm_module.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_gem.h>
> >  
> >  /* just for ttm_validate_buffer */
> > 
> > diff --git a/drivers/gpu/drm/radeon/radeon_mode.h
> > b/drivers/gpu/drm/radeon/radeon_mode.h index bb75201a24ba..7ceea8ffd0db
> > 100644
> > --- a/drivers/gpu/drm/radeon/radeon_mode.h
> > +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> > @@ -32,6 +32,7 @@
> > 
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_dp_helper.h>
> >  #include <drm/drm_dp_mst_helper.h>
> >  #include <drm/drm_fixed.h>
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> > b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h index
> > 269fbab15907..b79b2f075a74 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> > @@ -15,6 +15,7 @@
> > 
> >  #define __RCAR_DU_ENCODER_H__
> >  
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  struct drm_panel;
> >  struct rcar_du_device;
> > 
> > diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> > b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h index
> > 38ed4ff8aaf2..818b31549ddc 100644
> > --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> > +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> > @@ -16,6 +16,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  struct backlight_device;
> >  struct shmob_drm_device;
> > 
> > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> > index 0ddcce1b420d..5205790dd679 100644
> > --- a/drivers/gpu/drm/tegra/drm.h
> > +++ b/drivers/gpu/drm/tegra/drm.h
> > @@ -17,6 +17,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc_helper.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/drm_fixed.h>
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index fef172804345..f89a95cb98cf 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -9,6 +9,8 @@
> > 
> >  #include "drmP.h"
> >  #include "drm_gem_cma_helper.h"
> > 
> > +#include <drm/drm_encoder.h>
> > +
> > 
> >  struct vc4_dev {
> >  
> >  	struct drm_device *dev;
> > 
> > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h
> > b/drivers/gpu/drm/virtio/virtgpu_drv.h index ec1ebdcfe80b..475ac93848c3
> > 100644
> > --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> > @@ -35,6 +35,7 @@
> > 
> >  #include <drm/drm_gem.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <ttm/ttm_bo_api.h>
> >  #include <ttm/ttm_bo_driver.h>
> >  #include <ttm/ttm_placement.h>
> > 
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index ff4803c107bc..5ee25fb07ea2
> > 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > @@ -30,6 +30,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include "vmwgfx_drv.h"
> >  
> >  /**
> > 
> > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> > index 946672f97e1e..9ef0ac0ce69f 100644
> > --- a/include/drm/drm_crtc.h
> > +++ b/include/drm/drm_crtc.h
> > @@ -39,7 +39,6 @@
> > 
> >  #include <drm/drm_framebuffer.h>
> >  #include <drm/drm_modes.h>
> >  #include <drm/drm_connector.h>
> > 
> > -#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_property.h>
> >  #include <drm/drm_bridge.h>
> >  #include <drm/drm_edid.h>
> > 
> > @@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
> > 
> >  }
> >  
> >  struct drm_crtc;
> > 
> > -struct drm_encoder;
> > 
> >  struct drm_pending_vblank_event;
> >  struct drm_plane;
> >  struct drm_bridge;
> >  struct drm_atomic_state;
> >  
> >  struct drm_crtc_helper_funcs;
> > 
> > -struct drm_encoder_helper_funcs;
> > 
> >  struct drm_plane_helper_funcs;
> >  
> >  /**
> > 
> > diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> > index c7438ff0d609..cec6ac45c6cc 100644
> > --- a/include/drm/drm_encoder.h
> > +++ b/include/drm/drm_encoder.h
> > @@ -25,8 +25,11 @@
> > 
> >  #include <linux/list.h>
> >  #include <linux/ctype.h>
> > 
> > +#include <drm/drm_mode.h>
> > 
> >  #include <drm/drm_mode_object.h>
> > 
> > +struct drm_encoder;
> > +
> > 
> >  /**
> >  
> >   * struct drm_encoder_funcs - encoder controls
> >   *
> > 
> > diff --git a/include/drm/drm_encoder_slave.h
> > b/include/drm/drm_encoder_slave.h index 82cdf611393d..1107b4b1c599 100644
> > --- a/include/drm/drm_encoder_slave.h
> > +++ b/include/drm/drm_encoder_slave.h
> > @@ -29,6 +29,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  /**
> >  
> >   * struct drm_encoder_slave_funcs - Entry points exposed by a slave
> >   encoder driver> 
> > diff --git a/include/drm/drm_modeset_helper_vtables.h
> > b/include/drm/drm_modeset_helper_vtables.h index
> > 72478cf82147..21d9823d4872 100644
> > --- a/include/drm/drm_modeset_helper_vtables.h
> > +++ b/include/drm/drm_modeset_helper_vtables.h
> > @@ -30,6 +30,7 @@
> > 
> >  #define __DRM_MODESET_HELPER_VTABLES_H__
> >  
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  /**
> >  
> >   * DOC: overview

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
@ 2016-11-29  9:37       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:37 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Thomas Hellstrom, Laurent Pinchart, Alison Wang, dri-devel,
	linux-renesas-soc, Ben Skeggs, Alex Deucher, Daniel Vetter,
	Christian König

Hi Daniel,

On Tuesday 29 Nov 2016 10:30:36 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:31AM +0200, Laurent Pinchart wrote:
> > <drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
> > now been split into separate files for each object type, but still
> > includes most other KMS headers to avoid breaking driver compilation.
> > 
> > As a step towards fixing that problem, remove the inclusion of
> > <drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
> > appropriate. Also remove the forward declarations of the drm_encoder and
> > drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
> > needed in the header.
> > 
> > <drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
> > forward declaration of struct drm_encoder in order to allow including it
> > as the first header in a compilation unit.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Assuming it all still compiles the various defconfigs we have (I didn't
> check that, but lgtm otherwise):

I've done my best to try and compile all affected drivers. 0day hasn't 
complained either so far, so we should be good.

> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > ---
> > 
> >  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
> >  drivers/gpu/drm/ast/ast_drv.h               | 1 +
> >  drivers/gpu/drm/bochs/bochs.h               | 1 +
> >  drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
> >  drivers/gpu/drm/drm_connector.c             | 1 +
> >  drivers/gpu/drm/drm_crtc_helper.c           | 1 +
> >  drivers/gpu/drm/drm_edid.c                  | 1 +
> >  drivers/gpu/drm/drm_mode_config.c           | 1 +
> >  drivers/gpu/drm/drm_of.c                    | 1 +
> >  drivers/gpu/drm/drm_plane_helper.c          | 1 +
> >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
> >  drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
> >  drivers/gpu/drm/i915/intel_drv.h            | 1 +
> >  drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
> >  drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
> >  drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
> >  drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
> >  drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
> >  drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
> >  drivers/gpu/drm/tegra/drm.h                 | 1 +
> >  drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
> >  drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
> >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
> >  include/drm/drm_crtc.h                      | 3 ---
> >  include/drm/drm_encoder.h                   | 3 +++
> >  include/drm/drm_encoder_slave.h             | 1 +
> >  include/drm/drm_modeset_helper_vtables.h    | 1 +
> >  27 files changed, 30 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index
> > 1e23334b07fb..fac06064a8f5 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> > @@ -32,6 +32,7 @@
> > 
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_dp_helper.h>
> >  #include <drm/drm_fixed.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> > index 908011d2c8f5..6f3b6f50cf52 100644
> > --- a/drivers/gpu/drm/ast/ast_drv.h
> > +++ b/drivers/gpu/drm/ast/ast_drv.h
> > @@ -28,6 +28,7 @@
> > 
> >  #ifndef __AST_DRV_H__
> >  #define __AST_DRV_H__
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  
> >  #include <drm/ttm/ttm_bo_api.h>
> > 
> > diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
> > index 32dfe418cc98..f626bab7f5e3 100644
> > --- a/drivers/gpu/drm/bochs/bochs.h
> > +++ b/drivers/gpu/drm/bochs/bochs.h
> > @@ -4,6 +4,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  
> >  #include <drm/drm_gem.h>
> > 
> > diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h
> > b/drivers/gpu/drm/cirrus/cirrus_drv.h index 2188d6b61b3e..b59aeef4635a
> > 100644
> > --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> > +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> > @@ -13,6 +13,7 @@
> > 
> >  #include <video/vga.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  
> >  #include <drm/ttm/ttm_bo_api.h>
> > 
> > diff --git a/drivers/gpu/drm/drm_connector.c
> > b/drivers/gpu/drm/drm_connector.c index b5c6a8ee831e..5f1e1f190d30 100644
> > --- a/drivers/gpu/drm/drm_connector.c
> > +++ b/drivers/gpu/drm/drm_connector.c
> > @@ -23,6 +23,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_connector.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include "drm_crtc_internal.h"
> >  #include "drm_internal.h"
> > 
> > diff --git a/drivers/gpu/drm/drm_crtc_helper.c
> > b/drivers/gpu/drm/drm_crtc_helper.c index 5d2cb138eba6..b3fc23313cc3
> > 100644
> > --- a/drivers/gpu/drm/drm_crtc_helper.c
> > +++ b/drivers/gpu/drm/drm_crtc_helper.c
> > @@ -36,6 +36,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fourcc.h>
> >  #include <drm/drm_crtc_helper.h>
> >  #include <drm/drm_fb_helper.h>
> > 
> > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> > index 7eec18925b70..a9e3cc3990c1 100644
> > --- a/drivers/gpu/drm/drm_edid.c
> > +++ b/drivers/gpu/drm/drm_edid.c
> > @@ -35,6 +35,7 @@
> > 
> >  #include <linux/vga_switcheroo.h>
> >  #include <drm/drmP.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_displayid.h>
> >  
> >  #define version_greater(edid, maj, min) \
> > 
> > diff --git a/drivers/gpu/drm/drm_mode_config.c
> > b/drivers/gpu/drm/drm_mode_config.c index 2735a5847ffa..09b1d8f267a6
> > 100644
> > --- a/drivers/gpu/drm/drm_mode_config.c
> > +++ b/drivers/gpu/drm/drm_mode_config.c
> > @@ -20,6 +20,7 @@
> > 
> >   * OF THIS SOFTWARE.
> >   */
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_mode_config.h>
> >  #include <drm/drmP.h>
> > 
> > diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> > index 47848ed8ca48..b5f2f0fece99 100644
> > --- a/drivers/gpu/drm/drm_of.c
> > +++ b/drivers/gpu/drm/drm_of.c
> > @@ -4,6 +4,7 @@
> > 
> >  #include <linux/of_graph.h>
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_of.h>
> >  
> >  static void drm_release_of(struct device *dev, void *data)
> > 
> > diff --git a/drivers/gpu/drm/drm_plane_helper.c
> > b/drivers/gpu/drm/drm_plane_helper.c index 7a7dddf604d7..191a5f095cf9
> > 100644
> > --- a/drivers/gpu/drm/drm_plane_helper.c
> > +++ b/drivers/gpu/drm/drm_plane_helper.c
> > @@ -29,6 +29,7 @@
> > 
> >  #include <drm/drm_rect.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_atomic_helper.h>
> >  
> >  #define SUBPIXEL_MASK 0xffff
> > 
> > diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> > b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h index
> > 3b371fe7491e..4c22edd4c746 100644
> > --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> > +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> > @@ -12,6 +12,8 @@
> > 
> >  #ifndef __FSL_DCU_DRM_DRV_H__
> >  #define __FSL_DCU_DRM_DRV_H__
> > 
> > +#include <drm/drm_encoder.h>
> > +
> > 
> >  #include "fsl_dcu_drm_crtc.h"
> >  #include "fsl_dcu_drm_output.h"
> >  #include "fsl_dcu_drm_plane.h"
> > 
> > diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h
> > b/drivers/gpu/drm/gma500/psb_intel_drv.h index 2a3b7c684db2..6a10215fc42d
> > 100644
> > --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> > +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> > @@ -23,6 +23,7 @@
> > 
> >  #include <linux/i2c-algo-bit.h>
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <linux/gpio.h>
> >  #include "gma_display.h"
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h index 398195bf6dd1..7fb8ac824b01
> > 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -32,6 +32,7 @@
> > 
> >  #include "i915_drv.h"
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/drm_dp_dual_mode_helper.h>
> >  #include <drm/drm_dp_mst_helper.h>
> > 
> > diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h
> > b/drivers/gpu/drm/mgag200/mgag200_drv.h index 3e02ac20777c..87e0934773de
> > 100644
> > --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> > +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> > @@ -15,6 +15,7 @@
> > 
> >  #include <video/vga.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/ttm/ttm_bo_api.h>
> >  #include <drm/ttm/ttm_bo_driver.h>
> > 
> > diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h
> > b/drivers/gpu/drm/nouveau/nouveau_connector.h index
> > 096983c42a1f..a4d1a059bd3d 100644
> > --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
> > +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
> > @@ -30,6 +30,7 @@
> > 
> >  #include <nvif/notify.h>
> >  
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_dp_helper.h>
> >  #include "nouveau_crtc.h"
> > 
> > diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> > index 84995ebc6ffc..56df6b4ddbab 100644
> > --- a/drivers/gpu/drm/qxl/qxl_drv.h
> > +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> > @@ -43,6 +43,7 @@
> > 
> >  #include <ttm/ttm_placement.h>
> >  #include <ttm/ttm_module.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_gem.h>
> >  
> >  /* just for ttm_validate_buffer */
> > 
> > diff --git a/drivers/gpu/drm/radeon/radeon_mode.h
> > b/drivers/gpu/drm/radeon/radeon_mode.h index bb75201a24ba..7ceea8ffd0db
> > 100644
> > --- a/drivers/gpu/drm/radeon/radeon_mode.h
> > +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> > @@ -32,6 +32,7 @@
> > 
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_dp_helper.h>
> >  #include <drm/drm_dp_mst_helper.h>
> >  #include <drm/drm_fixed.h>
> > 
> > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> > b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h index
> > 269fbab15907..b79b2f075a74 100644
> > --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> > +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> > @@ -15,6 +15,7 @@
> > 
> >  #define __RCAR_DU_ENCODER_H__
> >  
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  struct drm_panel;
> >  struct rcar_du_device;
> > 
> > diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> > b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h index
> > 38ed4ff8aaf2..818b31549ddc 100644
> > --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> > +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> > @@ -16,6 +16,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  struct backlight_device;
> >  struct shmob_drm_device;
> > 
> > diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> > index 0ddcce1b420d..5205790dd679 100644
> > --- a/drivers/gpu/drm/tegra/drm.h
> > +++ b/drivers/gpu/drm/tegra/drm.h
> > @@ -17,6 +17,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc_helper.h>
> >  #include <drm/drm_edid.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_fb_helper.h>
> >  #include <drm/drm_fixed.h>
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index fef172804345..f89a95cb98cf 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -9,6 +9,8 @@
> > 
> >  #include "drmP.h"
> >  #include "drm_gem_cma_helper.h"
> > 
> > +#include <drm/drm_encoder.h>
> > +
> > 
> >  struct vc4_dev {
> >  
> >  	struct drm_device *dev;
> > 
> > diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h
> > b/drivers/gpu/drm/virtio/virtgpu_drv.h index ec1ebdcfe80b..475ac93848c3
> > 100644
> > --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> > +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> > @@ -35,6 +35,7 @@
> > 
> >  #include <drm/drm_gem.h>
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include <ttm/ttm_bo_api.h>
> >  #include <ttm/ttm_bo_driver.h>
> >  #include <ttm/ttm_placement.h>
> > 
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index ff4803c107bc..5ee25fb07ea2
> > 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> > @@ -30,6 +30,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc_helper.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  #include "vmwgfx_drv.h"
> >  
> >  /**
> > 
> > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> > index 946672f97e1e..9ef0ac0ce69f 100644
> > --- a/include/drm/drm_crtc.h
> > +++ b/include/drm/drm_crtc.h
> > @@ -39,7 +39,6 @@
> > 
> >  #include <drm/drm_framebuffer.h>
> >  #include <drm/drm_modes.h>
> >  #include <drm/drm_connector.h>
> > 
> > -#include <drm/drm_encoder.h>
> > 
> >  #include <drm/drm_property.h>
> >  #include <drm/drm_bridge.h>
> >  #include <drm/drm_edid.h>
> > 
> > @@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
> > 
> >  }
> >  
> >  struct drm_crtc;
> > 
> > -struct drm_encoder;
> > 
> >  struct drm_pending_vblank_event;
> >  struct drm_plane;
> >  struct drm_bridge;
> >  struct drm_atomic_state;
> >  
> >  struct drm_crtc_helper_funcs;
> > 
> > -struct drm_encoder_helper_funcs;
> > 
> >  struct drm_plane_helper_funcs;
> >  
> >  /**
> > 
> > diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> > index c7438ff0d609..cec6ac45c6cc 100644
> > --- a/include/drm/drm_encoder.h
> > +++ b/include/drm/drm_encoder.h
> > @@ -25,8 +25,11 @@
> > 
> >  #include <linux/list.h>
> >  #include <linux/ctype.h>
> > 
> > +#include <drm/drm_mode.h>
> > 
> >  #include <drm/drm_mode_object.h>
> > 
> > +struct drm_encoder;
> > +
> > 
> >  /**
> >  
> >   * struct drm_encoder_funcs - encoder controls
> >   *
> > 
> > diff --git a/include/drm/drm_encoder_slave.h
> > b/include/drm/drm_encoder_slave.h index 82cdf611393d..1107b4b1c599 100644
> > --- a/include/drm/drm_encoder_slave.h
> > +++ b/include/drm/drm_encoder_slave.h
> > @@ -29,6 +29,7 @@
> > 
> >  #include <drm/drmP.h>
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  /**
> >  
> >   * struct drm_encoder_slave_funcs - Entry points exposed by a slave
> >   encoder driver> 
> > diff --git a/include/drm/drm_modeset_helper_vtables.h
> > b/include/drm/drm_modeset_helper_vtables.h index
> > 72478cf82147..21d9823d4872 100644
> > --- a/include/drm/drm_modeset_helper_vtables.h
> > +++ b/include/drm/drm_modeset_helper_vtables.h
> > @@ -30,6 +30,7 @@
> > 
> >  #define __DRM_MODESET_HELPER_VTABLES_H__
> >  
> >  #include <drm/drm_crtc.h>
> > 
> > +#include <drm/drm_encoder.h>
> > 
> >  /**
> >  
> >   * DOC: overview

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:35     ` Daniel Vetter
  (?)
@ 2016-11-29  9:43     ` Laurent Pinchart
  2016-11-29 10:05         ` Daniel Vetter
  -1 siblings, 1 reply; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:43 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Laurent Pinchart, dri-devel, Alison Wang, Jingoo Han,
	Seung-Woo Kim, Xinwei Kong, linux-renesas-soc, Kyungmin Park,
	Xinliang Liu, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou

Hi Daniel,

On Tuesday 29 Nov 2016 10:35:24 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> > Instead of linking encoders and bridges in every driver (and getting it
> > wrong half of the time, as many drivers forget to set the drm_bridge
> > encoder pointer), do so in core code. The drm_bridge_attach() function
> > needs the encoder and optional previous bridge to perform that task,
> > update all the callers.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >  drivers/gpu/drm/drm_bridge.c                       | 46 +++++++++++++----
> >  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >  include/drm/drm_bridge.h                           |  3 +-
> >  23 files changed, 83 insertions(+), 103 deletions(-)

[snip]

> > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > index 0ee052b7c21a..850bd6509ef1 100644
> > --- a/drivers/gpu/drm/drm_bridge.c
> > +++ b/drivers/gpu/drm/drm_bridge.c
> > @@ -26,6 +26,7 @@
> > 
> >  #include <linux/mutex.h>
> >  #include <drm/drm_bridge.h>
> > +#include <drm/drm_encoder.h>
> > 
> >  /**
> >   * DOC: overview
> > @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> >  EXPORT_SYMBOL(drm_bridge_remove);
> >  
> >  /**
> > - * drm_bridge_attach - associate given bridge to our DRM device
> > + * drm_bridge_attach - attach the bridge to an encoder's chain
> >   *
> > - * @dev: DRM device
> > - * @bridge: bridge control structure
> > + * @encoder: DRM encoder
> > + * @bridge: bridge to attach
> > + * @previous: previous bridge in the chain (optional)
> >   *
> > - * Called by a kms driver to link one of our encoder/bridge to the given
> > - * bridge.
> > + * Called by a kms driver to link the bridge to an encoder's chain. The
> > previous
> > + * argument specifies the previous bridge in the chain. If NULL, the
> > bridge is
> > + * linked directly at the encoder's output. Otherwise it is linked at the
> > + * previous bridge's output.
> >   *
> > - * Note that setting up links between the bridge and our encoder/bridge
> > - * objects needs to be handled by the kms driver itself.
> > + * If non-NULL the previous bridge must be already attached by a call to
> > this
> > + * function.
> >   *
> >   * RETURNS:
> >   * Zero on success, error code on failure
> >   */
> > -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> > +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> > *bridge,
> > +		      struct drm_bridge *previous)
> >  {
> > -	if (!dev || !bridge)
> > +	int ret;
> > +
> > +	if (!encoder || !bridge)
> > +		return -EINVAL;
> > +
> > +	if (previous && (!previous->dev || previous->encoder != encoder))
> >  		return -EINVAL;
> 
> Not sure we want to allow setting both encoder and bridge for chaining.
> I'd kinda expect that for chained use-case the bridge doesn't care that
> much who started the chain. And if not we can always create a helper to
> look up the drm_encoder.

As bridge drivers currently create connectors (I'd like to change that at some 
point, but one thing at a time) they need to call 
drm_mode_connector_attach_encoder() and thus need to have access to the 
drm_encoder object at the beginning of the chain. The drm_bridge structure has 
an encoder field, it seems to me that the easiest is to always populate it, 
regardless of the position of the bridge in the chain.

> Also, should we convert these to WARN_ON, they're kinda glaring driver (or
> well DT) bugs?

Yes, that seems like a good idea. I can add a patch on top of this one to 
convert the checks to WARN_ON, as I'd rather separate that change from the API 
change.

> Otherwise looks all reasonable to me, but deferring to Archit for final
> review.
> 
> >  	if (bridge->dev)
> >  		return -EBUSY;
> > 
> > -	bridge->dev = dev;
> > +	bridge->dev = encoder->dev;
> > +	bridge->encoder = encoder;
> > +
> > +	if (bridge->funcs->attach) {
> > +		ret = bridge->funcs->attach(bridge);
> > +		if (ret < 0) {
> > +			bridge->dev = NULL;
> > +			bridge->encoder = NULL;
> > +			return ret;
> > +		}
> > +	}
> > 
> > -	if (bridge->funcs->attach)
> > -		return bridge->funcs->attach(bridge);
> > +	if (previous)
> > +		previous->next = bridge;
> > +	else
> > +		encoder->bridge = bridge;
> > 
> >  	return 0;
> >  }
> > 

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-29  9:48     ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:48 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 11:04:34AM +0200, Laurent Pinchart wrote:
> Most drivers that use bridges forgot to detach them at cleanup time.
> Instead of fixing them one by one, detach the bridge in the core
> drm_encoder_cleanup() function.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/drm_encoder.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index 5c067719164d..9c1f99646e0d 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
>  	 * the indices on the drm_encoder after us in the encoder_list.
>  	 */
>  
> +	if (encoder->bridge)
> +		drm_bridge_detach(encoder->bridge);

Means we bake in drm_bridge much more as a core thing, but I guess that's
ok.

But there's 3 callers of drm_bridge_detach outside of the drm core, can't
we remove them and drop the EXPORT_SYMBOL for drm_bridge_detach? What's
it still needed for?

I think that cleanup should done in this patch here - drm_bridge_detach
WARN_ONs if the bridge is already detached ...
-Daniel

> +
>  	drm_modeset_lock_all(dev);
>  	drm_mode_object_unregister(dev, &encoder->base);
>  	kfree(encoder->name);
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
@ 2016-11-29  9:48     ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:48 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel

On Tue, Nov 29, 2016 at 11:04:34AM +0200, Laurent Pinchart wrote:
> Most drivers that use bridges forgot to detach them at cleanup time.
> Instead of fixing them one by one, detach the bridge in the core
> drm_encoder_cleanup() function.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/drm_encoder.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index 5c067719164d..9c1f99646e0d 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
>  	 * the indices on the drm_encoder after us in the encoder_list.
>  	 */
>  
> +	if (encoder->bridge)
> +		drm_bridge_detach(encoder->bridge);

Means we bake in drm_bridge much more as a core thing, but I guess that's
ok.

But there's 3 callers of drm_bridge_detach outside of the drm core, can't
we remove them and drop the EXPORT_SYMBOL for drm_bridge_detach? What's
it still needed for?

I think that cleanup should done in this patch here - drm_bridge_detach
WARN_ONs if the bridge is already detached ...
-Daniel

> +
>  	drm_modeset_lock_all(dev);
>  	drm_mode_object_unregister(dev, &encoder->base);
>  	kfree(encoder->name);
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 07/13] drm: bridge: vga-dac: Add adi,adv7123 compatible string
  2016-11-29  9:04   ` [PATCH v3 07/13] drm: bridge: vga-dac: Add adi, adv7123 " Laurent Pinchart
@ 2016-11-29  9:50     ` Maxime Ripard
  -1 siblings, 0 replies; 100+ messages in thread
From: Maxime Ripard @ 2016-11-29  9:50 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc, Archit Taneja

[-- Attachment #1: Type: text/plain, Size: 908 bytes --]

On Tue, Nov 29, 2016 at 11:04:37AM +0200, Laurent Pinchart wrote:
> The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
> controlled through a power save pin, and requires a power supply.
> However, on most boards where the device is used neither the power save
> signal nor the power supply are controllable.
> 
> To avoid developing a separate device-specific driver add an
> "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
> allow supporting most ADV7123-based boards easily, while allowing future
> development of an adv7123 driver when needed without breaking backward
> compatibility.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 07/13] drm: bridge: vga-dac: Add adi,adv7123 compatible string
@ 2016-11-29  9:50     ` Maxime Ripard
  0 siblings, 0 replies; 100+ messages in thread
From: Maxime Ripard @ 2016-11-29  9:50 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 908 bytes --]

On Tue, Nov 29, 2016 at 11:04:37AM +0200, Laurent Pinchart wrote:
> The ADV7123 is a transparent VGA DAC. Unlike dumb VGA DACs it can be
> controlled through a power save pin, and requires a power supply.
> However, on most boards where the device is used neither the power save
> signal nor the power supply are controllable.
> 
> To avoid developing a separate device-specific driver add an
> "adi,adv7123" compatible entry to the dumb-vga-dac driver. This will
> allow supporting most ADV7123-based boards easily, while allowing future
> development of an adv7123 driver when needed without breaking backward
> compatibility.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2016-11-29  9:04 ` [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver Laurent Pinchart
@ 2016-11-29  9:54   ` Daniel Vetter
  2016-11-29 20:57       ` Laurent Pinchart
  0 siblings, 1 reply; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:54 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> The LVDS encoder driver is a DRM bridge driver that supports the
> parallel to LVDS encoders that don't require any configuration. The
> driver thus doesn't interact with the device, but creates an LVDS
> connector for the panel and exposes its size and timing based on
> information retrieved from DT.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Since it's 100% dummy, why put LVDS into the name? This little thing here
could be our generic "wrap drm_panel and attach it to a chain" helper. So
what about calling this _The_ drm_panel_bridge, and also linking it into
docs to feature it a bit more prominently.

I came up with this because I spotted some refactoring belows for building
this helper, until I realized that this driver _is_ the helper I think we
want ;-) Only thing missing is an exported function to instantiate a
bridge with just a drm_panel as the parameter. And putting it into the
drm_kms_helper.ko module.

> +static enum drm_connector_status
> +lvds_connector_detect(struct drm_connector *connector, bool force)
> +{
> +	return connector_status_connected;
> +}

We have piles of this exact dummy callback all over, maybe make it the
default and rip them all out?
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29  9:04 ` [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure Laurent Pinchart
@ 2016-11-29  9:56   ` Daniel Vetter
  2016-11-29  9:58       ` Laurent Pinchart
  0 siblings, 1 reply; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29  9:56 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> The drm_bridge object models on- or off-chip hardware encoders and
> provide an abstract control API to display drivers. In order to help
> display drivers creating the right kind of drm_encoder object, expose
> the type of the hardware encoder associated with each bridge.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
one iota about the encoder type.
-Daniel

> ---
> Changes since v1:
> 
> - Clarify documentation
> ---
>  include/drm/drm_bridge.h | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 94e5ee96b3b5..0643b6ce27de 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -194,6 +194,14 @@ struct drm_bridge {
>  #endif
>  	struct list_head list;
>  
> +	/**
> +	 * @encoder_type:
> +	 *
> +	 * Type of the hardware encoder modeled by the bridge as one of the
> +	 * DRM_MODE_ENCODER_* types. For the last bridge in the chain this will
> +	 * usually be identical to the bridge's &drm_encoder encoder_type.
> +	 */
> +	int encoder_type;
>  	const struct drm_bridge_funcs *funcs;
>  	void *driver_private;
>  };
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29  9:56   ` Daniel Vetter
@ 2016-11-29  9:58       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:58 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> > The drm_bridge object models on- or off-chip hardware encoders and
> > provide an abstract control API to display drivers. In order to help
> > display drivers creating the right kind of drm_encoder object, expose
> > the type of the hardware encoder associated with each bridge.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
> one iota about the encoder type.

It's exposed to userspace though, are you 100% sure we won't break anything ?

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
@ 2016-11-29  9:58       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29  9:58 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> > The drm_bridge object models on- or off-chip hardware encoders and
> > provide an abstract control API to display drivers. In order to help
> > display drivers creating the right kind of drm_encoder object, expose
> > the type of the hardware encoder associated with each bridge.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
> one iota about the encoder type.

It's exposed to userspace though, are you 100% sure we won't break anything ?

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:43     ` Laurent Pinchart
@ 2016-11-29 10:05         ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 10:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Vetter, Laurent Pinchart, dri-devel, Alison Wang,
	Jingoo Han, Seung-Woo Kim, Xinwei Kong, linux-renesas-soc,
	Kyungmin Park, Xinliang Liu, Chen Feng, Rongrong Zou,
	Maxime Ripard, Vincent Abriou

On Tue, Nov 29, 2016 at 11:43:19AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tuesday 29 Nov 2016 10:35:24 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> > > Instead of linking encoders and bridges in every driver (and getting it
> > > wrong half of the time, as many drivers forget to set the drm_bridge
> > > encoder pointer), do so in core code. The drm_bridge_attach() function
> > > needs the encoder and optional previous bridge to perform that task,
> > > update all the callers.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> > >  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> > >  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> > >  drivers/gpu/drm/drm_bridge.c                       | 46 +++++++++++++----
> > >  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> > >  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> > >  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> > >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> > >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> > >  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> > >  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> > >  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> > >  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> > >  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> > >  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> > >  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> > >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> > >  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> > >  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> > >  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> > >  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> > >  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> > >  include/drm/drm_bridge.h                           |  3 +-
> > >  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> [snip]
> 
> > > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > > index 0ee052b7c21a..850bd6509ef1 100644
> > > --- a/drivers/gpu/drm/drm_bridge.c
> > > +++ b/drivers/gpu/drm/drm_bridge.c
> > > @@ -26,6 +26,7 @@
> > > 
> > >  #include <linux/mutex.h>
> > >  #include <drm/drm_bridge.h>
> > > +#include <drm/drm_encoder.h>
> > > 
> > >  /**
> > >   * DOC: overview
> > > @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> > >  EXPORT_SYMBOL(drm_bridge_remove);
> > >  
> > >  /**
> > > - * drm_bridge_attach - associate given bridge to our DRM device
> > > + * drm_bridge_attach - attach the bridge to an encoder's chain
> > >   *
> > > - * @dev: DRM device
> > > - * @bridge: bridge control structure
> > > + * @encoder: DRM encoder
> > > + * @bridge: bridge to attach
> > > + * @previous: previous bridge in the chain (optional)
> > >   *
> > > - * Called by a kms driver to link one of our encoder/bridge to the given
> > > - * bridge.
> > > + * Called by a kms driver to link the bridge to an encoder's chain. The
> > > previous
> > > + * argument specifies the previous bridge in the chain. If NULL, the
> > > bridge is
> > > + * linked directly at the encoder's output. Otherwise it is linked at the
> > > + * previous bridge's output.
> > >   *
> > > - * Note that setting up links between the bridge and our encoder/bridge
> > > - * objects needs to be handled by the kms driver itself.
> > > + * If non-NULL the previous bridge must be already attached by a call to
> > > this
> > > + * function.
> > >   *
> > >   * RETURNS:
> > >   * Zero on success, error code on failure
> > >   */
> > > -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> > > +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> > > *bridge,
> > > +		      struct drm_bridge *previous)
> > >  {
> > > -	if (!dev || !bridge)
> > > +	int ret;
> > > +
> > > +	if (!encoder || !bridge)
> > > +		return -EINVAL;
> > > +
> > > +	if (previous && (!previous->dev || previous->encoder != encoder))
> > >  		return -EINVAL;
> > 
> > Not sure we want to allow setting both encoder and bridge for chaining.
> > I'd kinda expect that for chained use-case the bridge doesn't care that
> > much who started the chain. And if not we can always create a helper to
> > look up the drm_encoder.
> 
> As bridge drivers currently create connectors (I'd like to change that at some 
> point, but one thing at a time) they need to call 
> drm_mode_connector_attach_encoder() and thus need to have access to the 
> drm_encoder object at the beginning of the chain. The drm_bridge structure has 
> an encoder field, it seems to me that the easiest is to always populate it, 
> regardless of the position of the bridge in the chain.

I mean the function inteface, not what we fill out in the drm_bridge
struct. I.e. instead of expecting callers to give you the encoder for
chained bridges, look it up yourself:

	bridge->encoder = previous : previous->encoder ? encoder;

Or something  like that. Just feels confusing to connect a bridge to both
a bridge _and_ the first encoder.

Wrt creating the connector: Some helpers to make that easier could be
useful, and probably we need a separate ->register callback. That's needed
for proper demidlayered init/teardown sequence anyway, and then the
drm_bridge.c code make sure to only call ->register for the very last
bridge. Other bridges could still create ther connectors (less conditions
in the code), as long as they don't register them no one will ever see
them ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29 10:05         ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 10:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Xinliang Liu, Laurent Pinchart, Alison Wang, Jingoo Han,
	Seung-Woo Kim, Kyungmin Park, dri-devel, linux-renesas-soc,
	Xinwei Kong, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou

On Tue, Nov 29, 2016 at 11:43:19AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tuesday 29 Nov 2016 10:35:24 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> > > Instead of linking encoders and bridges in every driver (and getting it
> > > wrong half of the time, as many drivers forget to set the drm_bridge
> > > encoder pointer), do so in core code. The drm_bridge_attach() function
> > > needs the encoder and optional previous bridge to perform that task,
> > > update all the callers.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> > >  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> > >  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> > >  drivers/gpu/drm/drm_bridge.c                       | 46 +++++++++++++----
> > >  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> > >  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> > >  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> > >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> > >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> > >  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> > >  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> > >  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> > >  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> > >  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> > >  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> > >  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> > >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> > >  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> > >  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> > >  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> > >  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> > >  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> > >  include/drm/drm_bridge.h                           |  3 +-
> > >  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> [snip]
> 
> > > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > > index 0ee052b7c21a..850bd6509ef1 100644
> > > --- a/drivers/gpu/drm/drm_bridge.c
> > > +++ b/drivers/gpu/drm/drm_bridge.c
> > > @@ -26,6 +26,7 @@
> > > 
> > >  #include <linux/mutex.h>
> > >  #include <drm/drm_bridge.h>
> > > +#include <drm/drm_encoder.h>
> > > 
> > >  /**
> > >   * DOC: overview
> > > @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> > >  EXPORT_SYMBOL(drm_bridge_remove);
> > >  
> > >  /**
> > > - * drm_bridge_attach - associate given bridge to our DRM device
> > > + * drm_bridge_attach - attach the bridge to an encoder's chain
> > >   *
> > > - * @dev: DRM device
> > > - * @bridge: bridge control structure
> > > + * @encoder: DRM encoder
> > > + * @bridge: bridge to attach
> > > + * @previous: previous bridge in the chain (optional)
> > >   *
> > > - * Called by a kms driver to link one of our encoder/bridge to the given
> > > - * bridge.
> > > + * Called by a kms driver to link the bridge to an encoder's chain. The
> > > previous
> > > + * argument specifies the previous bridge in the chain. If NULL, the
> > > bridge is
> > > + * linked directly at the encoder's output. Otherwise it is linked at the
> > > + * previous bridge's output.
> > >   *
> > > - * Note that setting up links between the bridge and our encoder/bridge
> > > - * objects needs to be handled by the kms driver itself.
> > > + * If non-NULL the previous bridge must be already attached by a call to
> > > this
> > > + * function.
> > >   *
> > >   * RETURNS:
> > >   * Zero on success, error code on failure
> > >   */
> > > -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> > > +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> > > *bridge,
> > > +		      struct drm_bridge *previous)
> > >  {
> > > -	if (!dev || !bridge)
> > > +	int ret;
> > > +
> > > +	if (!encoder || !bridge)
> > > +		return -EINVAL;
> > > +
> > > +	if (previous && (!previous->dev || previous->encoder != encoder))
> > >  		return -EINVAL;
> > 
> > Not sure we want to allow setting both encoder and bridge for chaining.
> > I'd kinda expect that for chained use-case the bridge doesn't care that
> > much who started the chain. And if not we can always create a helper to
> > look up the drm_encoder.
> 
> As bridge drivers currently create connectors (I'd like to change that at some 
> point, but one thing at a time) they need to call 
> drm_mode_connector_attach_encoder() and thus need to have access to the 
> drm_encoder object at the beginning of the chain. The drm_bridge structure has 
> an encoder field, it seems to me that the easiest is to always populate it, 
> regardless of the position of the bridge in the chain.

I mean the function inteface, not what we fill out in the drm_bridge
struct. I.e. instead of expecting callers to give you the encoder for
chained bridges, look it up yourself:

	bridge->encoder = previous : previous->encoder ? encoder;

Or something  like that. Just feels confusing to connect a bridge to both
a bridge _and_ the first encoder.

Wrt creating the connector: Some helpers to make that easier could be
useful, and probably we need a separate ->register callback. That's needed
for proper demidlayered init/teardown sequence anyway, and then the
drm_bridge.c code make sure to only call ->register for the very last
bridge. Other bridges could still create ther connectors (less conditions
in the code), as long as they don't register them no one will ever see
them ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-29 10:27     ` Archit Taneja
  -1 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-29 10:27 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: linux-renesas-soc, Boris Brezillon, Jingoo Han, Inki Dae,
	Joonyoung Shim, Seung-Woo Kim, Kyungmin Park, Stefan Agner,
	Alison Wang, Xinliang Liu, Rongrong Zou, Xinwei Kong, Chen Feng,
	Philipp Zabel, CK Hu, Rob Clark, Benjamin Gaignard,
	Vincent Abriou, Maxime Ripard



On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
>
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>  	of_node_put(np);
>
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>
>  	dp->bridge = bridge;
>
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;

I think we could derive previous from the encoder itself. Something like:

	previous = encoder->bridge;
	while (previous && previous->next)
		previous = previous->next;
		
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;
>
>  	if (bridge->dev)
>  		return -EBUSY;
>
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>
>  	return 0;
>  }

<snip>

Archit

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29 10:27     ` Archit Taneja
  0 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-29 10:27 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: Alison Wang, Jingoo Han, Seung-Woo Kim, Xinwei Kong,
	linux-renesas-soc, Kyungmin Park, Xinliang Liu, Chen Feng,
	Rongrong Zou, Maxime Ripard, Vincent Abriou



On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
>
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>  	of_node_put(np);
>
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>
>  	dp->bridge = bridge;
>
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;

I think we could derive previous from the encoder itself. Something like:

	previous = encoder->bridge;
	while (previous && previous->next)
		previous = previous->next;
		
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;
>
>  	if (bridge->dev)
>  		return -EBUSY;
>
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>
>  	return 0;
>  }

<snip>

Archit

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29  9:58       ` Laurent Pinchart
@ 2016-11-29 10:27         ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 10:27 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Vetter, Laurent Pinchart, dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 11:58:44AM +0200, Laurent Pinchart wrote:
> On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> > > The drm_bridge object models on- or off-chip hardware encoders and
> > > provide an abstract control API to display drivers. In order to help
> > > display drivers creating the right kind of drm_encoder object, expose
> > > the type of the hardware encoder associated with each bridge.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
> > one iota about the encoder type.
> 
> It's exposed to userspace though, are you 100% sure we won't break anything ?

We've added DP, DSI, DPMST and DPI encoder types thus far, no one
screamed. We should be fine I think. Connector types are a bit different,
userspace (at least X) wants to pretty-print them for xrandr names.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
@ 2016-11-29 10:27         ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 10:27 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

On Tue, Nov 29, 2016 at 11:58:44AM +0200, Laurent Pinchart wrote:
> On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> > > The drm_bridge object models on- or off-chip hardware encoders and
> > > provide an abstract control API to display drivers. In order to help
> > > display drivers creating the right kind of drm_encoder object, expose
> > > the type of the hardware encoder associated with each bridge.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
> > one iota about the encoder type.
> 
> It's exposed to userspace though, are you 100% sure we won't break anything ?

We've added DP, DSI, DPMST and DPI encoder types thus far, no one
screamed. We should be fine I think. Connector types are a bit different,
userspace (at least X) wants to pretty-print them for xrandr names.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
  2016-11-29  9:04   ` Laurent Pinchart
  (?)
  (?)
@ 2016-11-29 10:34   ` Archit Taneja
  2016-11-29 18:56       ` Laurent Pinchart
  -1 siblings, 1 reply; 100+ messages in thread
From: Archit Taneja @ 2016-11-29 10:34 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel; +Cc: linux-renesas-soc



On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> Most drivers that use bridges forgot to detach them at cleanup time.
> Instead of fixing them one by one, detach the bridge in the core
> drm_encoder_cleanup() function.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/drm_encoder.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> index 5c067719164d..9c1f99646e0d 100644
> --- a/drivers/gpu/drm/drm_encoder.c
> +++ b/drivers/gpu/drm/drm_encoder.c
> @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
>  	 * the indices on the drm_encoder after us in the encoder_list.
>  	 */
>
> +	if (encoder->bridge)
> +		drm_bridge_detach(encoder->bridge);

This would require the kms driver to still detach the remaining
n - 1 bridges in a possible chain. We could probably detach all of
them here, or maybe leave detaching of all to the kms driver, and just
report a warning here.

Archit

> +
>  	drm_modeset_lock_all(dev);
>  	drm_mode_object_unregister(dev, &encoder->base);
>  	kfree(encoder->name);
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-29 17:01     ` Stefan Agner
  -1 siblings, 0 replies; 100+ messages in thread
From: Stefan Agner @ 2016-11-29 17:01 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, Archit Taneja, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Alison Wang, Xinliang Liu, Rongrong Zou,
	Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu, Rob Clark,
	Benjamin Gaignard, Vincent Abriou, Maxime Ripard

On 2016-11-29 01:04, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--

For DCU

Acked-by: Stefan Agner <stefan@agner.ch>

>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct
> drm_device *dev,
>  	of_node_put(np);
>  
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct
> drm_device *drm_dev,
>  
>  	dp->bridge = bridge;
>  
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device
> *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>  
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain.
> The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;
>  
>  	if (bridge->dev)
>  		return -EBUSY;
>  
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>  
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c
> b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs
> drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	bridge->encoder = &pipe->encoder;
> -	pipe->encoder.bridge = bridge;
> -	return drm_bridge_attach(pipe->encoder.dev, bridge);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c
> b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct
> analogix_dp_plat_data *plat_data,
>  				   struct drm_connector *connector)
>  {
>  	struct exynos_dp_device *dp = to_dp(plat_data);
> -	struct drm_encoder *encoder = &dp->encoder;
>  	int ret;
>  
>  	drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct
> analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		bridge->next = dp->ptn_bridge;
> -		dp->ptn_bridge->encoder = encoder;
> -		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev,
> struct device *master,
>  	}
>  
>  	bridge = of_drm_find_bridge(dsi->bridge_node);
> -	if (bridge) {
> -		encoder->bridge = bridge;
> -		drm_bridge_attach(drm_dev, bridge);
> -	}
> +	if (bridge)
> +		drm_bridge_attach(encoder, bridge, NULL);
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct
> fsl_dcu_drm_device *fsl_dev,
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	fsl_dev->encoder.bridge = bridge;
> -	bridge->encoder = &fsl_dev->encoder;
> -
> -	return drm_bridge_attach(fsl_dev->drm, bridge);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>  
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device
> *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -
> -	ret = drm_bridge_attach(dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>  			 DRM_MODE_ENCODER_LVDS, NULL);
>  
>  	if (imx_ldb_ch->bridge) {
> -		imx_ldb_ch->bridge->encoder = encoder;
> -
> -		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +					imx_ldb_ch->bridge, NULL);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c
> b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		imxpd->bridge->encoder = encoder;
> -		encoder->bridge = imxpd->bridge;
> -		ret = drm_bridge_attach(drm, imxpd->bridge);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c
> b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct
> device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	dpi->encoder.bridge->encoder = &dpi->encoder;
> -	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  
>  	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>  
> -	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +	dpi->bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->encoder.bridge)
> +	if (!dpi->bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>  	.get_modes = mtk_dsi_connector_get_modes,
>  };
>  
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -				 struct drm_encoder *encoder)
> -{
> -	int ret;
> -
> -	if (!bridge)
> -		return -ENOENT;
> -
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -	ret = drm_bridge_attach(encoder->dev, bridge);
> -	if (ret) {
> -		DRM_ERROR("Failed to attach bridge to drm\n");
> -		encoder->bridge = NULL;
> -		bridge->encoder = NULL;
> -	}
> -
> -	return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct
> mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct
> drm_device *drm, struct mtk_dsi *dsi)
>  	dsi->encoder.possible_crtcs = 1;
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
> -	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>  	if (ret) {
> +		DRM_ERROR("Failed to attach bridge to drm\n");
> +
>  		/* Otherwise create our own connector and attach to a panel */
>  		ret = mtk_dsi_create_connector(drm, dsi);
>  		if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>  
>  struct mtk_hdmi {
>  	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
>  	struct drm_connector conn;
>  	struct device *dev;
>  	struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct
> drm_bridge *bridge)
>  		return ret;
>  	}
>  
> -	if (bridge->next) {
> -		bridge->next->encoder = bridge->encoder;
> -		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +	if (hdmi->next_bridge) {
> +		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +					bridge);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	of_node_put(ep);
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -		hdmi->bridge.next = of_drm_find_bridge(remote);
> -		if (!hdmi->bridge.next) {
> +		hdmi->next_bridge = of_drm_find_bridge(remote);
> +		if (!hdmi->next_bridge) {
>  			dev_err(dev, "Waiting for external bridge\n");
>  			of_node_put(remote);
>  			return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>  	struct drm_bridge *bridge = NULL;
>  	struct dsi_bridge *dsi_bridge;
> +	struct drm_encoder *encoder;
>  	int ret;
>  
>  	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  
>  	dsi_bridge->id = id;
>  
> +	/*
> +	 * HACK: we may not know the external DSI bridge device's mode
> +	 * flags here. We'll get to know them only when the device
> +	 * attaches to the dsi host. For now, assume the bridge supports
> +	 * DSI video mode
> +	 */
> +	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> @@ -628,11 +637,7 @@ struct drm_connector
> *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	int_bridge->next = ext_bridge;
> -	/* set the external bridge's encoder as dsi's encoder */
> -	ext_bridge->encoder = encoder;
> -
> -	drm_bridge_attach(dev, ext_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c
> b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->dev, bridge);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->dev, bridge);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>  	hdmienc->renc = renc;
>  
>  	/* Link the bridge to the encoder. */
> -	bridge->encoder = encoder;
> -	encoder->bridge = bridge;
> -
> -	ret = drm_bridge_attach(rcdu->ddev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev,
> struct device *master, void *data)
>  		return err;
>  	}
>  
> -	err = drm_bridge_attach(drm_dev, bridge);
> +	err = drm_bridge_attach(encoder, bridge, NULL);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
>  	}
>  
>  	dvo->bridge = bridge;
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  	dvo->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct
> device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev,
> struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sun4i_tcon *tcon = drv->tcon;
>  	struct drm_encoder *encoder;
> +	struct drm_bridge *bridge;
>  	struct sun4i_rgb *rgb;
>  	int ret;
>  
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	encoder = &rgb->encoder;
>  
>  	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>  		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>  		return 0;
>  	}
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> -		encoder->bridge->encoder = &rgb->encoder;
> -
> -		ret = drm_bridge_attach(drm, encoder->bridge);
> +	if (!IS_ERR(bridge)) {
> +		ret = drm_bridge_attach(encoder, bridge, NULL);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29 17:01     ` Stefan Agner
  0 siblings, 0 replies; 100+ messages in thread
From: Stefan Agner @ 2016-11-29 17:01 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, Archit Taneja, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Alison Wang, Xinliang Liu, Rongrong Zou,
	Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu, Rob Clark,
	Benjamin Gaignard, Vincent Abriou, Maxime

On 2016-11-29 01:04, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--

For DCU

Acked-by: Stefan Agner <stefan@agner.ch>

>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct
> drm_device *dev,
>  	of_node_put(np);
>  
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct
> drm_device *drm_dev,
>  
>  	dp->bridge = bridge;
>  
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device
> *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>  
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain.
> The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;
>  
>  	if (bridge->dev)
>  		return -EBUSY;
>  
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>  
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c
> b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs
> drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	bridge->encoder = &pipe->encoder;
> -	pipe->encoder.bridge = bridge;
> -	return drm_bridge_attach(pipe->encoder.dev, bridge);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c
> b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct
> analogix_dp_plat_data *plat_data,
>  				   struct drm_connector *connector)
>  {
>  	struct exynos_dp_device *dp = to_dp(plat_data);
> -	struct drm_encoder *encoder = &dp->encoder;
>  	int ret;
>  
>  	drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct
> analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		bridge->next = dp->ptn_bridge;
> -		dp->ptn_bridge->encoder = encoder;
> -		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev,
> struct device *master,
>  	}
>  
>  	bridge = of_drm_find_bridge(dsi->bridge_node);
> -	if (bridge) {
> -		encoder->bridge = bridge;
> -		drm_bridge_attach(drm_dev, bridge);
> -	}
> +	if (bridge)
> +		drm_bridge_attach(encoder, bridge, NULL);
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct
> fsl_dcu_drm_device *fsl_dev,
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	fsl_dev->encoder.bridge = bridge;
> -	bridge->encoder = &fsl_dev->encoder;
> -
> -	return drm_bridge_attach(fsl_dev->drm, bridge);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>  
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device
> *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -
> -	ret = drm_bridge_attach(dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>  			 DRM_MODE_ENCODER_LVDS, NULL);
>  
>  	if (imx_ldb_ch->bridge) {
> -		imx_ldb_ch->bridge->encoder = encoder;
> -
> -		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +					imx_ldb_ch->bridge, NULL);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c
> b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		imxpd->bridge->encoder = encoder;
> -		encoder->bridge = imxpd->bridge;
> -		ret = drm_bridge_attach(drm, imxpd->bridge);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c
> b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct
> device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	dpi->encoder.bridge->encoder = &dpi->encoder;
> -	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  
>  	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>  
> -	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +	dpi->bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->encoder.bridge)
> +	if (!dpi->bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>  	.get_modes = mtk_dsi_connector_get_modes,
>  };
>  
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -				 struct drm_encoder *encoder)
> -{
> -	int ret;
> -
> -	if (!bridge)
> -		return -ENOENT;
> -
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -	ret = drm_bridge_attach(encoder->dev, bridge);
> -	if (ret) {
> -		DRM_ERROR("Failed to attach bridge to drm\n");
> -		encoder->bridge = NULL;
> -		bridge->encoder = NULL;
> -	}
> -
> -	return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct
> mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct
> drm_device *drm, struct mtk_dsi *dsi)
>  	dsi->encoder.possible_crtcs = 1;
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
> -	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>  	if (ret) {
> +		DRM_ERROR("Failed to attach bridge to drm\n");
> +
>  		/* Otherwise create our own connector and attach to a panel */
>  		ret = mtk_dsi_create_connector(drm, dsi);
>  		if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>  
>  struct mtk_hdmi {
>  	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
>  	struct drm_connector conn;
>  	struct device *dev;
>  	struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct
> drm_bridge *bridge)
>  		return ret;
>  	}
>  
> -	if (bridge->next) {
> -		bridge->next->encoder = bridge->encoder;
> -		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +	if (hdmi->next_bridge) {
> +		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +					bridge);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	of_node_put(ep);
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -		hdmi->bridge.next = of_drm_find_bridge(remote);
> -		if (!hdmi->bridge.next) {
> +		hdmi->next_bridge = of_drm_find_bridge(remote);
> +		if (!hdmi->next_bridge) {
>  			dev_err(dev, "Waiting for external bridge\n");
>  			of_node_put(remote);
>  			return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>  	struct drm_bridge *bridge = NULL;
>  	struct dsi_bridge *dsi_bridge;
> +	struct drm_encoder *encoder;
>  	int ret;
>  
>  	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  
>  	dsi_bridge->id = id;
>  
> +	/*
> +	 * HACK: we may not know the external DSI bridge device's mode
> +	 * flags here. We'll get to know them only when the device
> +	 * attaches to the dsi host. For now, assume the bridge supports
> +	 * DSI video mode
> +	 */
> +	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> @@ -628,11 +637,7 @@ struct drm_connector
> *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	int_bridge->next = ext_bridge;
> -	/* set the external bridge's encoder as dsi's encoder */
> -	ext_bridge->encoder = encoder;
> -
> -	drm_bridge_attach(dev, ext_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c
> b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->dev, bridge);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->dev, bridge);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>  	hdmienc->renc = renc;
>  
>  	/* Link the bridge to the encoder. */
> -	bridge->encoder = encoder;
> -	encoder->bridge = bridge;
> -
> -	ret = drm_bridge_attach(rcdu->ddev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev,
> struct device *master, void *data)
>  		return err;
>  	}
>  
> -	err = drm_bridge_attach(drm_dev, bridge);
> +	err = drm_bridge_attach(encoder, bridge, NULL);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
>  	}
>  
>  	dvo->bridge = bridge;
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  	dvo->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct
> device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev,
> struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sun4i_tcon *tcon = drv->tcon;
>  	struct drm_encoder *encoder;
> +	struct drm_bridge *bridge;
>  	struct sun4i_rgb *rgb;
>  	int ret;
>  
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	encoder = &rgb->encoder;
>  
>  	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>  		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>  		return 0;
>  	}
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> -		encoder->bridge->encoder = &rgb->encoder;
> -
> -		ret = drm_bridge_attach(drm, encoder->bridge);
> +	if (!IS_ERR(bridge)) {
> +		ret = drm_bridge_attach(encoder, bridge, NULL);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29 10:27         ` Daniel Vetter
  (?)
@ 2016-11-29 17:49         ` Laurent Pinchart
  2016-11-29 20:25           ` Daniel Vetter
  -1 siblings, 1 reply; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 17:49 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Daniel,

On Tuesday 29 Nov 2016 11:27:20 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:58:44AM +0200, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> >>> The drm_bridge object models on- or off-chip hardware encoders and
> >>> provide an abstract control API to display drivers. In order to help
> >>> display drivers creating the right kind of drm_encoder object, expose
> >>> the type of the hardware encoder associated with each bridge.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >> 
> >> DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
> >> one iota about the encoder type.
> > 
> > It's exposed to userspace though, are you 100% sure we won't break
> > anything ?
>
> We've added DP, DSI, DPMST and DPI encoder types thus far, no one
> screamed.

In that case why don't we go one step further and remove the encoder type 
completely ? We can't remove the field from the API, but we can hardcode it to 
a single value.

There are however drivers that rely on the encoder type (radeon, nouveau, sti, 
amdgpu, msm and rcar-du, but I'll fix the last one) so we'd need to address 
that first. If we don't want to remove the encoder_type field from in-kernel 
structures and let drivers use it, then I don't think DRM_MODE_ENCODER_BRIDGE 
would be a good option, we should report the real type instead.

> We should be fine I think. Connector types are a bit different, userspace
> (at least X) wants to pretty-print them for xrandr names.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29 10:27     ` Archit Taneja
@ 2016-11-29 17:57       ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 17:57 UTC (permalink / raw)
  To: Archit Taneja
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard, Vincent Abriou, Maxime Ripard

Hi Archit,

On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> > Instead of linking encoders and bridges in every driver (and getting it
> > wrong half of the time, as many drivers forget to set the drm_bridge
> > encoder pointer), do so in core code. The drm_bridge_attach() function
> > needs the encoder and optional previous bridge to perform that task,
> > update all the callers.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++-----
> >  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >  include/drm/drm_bridge.h                           |  3 +-
> >  23 files changed, 83 insertions(+), 103 deletions(-)

[snip]

> > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > index 0ee052b7c21a..850bd6509ef1 100644
> > --- a/drivers/gpu/drm/drm_bridge.c
> > +++ b/drivers/gpu/drm/drm_bridge.c

[snip]

> > @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> >  EXPORT_SYMBOL(drm_bridge_remove);
> >  
> >  /**
> > - * drm_bridge_attach - associate given bridge to our DRM device
> > + * drm_bridge_attach - attach the bridge to an encoder's chain
> >   *
> > - * @dev: DRM device
> > - * @bridge: bridge control structure
> > + * @encoder: DRM encoder
> > + * @bridge: bridge to attach
> > + * @previous: previous bridge in the chain (optional)
> >   *
> > - * Called by a kms driver to link one of our encoder/bridge to the given
> > - * bridge.
> > + * Called by a kms driver to link the bridge to an encoder's chain. The
> > previous
> > + * argument specifies the previous bridge in the chain. If NULL, the
> > bridge is
> > + * linked directly at the encoder's output. Otherwise it is linked at the
> > + * previous bridge's output.
> >   *
> > - * Note that setting up links between the bridge and our encoder/bridge
> > - * objects needs to be handled by the kms driver itself.
> > + * If non-NULL the previous bridge must be already attached by a call to
> > this
> > + * function.
> >   *
> >   * RETURNS:
> >   * Zero on success, error code on failure
> >   */
> > -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> > +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> > *bridge,
> > +		      struct drm_bridge *previous)
> >  {
> > -	if (!dev || !bridge)
> > +	int ret;
> > +
> > +	if (!encoder || !bridge)
> > +		return -EINVAL;
> 
> I think we could derive previous from the encoder itself. Something like:
> 
> 	previous = encoder->bridge;
> 	while (previous && previous->next)
> 		previous = previous->next;

That's a very good point. It would however prevent us from catching drivers 
that attach bridges in the wrong order, which the !previous->dev currently 
allows us to do (and it should be turned into a WARN_ON as Daniel proposed).

I'm fine losing that ability, as your proposal makes the API simpler. I'll let 
you decide, which option do you prefer ?

> > +
> > +	if (previous && (!previous->dev || previous->encoder != encoder))
> >  		return -EINVAL;
> >  	
> >  	if (bridge->dev)
> >  		return -EBUSY;
> > 
> > -	bridge->dev = dev;
> > +	bridge->dev = encoder->dev;
> > +	bridge->encoder = encoder;
> > +
> > +	if (bridge->funcs->attach) {
> > +		ret = bridge->funcs->attach(bridge);
> > +		if (ret < 0) {
> > +			bridge->dev = NULL;
> > +			bridge->encoder = NULL;
> > +			return ret;
> > +		}
> > +	}
> > 
> > -	if (bridge->funcs->attach)
> > -		return bridge->funcs->attach(bridge);
> > +	if (previous)
> > +		previous->next = bridge;
> > +	else
> > +		encoder->bridge = bridge;
> > 
> >  	return 0;
> >  }
> 
> <snip>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29 17:57       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 17:57 UTC (permalink / raw)
  To: Archit Taneja
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard

Hi Archit,

On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> > Instead of linking encoders and bridges in every driver (and getting it
> > wrong half of the time, as many drivers forget to set the drm_bridge
> > encoder pointer), do so in core code. The drm_bridge_attach() function
> > needs the encoder and optional previous bridge to perform that task,
> > update all the callers.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++-----
> >  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >  include/drm/drm_bridge.h                           |  3 +-
> >  23 files changed, 83 insertions(+), 103 deletions(-)

[snip]

> > diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> > index 0ee052b7c21a..850bd6509ef1 100644
> > --- a/drivers/gpu/drm/drm_bridge.c
> > +++ b/drivers/gpu/drm/drm_bridge.c

[snip]

> > @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> >  EXPORT_SYMBOL(drm_bridge_remove);
> >  
> >  /**
> > - * drm_bridge_attach - associate given bridge to our DRM device
> > + * drm_bridge_attach - attach the bridge to an encoder's chain
> >   *
> > - * @dev: DRM device
> > - * @bridge: bridge control structure
> > + * @encoder: DRM encoder
> > + * @bridge: bridge to attach
> > + * @previous: previous bridge in the chain (optional)
> >   *
> > - * Called by a kms driver to link one of our encoder/bridge to the given
> > - * bridge.
> > + * Called by a kms driver to link the bridge to an encoder's chain. The
> > previous
> > + * argument specifies the previous bridge in the chain. If NULL, the
> > bridge is
> > + * linked directly at the encoder's output. Otherwise it is linked at the
> > + * previous bridge's output.
> >   *
> > - * Note that setting up links between the bridge and our encoder/bridge
> > - * objects needs to be handled by the kms driver itself.
> > + * If non-NULL the previous bridge must be already attached by a call to
> > this
> > + * function.
> >   *
> >   * RETURNS:
> >   * Zero on success, error code on failure
> >   */
> > -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> > +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> > *bridge,
> > +		      struct drm_bridge *previous)
> >  {
> > -	if (!dev || !bridge)
> > +	int ret;
> > +
> > +	if (!encoder || !bridge)
> > +		return -EINVAL;
> 
> I think we could derive previous from the encoder itself. Something like:
> 
> 	previous = encoder->bridge;
> 	while (previous && previous->next)
> 		previous = previous->next;

That's a very good point. It would however prevent us from catching drivers 
that attach bridges in the wrong order, which the !previous->dev currently 
allows us to do (and it should be turned into a WARN_ON as Daniel proposed).

I'm fine losing that ability, as your proposal makes the API simpler. I'll let 
you decide, which option do you prefer ?

> > +
> > +	if (previous && (!previous->dev || previous->encoder != encoder))
> >  		return -EINVAL;
> >  	
> >  	if (bridge->dev)
> >  		return -EBUSY;
> > 
> > -	bridge->dev = dev;
> > +	bridge->dev = encoder->dev;
> > +	bridge->encoder = encoder;
> > +
> > +	if (bridge->funcs->attach) {
> > +		ret = bridge->funcs->attach(bridge);
> > +		if (ret < 0) {
> > +			bridge->dev = NULL;
> > +			bridge->encoder = NULL;
> > +			return ret;
> > +		}
> > +	}
> > 
> > -	if (bridge->funcs->attach)
> > -		return bridge->funcs->attach(bridge);
> > +	if (previous)
> > +		previous->next = bridge;
> > +	else
> > +		encoder->bridge = bridge;
> > 
> >  	return 0;
> >  }
> 
> <snip>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29 10:05         ` Daniel Vetter
@ 2016-11-29 18:02           ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 18:02 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Laurent Pinchart, dri-devel, Alison Wang, Jingoo Han,
	Seung-Woo Kim, Xinwei Kong, linux-renesas-soc, Kyungmin Park,
	Xinliang Liu, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou

Hi Daniel,

On Tuesday 29 Nov 2016 11:05:27 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:43:19AM +0200, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 10:35:24 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> >>> Instead of linking encoders and bridges in every driver (and getting
> >>> it wrong half of the time, as many drivers forget to set the
> >>> drm_bridge encoder pointer), do so in core code. The
> >>> drm_bridge_attach() function needs the encoder and optional previous
> >>> bridge to perform that task, update all the callers.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >>> ---
> >>> 
> >>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >>>  drivers/gpu/drm/drm_bridge.c                       | 46 +++++++++----
> >>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >>>  include/drm/drm_bridge.h                           |  3 +-
> >>>  23 files changed, 83 insertions(+), 103 deletions(-)
> > 
> > [snip]
> > 
> >>> diff --git a/drivers/gpu/drm/drm_bridge.c
> >>> b/drivers/gpu/drm/drm_bridge.c
> >>> index 0ee052b7c21a..850bd6509ef1 100644
> >>> --- a/drivers/gpu/drm/drm_bridge.c
> >>> +++ b/drivers/gpu/drm/drm_bridge.c

[snip]

> >>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
> >>> *bridge)
> >>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> >>> *bridge,
> >>> +		      struct drm_bridge *previous)
> >>>  {
> >>> -	if (!dev || !bridge)
> >>> +	int ret;
> >>> +
> >>> +	if (!encoder || !bridge)
> >>> +		return -EINVAL;
> >>> +
> >>> +	if (previous && (!previous->dev || previous->encoder != encoder))
> >>>  		return -EINVAL;
> >> 
> >> Not sure we want to allow setting both encoder and bridge for chaining.
> >> I'd kinda expect that for chained use-case the bridge doesn't care that
> >> much who started the chain. And if not we can always create a helper to
> >> look up the drm_encoder.
> > 
> > As bridge drivers currently create connectors (I'd like to change that at
> > some point, but one thing at a time) they need to call
> > drm_mode_connector_attach_encoder() and thus need to have access to the
> > drm_encoder object at the beginning of the chain. The drm_bridge structure
> > has an encoder field, it seems to me that the easiest is to always
> > populate it, regardless of the position of the bridge in the chain.
> 
> I mean the function inteface, not what we fill out in the drm_bridge
> struct. I.e. instead of expecting callers to give you the encoder for
> chained bridges, look it up yourself:
> 
> 	bridge->encoder = previous : previous->encoder ? encoder;
> 
> Or something  like that. Just feels confusing to connect a bridge to both
> a bridge _and_ the first encoder.

Right. Archit proposed doing it the other way around:

        previous = encoder->bridge;
        while (previous && previous->next)
                previous = previous->next;

That would simplify the API, at the cost of preventing us from catching 
drivers that attach bridges in the wrong order (through the !previous->dev 
check that you suggested should be turned into a WARN_ON). The previous-
>encoder != encoder check is also a safety net.

Any opinion on which option you like better ? I'd be very tempted to go for 
Archit's proposal as it removes the previous parameter from the API, if it 
wasn't for the loss of sanity checking.

> Wrt creating the connector: Some helpers to make that easier could be
> useful, and probably we need a separate ->register callback. That's needed
> for proper demidlayered init/teardown sequence anyway, and then the
> drm_bridge.c code make sure to only call ->register for the very last
> bridge. Other bridges could still create ther connectors (less conditions
> in the code), as long as they don't register them no one will ever see
> them ;-)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29 18:02           ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 18:02 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Xinliang Liu, Laurent Pinchart, Alison Wang, Jingoo Han,
	Seung-Woo Kim, Kyungmin Park, dri-devel, linux-renesas-soc,
	Xinwei Kong, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou

Hi Daniel,

On Tuesday 29 Nov 2016 11:05:27 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:43:19AM +0200, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 10:35:24 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> >>> Instead of linking encoders and bridges in every driver (and getting
> >>> it wrong half of the time, as many drivers forget to set the
> >>> drm_bridge encoder pointer), do so in core code. The
> >>> drm_bridge_attach() function needs the encoder and optional previous
> >>> bridge to perform that task, update all the callers.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >>> ---
> >>> 
> >>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >>>  drivers/gpu/drm/drm_bridge.c                       | 46 +++++++++----
> >>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >>>  include/drm/drm_bridge.h                           |  3 +-
> >>>  23 files changed, 83 insertions(+), 103 deletions(-)
> > 
> > [snip]
> > 
> >>> diff --git a/drivers/gpu/drm/drm_bridge.c
> >>> b/drivers/gpu/drm/drm_bridge.c
> >>> index 0ee052b7c21a..850bd6509ef1 100644
> >>> --- a/drivers/gpu/drm/drm_bridge.c
> >>> +++ b/drivers/gpu/drm/drm_bridge.c

[snip]

> >>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
> >>> *bridge)
> >>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> >>> *bridge,
> >>> +		      struct drm_bridge *previous)
> >>>  {
> >>> -	if (!dev || !bridge)
> >>> +	int ret;
> >>> +
> >>> +	if (!encoder || !bridge)
> >>> +		return -EINVAL;
> >>> +
> >>> +	if (previous && (!previous->dev || previous->encoder != encoder))
> >>>  		return -EINVAL;
> >> 
> >> Not sure we want to allow setting both encoder and bridge for chaining.
> >> I'd kinda expect that for chained use-case the bridge doesn't care that
> >> much who started the chain. And if not we can always create a helper to
> >> look up the drm_encoder.
> > 
> > As bridge drivers currently create connectors (I'd like to change that at
> > some point, but one thing at a time) they need to call
> > drm_mode_connector_attach_encoder() and thus need to have access to the
> > drm_encoder object at the beginning of the chain. The drm_bridge structure
> > has an encoder field, it seems to me that the easiest is to always
> > populate it, regardless of the position of the bridge in the chain.
> 
> I mean the function inteface, not what we fill out in the drm_bridge
> struct. I.e. instead of expecting callers to give you the encoder for
> chained bridges, look it up yourself:
> 
> 	bridge->encoder = previous : previous->encoder ? encoder;
> 
> Or something  like that. Just feels confusing to connect a bridge to both
> a bridge _and_ the first encoder.

Right. Archit proposed doing it the other way around:

        previous = encoder->bridge;
        while (previous && previous->next)
                previous = previous->next;

That would simplify the API, at the cost of preventing us from catching 
drivers that attach bridges in the wrong order (through the !previous->dev 
check that you suggested should be turned into a WARN_ON). The previous-
>encoder != encoder check is also a safety net.

Any opinion on which option you like better ? I'd be very tempted to go for 
Archit's proposal as it removes the previous parameter from the API, if it 
wasn't for the loss of sanity checking.

> Wrt creating the connector: Some helpers to make that easier could be
> useful, and probably we need a separate ->register callback. That's needed
> for proper demidlayered init/teardown sequence anyway, and then the
> drm_bridge.c code make sure to only call ->register for the very last
> bridge. Other bridges could still create ther connectors (less conditions
> in the code), as long as they don't register them no one will ever see
> them ;-)

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29 18:02           ` Laurent Pinchart
  (?)
@ 2016-11-29 18:51           ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 18:51 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, Xinliang Liu, Laurent Pinchart, Alison Wang,
	Jingoo Han, Seung-Woo Kim, Kyungmin Park, linux-renesas-soc,
	Xinwei Kong, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou

Hi Daniel,

On Tuesday 29 Nov 2016 20:02:01 Laurent Pinchart wrote:
> On Tuesday 29 Nov 2016 11:05:27 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:43:19AM +0200, Laurent Pinchart wrote:
> >> On Tuesday 29 Nov 2016 10:35:24 Daniel Vetter wrote:
> >>> On Tue, Nov 29, 2016 at 11:04:33AM +0200, Laurent Pinchart wrote:
> >>>> Instead of linking encoders and bridges in every driver (and getting
> >>>> it wrong half of the time, as many drivers forget to set the
> >>>> drm_bridge encoder pointer), do so in core code. The
> >>>> drm_bridge_attach() function needs the encoder and optional previous
> >>>> bridge to perform that task, update all the callers.
> >>>> 
> >>>> Signed-off-by: Laurent Pinchart
> >>>> <laurent.pinchart+renesas@ideasonboard.com>
> >>>> ---

[snip]

> >>>> diff --git a/drivers/gpu/drm/drm_bridge.c
> >>>> b/drivers/gpu/drm/drm_bridge.c
> >>>> index 0ee052b7c21a..850bd6509ef1 100644
> >>>> --- a/drivers/gpu/drm/drm_bridge.c
> >>>> +++ b/drivers/gpu/drm/drm_bridge.c
> 
> [snip]
> 
> >>>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
> >>>> *bridge)
> >>>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> >>>> *bridge,
> >>>> +		      struct drm_bridge *previous)
> >>>>  {
> >>>> -	if (!dev || !bridge)
> >>>> +	int ret;
> >>>> +
> >>>> +	if (!encoder || !bridge)
> >>>> +		return -EINVAL;
> >>>> +
> >>>> +	if (previous && (!previous->dev || previous->encoder !=
> >>>> encoder))
> >>>>  		return -EINVAL;
> >>> 
> >>> Not sure we want to allow setting both encoder and bridge for chaining.
> >>> I'd kinda expect that for chained use-case the bridge doesn't care that
> >>> much who started the chain. And if not we can always create a helper to
> >>> look up the drm_encoder.
> >> 
> >> As bridge drivers currently create connectors (I'd like to change that
> >> at some point, but one thing at a time) they need to call
> >> drm_mode_connector_attach_encoder() and thus need to have access to the
> >> drm_encoder object at the beginning of the chain. The drm_bridge
> >> structure has an encoder field, it seems to me that the easiest is to
> >> always populate it, regardless of the position of the bridge in the
> >> chain.
> > 
> > I mean the function inteface, not what we fill out in the drm_bridge
> > struct. I.e. instead of expecting callers to give you the encoder for
> > 
> > chained bridges, look it up yourself:
> > 	bridge->encoder = previous : previous->encoder ? encoder;
> > 
> > Or something  like that. Just feels confusing to connect a bridge to both
> > a bridge _and_ the first encoder.
> 
> Right. Archit proposed doing it the other way around:
> 
>         previous = encoder->bridge;
>         while (previous && previous->next)
>                 previous = previous->next;
> 
> That would simplify the API, at the cost of preventing us from catching
> drivers that attach bridges in the wrong order (through the !previous->dev
> check that you suggested should be turned into a WARN_ON). The previous-
> 
> >encoder != encoder check is also a safety net.
> 
> Any opinion on which option you like better ? I'd be very tempted to go for
> Archit's proposal as it removes the previous parameter from the API, if it
> wasn't for the loss of sanity checking.
> 
> > Wrt creating the connector: Some helpers to make that easier could be
> > useful, and probably we need a separate ->register callback. That's needed
> > for proper demidlayered init/teardown sequence anyway, and then the
> > drm_bridge.c code make sure to only call ->register for the very last
> > bridge. Other bridges could still create ther connectors (less conditions
> > in the code), as long as they don't register them no one will ever see
> > them ;-)

One thing at a time, we'll get there :-)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
  2016-11-29 10:34   ` Archit Taneja
@ 2016-11-29 18:56       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 18:56 UTC (permalink / raw)
  To: Archit Taneja; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Archit,

On Tuesday 29 Nov 2016 16:04:08 Archit Taneja wrote:
> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> > Most drivers that use bridges forgot to detach them at cleanup time.
> > Instead of fixing them one by one, detach the bridge in the core
> > drm_encoder_cleanup() function.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/drm_encoder.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> > index 5c067719164d..9c1f99646e0d 100644
> > --- a/drivers/gpu/drm/drm_encoder.c
> > +++ b/drivers/gpu/drm/drm_encoder.c
> > @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
> >  	 * the indices on the drm_encoder after us in the encoder_list.
> >  	 */
> > +	if (encoder->bridge)
> > +		drm_bridge_detach(encoder->bridge);
> 
> This would require the kms driver to still detach the remaining
> n - 1 bridges in a possible chain. We could probably detach all of
> them here, or maybe leave detaching of all to the kms driver, and just
> report a warning here.

I'd prefer detaching them all here, but that's a bit intrusive and should be 
tested correctly. The patch series is already growing big, could we do that in 
a separate patch ?

> > +
> > 
> >  	drm_modeset_lock_all(dev);
> >  	drm_mode_object_unregister(dev, &encoder->base);
> >  	kfree(encoder->name);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
@ 2016-11-29 18:56       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 18:56 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Archit,

On Tuesday 29 Nov 2016 16:04:08 Archit Taneja wrote:
> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> > Most drivers that use bridges forgot to detach them at cleanup time.
> > Instead of fixing them one by one, detach the bridge in the core
> > drm_encoder_cleanup() function.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/drm_encoder.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> > index 5c067719164d..9c1f99646e0d 100644
> > --- a/drivers/gpu/drm/drm_encoder.c
> > +++ b/drivers/gpu/drm/drm_encoder.c
> > @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
> >  	 * the indices on the drm_encoder after us in the encoder_list.
> >  	 */
> > +	if (encoder->bridge)
> > +		drm_bridge_detach(encoder->bridge);
> 
> This would require the kms driver to still detach the remaining
> n - 1 bridges in a possible chain. We could probably detach all of
> them here, or maybe leave detaching of all to the kms driver, and just
> report a warning here.

I'd prefer detaching them all here, but that's a bit intrusive and should be 
tested correctly. The patch series is already growing big, could we do that in 
a separate patch ?

> > +
> > 
> >  	drm_modeset_lock_all(dev);
> >  	drm_mode_object_unregister(dev, &encoder->base);
> >  	kfree(encoder->name);

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
  2016-11-29  9:48     ` Daniel Vetter
  (?)
@ 2016-11-29 19:00     ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 19:00 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Daniel,

On Tuesday 29 Nov 2016 10:48:21 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:34AM +0200, Laurent Pinchart wrote:
> > Most drivers that use bridges forgot to detach them at cleanup time.
> > Instead of fixing them one by one, detach the bridge in the core
> > drm_encoder_cleanup() function.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> > ---
> > 
> >  drivers/gpu/drm/drm_encoder.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> > index 5c067719164d..9c1f99646e0d 100644
> > --- a/drivers/gpu/drm/drm_encoder.c
> > +++ b/drivers/gpu/drm/drm_encoder.c
> > @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
> > 
> >  	 * the indices on the drm_encoder after us in the encoder_list.
> >  	 */
> > 
> > +	if (encoder->bridge)
> > +		drm_bridge_detach(encoder->bridge);
> 
> Means we bake in drm_bridge much more as a core thing, but I guess that's
> ok.
> 
> But there's 3 callers of drm_bridge_detach outside of the drm core, can't
> we remove them and drop the EXPORT_SYMBOL for drm_bridge_detach? What's
> it still needed for?

Agreed, I'll fix that.

> I think that cleanup should done in this patch here - drm_bridge_detach
> WARN_ONs if the bridge is already detached ...
>
> > +
> >  	drm_modeset_lock_all(dev);
> >  	drm_mode_object_unregister(dev, &encoder->base);
> >  	kfree(encoder->name);

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-29 19:58     ` Boris Brezillon
  -1 siblings, 0 replies; 100+ messages in thread
From: Boris Brezillon @ 2016-11-29 19:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, Archit Taneja, Jingoo Han,
	Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Stefan Agner, Alison Wang, Xinliang Liu, Rongrong Zou,
	Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu, Rob Clark,
	Benjamin Gaignard, Vincent Abriou, Maxime Ripard

On Tue, 29 Nov 2016 11:04:33 +0200
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> wrote:

> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-

For atmel-hlcdc

Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>

>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>  	of_node_put(np);
>  
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>  
>  	dp->bridge = bridge;
>  
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>  
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;
>  
>  	if (bridge->dev)
>  		return -EBUSY;
>  
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>  
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	bridge->encoder = &pipe->encoder;
> -	pipe->encoder.bridge = bridge;
> -	return drm_bridge_attach(pipe->encoder.dev, bridge);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  				   struct drm_connector *connector)
>  {
>  	struct exynos_dp_device *dp = to_dp(plat_data);
> -	struct drm_encoder *encoder = &dp->encoder;
>  	int ret;
>  
>  	drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		bridge->next = dp->ptn_bridge;
> -		dp->ptn_bridge->encoder = encoder;
> -		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>  	}
>  
>  	bridge = of_drm_find_bridge(dsi->bridge_node);
> -	if (bridge) {
> -		encoder->bridge = bridge;
> -		drm_bridge_attach(drm_dev, bridge);
> -	}
> +	if (bridge)
> +		drm_bridge_attach(encoder, bridge, NULL);
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	fsl_dev->encoder.bridge = bridge;
> -	bridge->encoder = &fsl_dev->encoder;
> -
> -	return drm_bridge_attach(fsl_dev->drm, bridge);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>  
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -
> -	ret = drm_bridge_attach(dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>  			 DRM_MODE_ENCODER_LVDS, NULL);
>  
>  	if (imx_ldb_ch->bridge) {
> -		imx_ldb_ch->bridge->encoder = encoder;
> -
> -		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +					imx_ldb_ch->bridge, NULL);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		imxpd->bridge->encoder = encoder;
> -		encoder->bridge = imxpd->bridge;
> -		ret = drm_bridge_attach(drm, imxpd->bridge);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	dpi->encoder.bridge->encoder = &dpi->encoder;
> -	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  
>  	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>  
> -	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +	dpi->bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->encoder.bridge)
> +	if (!dpi->bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>  	.get_modes = mtk_dsi_connector_get_modes,
>  };
>  
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -				 struct drm_encoder *encoder)
> -{
> -	int ret;
> -
> -	if (!bridge)
> -		return -ENOENT;
> -
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -	ret = drm_bridge_attach(encoder->dev, bridge);
> -	if (ret) {
> -		DRM_ERROR("Failed to attach bridge to drm\n");
> -		encoder->bridge = NULL;
> -		bridge->encoder = NULL;
> -	}
> -
> -	return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>  	dsi->encoder.possible_crtcs = 1;
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
> -	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>  	if (ret) {
> +		DRM_ERROR("Failed to attach bridge to drm\n");
> +
>  		/* Otherwise create our own connector and attach to a panel */
>  		ret = mtk_dsi_create_connector(drm, dsi);
>  		if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>  
>  struct mtk_hdmi {
>  	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
>  	struct drm_connector conn;
>  	struct device *dev;
>  	struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>  		return ret;
>  	}
>  
> -	if (bridge->next) {
> -		bridge->next->encoder = bridge->encoder;
> -		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +	if (hdmi->next_bridge) {
> +		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +					bridge);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	of_node_put(ep);
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -		hdmi->bridge.next = of_drm_find_bridge(remote);
> -		if (!hdmi->bridge.next) {
> +		hdmi->next_bridge = of_drm_find_bridge(remote);
> +		if (!hdmi->next_bridge) {
>  			dev_err(dev, "Waiting for external bridge\n");
>  			of_node_put(remote);
>  			return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>  	struct drm_bridge *bridge = NULL;
>  	struct dsi_bridge *dsi_bridge;
> +	struct drm_encoder *encoder;
>  	int ret;
>  
>  	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  
>  	dsi_bridge->id = id;
>  
> +	/*
> +	 * HACK: we may not know the external DSI bridge device's mode
> +	 * flags here. We'll get to know them only when the device
> +	 * attaches to the dsi host. For now, assume the bridge supports
> +	 * DSI video mode
> +	 */
> +	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> @@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	int_bridge->next = ext_bridge;
> -	/* set the external bridge's encoder as dsi's encoder */
> -	ext_bridge->encoder = encoder;
> -
> -	drm_bridge_attach(dev, ext_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->dev, bridge);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->dev, bridge);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>  	hdmienc->renc = renc;
>  
>  	/* Link the bridge to the encoder. */
> -	bridge->encoder = encoder;
> -	encoder->bridge = bridge;
> -
> -	ret = drm_bridge_attach(rcdu->ddev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  		return err;
>  	}
>  
> -	err = drm_bridge_attach(drm_dev, bridge);
> +	err = drm_bridge_attach(encoder, bridge, NULL);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
>  	}
>  
>  	dvo->bridge = bridge;
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  	dvo->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sun4i_tcon *tcon = drv->tcon;
>  	struct drm_encoder *encoder;
> +	struct drm_bridge *bridge;
>  	struct sun4i_rgb *rgb;
>  	int ret;
>  
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	encoder = &rgb->encoder;
>  
>  	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>  		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>  		return 0;
>  	}
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> -		encoder->bridge->encoder = &rgb->encoder;
> -
> -		ret = drm_bridge_attach(drm, encoder->bridge);
> +	if (!IS_ERR(bridge)) {
> +		ret = drm_bridge_attach(encoder, bridge, NULL);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-29 19:58     ` Boris Brezillon
  0 siblings, 0 replies; 100+ messages in thread
From: Boris Brezillon @ 2016-11-29 19:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Alison Wang, Jingoo Han, Seung-Woo Kim, Xinwei Kong, dri-devel,
	linux-renesas-soc, Kyungmin Park, Xinliang Liu, Chen Feng,
	Rongrong Zou, Maxime Ripard, Vincent Abriou

On Tue, 29 Nov 2016 11:04:33 +0200
Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> wrote:

> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-

For atmel-hlcdc

Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>

>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>  	of_node_put(np);
>  
>  	if (bridge) {
> -		output->encoder.bridge = bridge;
> -		bridge->encoder = &output->encoder;
> -		ret = drm_bridge_attach(dev, bridge);
> +		ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>  		if (!ret)
>  			return 0;
>  	}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>  
>  	dp->bridge = bridge;
>  
> -	dp->encoder->bridge = bridge;
>  	bridge->driver_private = dp;
> -	bridge->encoder = dp->encoder;
>  	bridge->funcs = &analogix_dp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(drm_dev, bridge);
> +	ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach drm bridge\n");
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>  	hdmi->bridge = bridge;
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &dw_hdmi_bridge_funcs;
> -	ret = drm_bridge_attach(drm, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("Failed to initialize bridge with drm\n");
>  		return -EINVAL;
>  	}
>  
> -	encoder->bridge = bridge;
>  	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>  
>  	drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>  
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>  
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous)
>  {
> -	if (!dev || !bridge)
> +	int ret;
> +
> +	if (!encoder || !bridge)
> +		return -EINVAL;
> +
> +	if (previous && (!previous->dev || previous->encoder != encoder))
>  		return -EINVAL;
>  
>  	if (bridge->dev)
>  		return -EBUSY;
>  
> -	bridge->dev = dev;
> +	bridge->dev = encoder->dev;
> +	bridge->encoder = encoder;
> +
> +	if (bridge->funcs->attach) {
> +		ret = bridge->funcs->attach(bridge);
> +		if (ret < 0) {
> +			bridge->dev = NULL;
> +			bridge->encoder = NULL;
> +			return ret;
> +		}
> +	}
>  
> -	if (bridge->funcs->attach)
> -		return bridge->funcs->attach(bridge);
> +	if (previous)
> +		previous->next = bridge;
> +	else
> +		encoder->bridge = bridge;
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>  					  struct drm_bridge *bridge)
>  {
> -	bridge->encoder = &pipe->encoder;
> -	pipe->encoder.bridge = bridge;
> -	return drm_bridge_attach(pipe->encoder.dev, bridge);
> +	return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>  
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  				   struct drm_connector *connector)
>  {
>  	struct exynos_dp_device *dp = to_dp(plat_data);
> -	struct drm_encoder *encoder = &dp->encoder;
>  	int ret;
>  
>  	drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>  
>  	/* Pre-empt DP connector creation if there's a bridge */
>  	if (dp->ptn_bridge) {
> -		bridge->next = dp->ptn_bridge;
> -		dp->ptn_bridge->encoder = encoder;
> -		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +		ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>  		if (ret) {
>  			DRM_ERROR("Failed to attach bridge to drm\n");
>  			bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>  	}
>  
>  	bridge = of_drm_find_bridge(dsi->bridge_node);
> -	if (bridge) {
> -		encoder->bridge = bridge;
> -		drm_bridge_attach(drm_dev, bridge);
> -	}
> +	if (bridge)
> +		drm_bridge_attach(encoder, bridge, NULL);
>  
>  	return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
>  	if (!bridge)
>  		return -ENODEV;
>  
> -	fsl_dev->encoder.bridge = bridge;
> -	bridge->encoder = &fsl_dev->encoder;
> -
> -	return drm_bridge_attach(fsl_dev->drm, bridge);
> +	return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>  
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>  	int ret;
>  
>  	/* associate the bridge to dsi encoder */
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -
> -	ret = drm_bridge_attach(dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		DRM_ERROR("failed to attach external bridge\n");
>  		return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>  			 DRM_MODE_ENCODER_LVDS, NULL);
>  
>  	if (imx_ldb_ch->bridge) {
> -		imx_ldb_ch->bridge->encoder = encoder;
> -
> -		imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -		ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +		ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +					imx_ldb_ch->bridge, NULL);
>  		if (ret) {
>  			DRM_ERROR("Failed to initialize bridge with drm\n");
>  			return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>  		drm_panel_attach(imxpd->panel, &imxpd->connector);
>  
>  	if (imxpd->bridge) {
> -		imxpd->bridge->encoder = encoder;
> -		encoder->bridge = imxpd->bridge;
> -		ret = drm_bridge_attach(drm, imxpd->bridge);
> +		ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>  		if (ret < 0) {
>  			dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>  				ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>  	struct mtk_ddp_comp ddp_comp;
>  	struct drm_encoder encoder;
> +	struct drm_bridge *bridge;
>  	void __iomem *regs;
>  	struct device *dev;
>  	struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>  	/* Currently DPI0 is fixed to be driven by OVL1 */
>  	dpi->encoder.possible_crtcs = BIT(1);
>  
> -	dpi->encoder.bridge->encoder = &dpi->encoder;
> -	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +	ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed to attach bridge: %d\n", ret);
>  		goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>  
>  	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>  
> -	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +	dpi->bridge = of_drm_find_bridge(bridge_node);
>  	of_node_put(bridge_node);
> -	if (!dpi->encoder.bridge)
> +	if (!dpi->bridge)
>  		return -EPROBE_DEFER;
>  
>  	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>  	.get_modes = mtk_dsi_connector_get_modes,
>  };
>  
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -				 struct drm_encoder *encoder)
> -{
> -	int ret;
> -
> -	if (!bridge)
> -		return -ENOENT;
> -
> -	encoder->bridge = bridge;
> -	bridge->encoder = encoder;
> -	ret = drm_bridge_attach(encoder->dev, bridge);
> -	if (ret) {
> -		DRM_ERROR("Failed to attach bridge to drm\n");
> -		encoder->bridge = NULL;
> -		bridge->encoder = NULL;
> -	}
> -
> -	return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>  	int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>  	dsi->encoder.possible_crtcs = 1;
>  
>  	/* If there's a bridge, attach to it and let it create the connector */
> -	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +	ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>  	if (ret) {
> +		DRM_ERROR("Failed to attach bridge to drm\n");
> +
>  		/* Otherwise create our own connector and attach to a panel */
>  		ret = mtk_dsi_create_connector(drm, dsi);
>  		if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>  
>  struct mtk_hdmi {
>  	struct drm_bridge bridge;
> +	struct drm_bridge *next_bridge;
>  	struct drm_connector conn;
>  	struct device *dev;
>  	struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>  		return ret;
>  	}
>  
> -	if (bridge->next) {
> -		bridge->next->encoder = bridge->encoder;
> -		ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +	if (hdmi->next_bridge) {
> +		ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +					bridge);
>  		if (ret) {
>  			dev_err(hdmi->dev,
>  				"Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>  	of_node_put(ep);
>  
>  	if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -		hdmi->bridge.next = of_drm_find_bridge(remote);
> -		if (!hdmi->bridge.next) {
> +		hdmi->next_bridge = of_drm_find_bridge(remote);
> +		if (!hdmi->next_bridge) {
>  			dev_err(dev, "Waiting for external bridge\n");
>  			of_node_put(remote);
>  			return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>  	struct drm_bridge *bridge = NULL;
>  	struct dsi_bridge *dsi_bridge;
> +	struct drm_encoder *encoder;
>  	int ret;
>  
>  	dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>  
>  	dsi_bridge->id = id;
>  
> +	/*
> +	 * HACK: we may not know the external DSI bridge device's mode
> +	 * flags here. We'll get to know them only when the device
> +	 * attaches to the dsi host. For now, assume the bridge supports
> +	 * DSI video mode
> +	 */
> +	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>  	bridge = &dsi_bridge->base;
>  	bridge->funcs = &dsi_mgr_bridge_funcs;
>  
> -	ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> @@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>  	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>  
>  	/* link the internal dsi bridge to the external bridge */
> -	int_bridge->next = ext_bridge;
> -	/* set the external bridge's encoder as dsi's encoder */
> -	ext_bridge->encoder = encoder;
> -
> -	drm_bridge_attach(dev, ext_bridge);
> +	drm_bridge_attach(encoder, ext_bridge, int_bridge);
>  
>  	/*
>  	 * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>  	bridge = &edp_bridge->base;
>  	bridge->funcs = &edp_bridge_funcs;
>  
> -	ret = drm_bridge_attach(edp->dev, bridge);
> +	ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>  	bridge = &hdmi_bridge->base;
>  	bridge->funcs = &msm_hdmi_bridge_funcs;
>  
> -	ret = drm_bridge_attach(hdmi->dev, bridge);
> +	ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>  	if (ret)
>  		goto fail;
>  
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>  	hdmienc->renc = renc;
>  
>  	/* Link the bridge to the encoder. */
> -	bridge->encoder = encoder;
> -	encoder->bridge = bridge;
> -
> -	ret = drm_bridge_attach(rcdu->ddev, bridge);
> +	ret = drm_bridge_attach(encoder, bridge, NULL);
>  	if (ret) {
>  		drm_encoder_cleanup(encoder);
>  		return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  		return err;
>  	}
>  
> -	err = drm_bridge_attach(drm_dev, bridge);
> +	err = drm_bridge_attach(encoder, bridge, NULL);
>  	if (err) {
>  		DRM_ERROR("Failed to attach bridge\n");
>  		return err;
>  	}
>  
>  	dvo->bridge = bridge;
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  	dvo->encoder = encoder;
>  
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hda;
>  	bridge->funcs = &sti_hda_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>  
>  	bridge->driver_private = hdmi;
>  	bridge->funcs = &sti_hdmi_bridge_funcs;
> -	drm_bridge_attach(drm_dev, bridge);
> +	drm_bridge_attach(encoder, bridge, NULL);
>  
> -	encoder->bridge = bridge;
>  	connector->encoder = encoder;
>  
>  	drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	struct sun4i_drv *drv = drm->dev_private;
>  	struct sun4i_tcon *tcon = drv->tcon;
>  	struct drm_encoder *encoder;
> +	struct drm_bridge *bridge;
>  	struct sun4i_rgb *rgb;
>  	int ret;
>  
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>  	encoder = &rgb->encoder;
>  
>  	tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -	encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -	if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +	bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +	if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>  		dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>  		return 0;
>  	}
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>  		}
>  	}
>  
> -	if (!IS_ERR(encoder->bridge)) {
> -		encoder->bridge->encoder = &rgb->encoder;
> -
> -		ret = drm_bridge_attach(drm, encoder->bridge);
> +	if (!IS_ERR(bridge)) {
> +		ret = drm_bridge_attach(encoder, bridge, NULL);
>  		if (ret) {
>  			dev_err(drm->dev, "Couldn't attach our bridge\n");
>  			goto err_cleanup_connector;
>  		}
> -	} else {
> -		encoder->bridge = NULL;
>  	}
>  
>  	return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +		      struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>  
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
  2016-11-29 18:56       ` Laurent Pinchart
@ 2016-11-29 20:22         ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 20:22 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Archit Taneja, linux-renesas-soc, Laurent Pinchart, dri-devel

On Tue, Nov 29, 2016 at 08:56:44PM +0200, Laurent Pinchart wrote:
> Hi Archit,
> 
> On Tuesday 29 Nov 2016 16:04:08 Archit Taneja wrote:
> > On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> > > Most drivers that use bridges forgot to detach them at cleanup time.
> > > Instead of fixing them one by one, detach the bridge in the core
> > > drm_encoder_cleanup() function.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/drm_encoder.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> > > index 5c067719164d..9c1f99646e0d 100644
> > > --- a/drivers/gpu/drm/drm_encoder.c
> > > +++ b/drivers/gpu/drm/drm_encoder.c
> > > @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
> > >  	 * the indices on the drm_encoder after us in the encoder_list.
> > >  	 */
> > > +	if (encoder->bridge)
> > > +		drm_bridge_detach(encoder->bridge);
> > 
> > This would require the kms driver to still detach the remaining
> > n - 1 bridges in a possible chain. We could probably detach all of
> > them here, or maybe leave detaching of all to the kms driver, and just
> > report a warning here.
> 
> I'd prefer detaching them all here, but that's a bit intrusive and should be 
> tested correctly. The patch series is already growing big, could we do that in 
> a separate patch ?

I think you're bridge-for-panels driver is the first one that's actually
getting chained. I guess you do have to fix this here ;-) And if you go
through with making drm_bridge_detach be a purely drm.ko internal thing,
we can make it recursive like all the other functions. Problem solved.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time
@ 2016-11-29 20:22         ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 20:22 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

On Tue, Nov 29, 2016 at 08:56:44PM +0200, Laurent Pinchart wrote:
> Hi Archit,
> 
> On Tuesday 29 Nov 2016 16:04:08 Archit Taneja wrote:
> > On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> > > Most drivers that use bridges forgot to detach them at cleanup time.
> > > Instead of fixing them one by one, detach the bridge in the core
> > > drm_encoder_cleanup() function.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/drm_encoder.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
> > > index 5c067719164d..9c1f99646e0d 100644
> > > --- a/drivers/gpu/drm/drm_encoder.c
> > > +++ b/drivers/gpu/drm/drm_encoder.c
> > > @@ -164,6 +164,9 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
> > >  	 * the indices on the drm_encoder after us in the encoder_list.
> > >  	 */
> > > +	if (encoder->bridge)
> > > +		drm_bridge_detach(encoder->bridge);
> > 
> > This would require the kms driver to still detach the remaining
> > n - 1 bridges in a possible chain. We could probably detach all of
> > them here, or maybe leave detaching of all to the kms driver, and just
> > report a warning here.
> 
> I'd prefer detaching them all here, but that's a bit intrusive and should be 
> tested correctly. The patch series is already growing big, could we do that in 
> a separate patch ?

I think you're bridge-for-panels driver is the first one that's actually
getting chained. I guess you do have to fix this here ;-) And if you go
through with making drm_bridge_detach be a purely drm.ko internal thing,
we can make it recursive like all the other functions. Problem solved.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29 17:49         ` Laurent Pinchart
@ 2016-11-29 20:25           ` Daniel Vetter
  2016-11-29 22:42             ` Laurent Pinchart
  0 siblings, 1 reply; 100+ messages in thread
From: Daniel Vetter @ 2016-11-29 20:25 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Vetter, Laurent Pinchart, dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 07:49:22PM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tuesday 29 Nov 2016 11:27:20 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:58:44AM +0200, Laurent Pinchart wrote:
> > > On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> > >> On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> > >>> The drm_bridge object models on- or off-chip hardware encoders and
> > >>> provide an abstract control API to display drivers. In order to help
> > >>> display drivers creating the right kind of drm_encoder object, expose
> > >>> the type of the hardware encoder associated with each bridge.
> > >>> 
> > >>> Signed-off-by: Laurent Pinchart
> > >>> <laurent.pinchart+renesas@ideasonboard.com>
> > >> 
> > >> DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one cares
> > >> one iota about the encoder type.
> > > 
> > > It's exposed to userspace though, are you 100% sure we won't break
> > > anything ?
> >
> > We've added DP, DSI, DPMST and DPI encoder types thus far, no one
> > screamed.
> 
> In that case why don't we go one step further and remove the encoder type 
> completely ? We can't remove the field from the API, but we can hardcode it to 
> a single value.
> 
> There are however drivers that rely on the encoder type (radeon, nouveau, sti, 
> amdgpu, msm and rcar-du, but I'll fix the last one) so we'd need to address 
> that first. If we don't want to remove the encoder_type field from in-kernel 
> structures and let drivers use it, then I don't think DRM_MODE_ENCODER_BRIDGE 
> would be a good option, we should report the real type instead.

If you strongly believe that I will not stop you. This was just a
suggestion to get all your stuff landed with minimal amounts of effort and
across-the-subsystem cleanup needed. I'd do it that ;-)

And if you don't like DRM_MODE_ENCODER_BRIDGE you could also pick
DRM_MODE_ENCODER_NONE, which is what most seem to do today. In the end it
doesn't matter no matter which option you pick. The only difference is in
the amount of effort you need to spend to get it merged ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2016-11-29  9:54   ` Daniel Vetter
@ 2016-11-29 20:57       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 20:57 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Daniel,

On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> > The LVDS encoder driver is a DRM bridge driver that supports the
> > parallel to LVDS encoders that don't require any configuration. The
> > driver thus doesn't interact with the device, but creates an LVDS
> > connector for the panel and exposes its size and timing based on
> > information retrieved from DT.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Since it's 100% dummy, why put LVDS into the name? This little thing here
> could be our generic "wrap drm_panel and attach it to a chain" helper. So
> what about calling this _The_ drm_panel_bridge, and also linking it into
> docs to feature it a bit more prominently.

I'm not opposed to that, except that this driver should not be considered as 
just a helper to link a panel. It should only be used to support a real 
hardware bridge that requires no control.

> I came up with this because I spotted some refactoring belows for building
> this helper, until I realized that this driver _is_ the helper I think we
> want ;-) Only thing missing is an exported function to instantiate a
> bridge with just a drm_panel as the parameter. And putting it into the
> drm_kms_helper.ko module.

What would that be used for ? The bridge should be instantiated by this bridge 
driver, bound to a bridge device instantiated from DT (or the platform 
firmware of your choice).

> > +static enum drm_connector_status
> > +lvds_connector_detect(struct drm_connector *connector, bool force)
> > +{
> > +	return connector_status_connected;
> > +}
> 
> We have piles of this exact dummy callback all over, maybe make it the
> default and rip them all out?

Done, "[PATCH] drm: Make the connector .detect() callback optional".

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2016-11-29 20:57       ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 20:57 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Daniel,

On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> > The LVDS encoder driver is a DRM bridge driver that supports the
> > parallel to LVDS encoders that don't require any configuration. The
> > driver thus doesn't interact with the device, but creates an LVDS
> > connector for the panel and exposes its size and timing based on
> > information retrieved from DT.
> > 
> > Signed-off-by: Laurent Pinchart
> > <laurent.pinchart+renesas@ideasonboard.com>
> 
> Since it's 100% dummy, why put LVDS into the name? This little thing here
> could be our generic "wrap drm_panel and attach it to a chain" helper. So
> what about calling this _The_ drm_panel_bridge, and also linking it into
> docs to feature it a bit more prominently.

I'm not opposed to that, except that this driver should not be considered as 
just a helper to link a panel. It should only be used to support a real 
hardware bridge that requires no control.

> I came up with this because I spotted some refactoring belows for building
> this helper, until I realized that this driver _is_ the helper I think we
> want ;-) Only thing missing is an exported function to instantiate a
> bridge with just a drm_panel as the parameter. And putting it into the
> drm_kms_helper.ko module.

What would that be used for ? The bridge should be instantiated by this bridge 
driver, bound to a bridge device instantiated from DT (or the platform 
firmware of your choice).

> > +static enum drm_connector_status
> > +lvds_connector_detect(struct drm_connector *connector, bool force)
> > +{
> > +	return connector_status_connected;
> > +}
> 
> We have piles of this exact dummy callback all over, maybe make it the
> default and rip them all out?

Done, "[PATCH] drm: Make the connector .detect() callback optional".

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* [PATCH] drm: bridge: Detach all bridges in a chain at encoder cleanup time
  2016-11-29 20:22         ` Daniel Vetter
  (?)
@ 2016-11-29 21:54         ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 21:54 UTC (permalink / raw)
  To: dri-devel

Instead of detaching only the bridge directly connected to the encoder,
detach all bridges in the chain.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/drm_encoder.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Hi Daniel,

As requested, here's a patch that makes bridge detach recursive. It's based on
top of "[PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder
cleanup time".

diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 9c1f99646e0d..33d3e6ec83be 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -164,8 +164,16 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
 	 * the indices on the drm_encoder after us in the encoder_list.
 	 */
 
-	if (encoder->bridge)
-		drm_bridge_detach(encoder->bridge);
+	if (encoder->bridge) {
+		struct drm_bridge *bridge = encoder->bridge;
+		struct drm_bridge *next;
+
+		while (bridge) {
+			next = bridge->next;
+			drm_bridge_detach(bridge);
+			bridge = next;
+		}
+	}
 
 	drm_modeset_lock_all(dev);
 	drm_mode_object_unregister(dev, &encoder->base);
-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure
  2016-11-29 20:25           ` Daniel Vetter
@ 2016-11-29 22:42             ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-29 22:42 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Daniel,

On Tuesday 29 Nov 2016 21:25:27 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 07:49:22PM +0200, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 11:27:20 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 11:58:44AM +0200, Laurent Pinchart wrote:
> >>> On Tuesday 29 Nov 2016 10:56:53 Daniel Vetter wrote:
> >>>> On Tue, Nov 29, 2016 at 11:04:39AM +0200, Laurent Pinchart wrote:
> >>>>> The drm_bridge object models on- or off-chip hardware encoders and
> >>>>> provide an abstract control API to display drivers. In order to help
> >>>>> display drivers creating the right kind of drm_encoder object,
> >>>>> expose the type of the hardware encoder associated with each bridge.
> >>>>> 
> >>>>> Signed-off-by: Laurent Pinchart
> >>>>> <laurent.pinchart+renesas@ideasonboard.com>
> >>>> 
> >>>> DRM_MODE_ENCODER_BRIDGE. Problem solved, because in reality no one
> >>>> cares one iota about the encoder type.
> >>> 
> >>> It's exposed to userspace though, are you 100% sure we won't break
> >>> anything ?
> >> 
> >> We've added DP, DSI, DPMST and DPI encoder types thus far, no one
> >> screamed.
> > 
> > In that case why don't we go one step further and remove the encoder type
> > completely ? We can't remove the field from the API, but we can hardcode
> > it to a single value.
> > 
> > There are however drivers that rely on the encoder type (radeon, nouveau,
> > sti, amdgpu, msm and rcar-du, but I'll fix the last one) so we'd need to
> > address that first. If we don't want to remove the encoder_type field
> > from in-kernel structures and let drivers use it, then I don't think
> > DRM_MODE_ENCODER_BRIDGE would be a good option, we should report the real
> > type instead.
> 
> If you strongly believe that I will not stop you. This was just a
> suggestion to get all your stuff landed with minimal amounts of effort and
> across-the-subsystem cleanup needed. I'd do it that ;-)
> 
> And if you don't like DRM_MODE_ENCODER_BRIDGE you could also pick
> DRM_MODE_ENCODER_NONE, which is what most seem to do today. In the end it
> doesn't matter no matter which option you pick. The only difference is in
> the amount of effort you need to spend to get it merged ...

I've tried hardcoding the encoder type to DRM_MODE_ENCODER_NONE and basic 
tests still pass (I haven't tried more complex userspace stacks such as X or 
Weston though). I'll thus drop the addition of encoder_type to the bridge for 
now. As a result we should start deprecating the drm_encoder::encoder_type 
field (unless a compelling reason is found of course, in which case I'd have 
to revive drm_bridge::encoder_type).

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29 17:57       ` Laurent Pinchart
@ 2016-11-30  5:05         ` Archit Taneja
  -1 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-30  5:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard, Vincent Abriou, Maxime Ripard



On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
>>> Instead of linking encoders and bridges in every driver (and getting it
>>> wrong half of the time, as many drivers forget to set the drm_bridge
>>> encoder pointer), do so in core code. The drm_bridge_attach() function
>>> needs the encoder and optional previous bridge to perform that task,
>>> update all the callers.
>>>
>>> Signed-off-by: Laurent Pinchart
>>> <laurent.pinchart+renesas@ideasonboard.com>
>>> ---
>>>
>>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>>>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++-----
>>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>>>  include/drm/drm_bridge.h                           |  3 +-
>>>  23 files changed, 83 insertions(+), 103 deletions(-)
>
> [snip]
>
>>> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
>>> index 0ee052b7c21a..850bd6509ef1 100644
>>> --- a/drivers/gpu/drm/drm_bridge.c
>>> +++ b/drivers/gpu/drm/drm_bridge.c
>
> [snip]
>
>>> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>>>  EXPORT_SYMBOL(drm_bridge_remove);
>>>
>>>  /**
>>> - * drm_bridge_attach - associate given bridge to our DRM device
>>> + * drm_bridge_attach - attach the bridge to an encoder's chain
>>>   *
>>> - * @dev: DRM device
>>> - * @bridge: bridge control structure
>>> + * @encoder: DRM encoder
>>> + * @bridge: bridge to attach
>>> + * @previous: previous bridge in the chain (optional)
>>>   *
>>> - * Called by a kms driver to link one of our encoder/bridge to the given
>>> - * bridge.
>>> + * Called by a kms driver to link the bridge to an encoder's chain. The
>>> previous
>>> + * argument specifies the previous bridge in the chain. If NULL, the
>>> bridge is
>>> + * linked directly at the encoder's output. Otherwise it is linked at the
>>> + * previous bridge's output.
>>>   *
>>> - * Note that setting up links between the bridge and our encoder/bridge
>>> - * objects needs to be handled by the kms driver itself.
>>> + * If non-NULL the previous bridge must be already attached by a call to
>>> this
>>> + * function.
>>>   *
>>>   * RETURNS:
>>>   * Zero on success, error code on failure
>>>   */
>>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
>>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
>>> *bridge,
>>> +		      struct drm_bridge *previous)
>>>  {
>>> -	if (!dev || !bridge)
>>> +	int ret;
>>> +
>>> +	if (!encoder || !bridge)
>>> +		return -EINVAL;
>>
>> I think we could derive previous from the encoder itself. Something like:
>>
>> 	previous = encoder->bridge;
>> 	while (previous && previous->next)
>> 		previous = previous->next;
>
> That's a very good point. It would however prevent us from catching drivers
> that attach bridges in the wrong order, which the !previous->dev currently
> allows us to do (and it should be turned into a WARN_ON as Daniel proposed).
>

With the simpler API, I don't think we will ever hit the case of
!previous->dev. The previous bridge (if it exists) in the chain would
already have a dev attached to it. In other words, we would remove the
risk of the chance of the 'previous' bridge being unattached.

I'm a bit unclear about what you mean about the order part. If a kms driver
wants to create a chain: encoder->bridge1->bridge2, it should ideally do:

drm_bridge_attach(encoder, bridge1, NULL);
drm_bridge_attach(encoder, bridge2, bridge1);

We can't do much if the kms driver does the opposite:

drm_bridge_attach(encoder, bridge2, NULL);
drm_bridge_attach(encoder, bridge2, bridge1);


> I'm fine losing that ability, as your proposal makes the API simpler. I'll let
> you decide, which option do you prefer ?

I prefer the simpler API. I guess the main aim of the patch was to prevent the
driver setting up the encoder<->bridge links, which will be done anyway.

Thanks,
Archit

>
>>> +
>>> +	if (previous && (!previous->dev || previous->encoder != encoder))
>>>  		return -EINVAL;
>>>  	
>>>  	if (bridge->dev)
>>>  		return -EBUSY;
>>>
>>> -	bridge->dev = dev;
>>> +	bridge->dev = encoder->dev;
>>> +	bridge->encoder = encoder;
>>> +
>>> +	if (bridge->funcs->attach) {
>>> +		ret = bridge->funcs->attach(bridge);
>>> +		if (ret < 0) {
>>> +			bridge->dev = NULL;
>>> +			bridge->encoder = NULL;
>>> +			return ret;
>>> +		}
>>> +	}
>>>
>>> -	if (bridge->funcs->attach)
>>> -		return bridge->funcs->attach(bridge);
>>> +	if (previous)
>>> +		previous->next = bridge;
>>> +	else
>>> +		encoder->bridge = bridge;
>>>
>>>  	return 0;
>>>  }
>>
>> <snip>
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-30  5:05         ` Archit Taneja
  0 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-30  5:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard



On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
>>> Instead of linking encoders and bridges in every driver (and getting it
>>> wrong half of the time, as many drivers forget to set the drm_bridge
>>> encoder pointer), do so in core code. The drm_bridge_attach() function
>>> needs the encoder and optional previous bridge to perform that task,
>>> update all the callers.
>>>
>>> Signed-off-by: Laurent Pinchart
>>> <laurent.pinchart+renesas@ideasonboard.com>
>>> ---
>>>
>>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>>>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++-----
>>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>>>  include/drm/drm_bridge.h                           |  3 +-
>>>  23 files changed, 83 insertions(+), 103 deletions(-)
>
> [snip]
>
>>> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
>>> index 0ee052b7c21a..850bd6509ef1 100644
>>> --- a/drivers/gpu/drm/drm_bridge.c
>>> +++ b/drivers/gpu/drm/drm_bridge.c
>
> [snip]
>
>>> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>>>  EXPORT_SYMBOL(drm_bridge_remove);
>>>
>>>  /**
>>> - * drm_bridge_attach - associate given bridge to our DRM device
>>> + * drm_bridge_attach - attach the bridge to an encoder's chain
>>>   *
>>> - * @dev: DRM device
>>> - * @bridge: bridge control structure
>>> + * @encoder: DRM encoder
>>> + * @bridge: bridge to attach
>>> + * @previous: previous bridge in the chain (optional)
>>>   *
>>> - * Called by a kms driver to link one of our encoder/bridge to the given
>>> - * bridge.
>>> + * Called by a kms driver to link the bridge to an encoder's chain. The
>>> previous
>>> + * argument specifies the previous bridge in the chain. If NULL, the
>>> bridge is
>>> + * linked directly at the encoder's output. Otherwise it is linked at the
>>> + * previous bridge's output.
>>>   *
>>> - * Note that setting up links between the bridge and our encoder/bridge
>>> - * objects needs to be handled by the kms driver itself.
>>> + * If non-NULL the previous bridge must be already attached by a call to
>>> this
>>> + * function.
>>>   *
>>>   * RETURNS:
>>>   * Zero on success, error code on failure
>>>   */
>>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
>>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
>>> *bridge,
>>> +		      struct drm_bridge *previous)
>>>  {
>>> -	if (!dev || !bridge)
>>> +	int ret;
>>> +
>>> +	if (!encoder || !bridge)
>>> +		return -EINVAL;
>>
>> I think we could derive previous from the encoder itself. Something like:
>>
>> 	previous = encoder->bridge;
>> 	while (previous && previous->next)
>> 		previous = previous->next;
>
> That's a very good point. It would however prevent us from catching drivers
> that attach bridges in the wrong order, which the !previous->dev currently
> allows us to do (and it should be turned into a WARN_ON as Daniel proposed).
>

With the simpler API, I don't think we will ever hit the case of
!previous->dev. The previous bridge (if it exists) in the chain would
already have a dev attached to it. In other words, we would remove the
risk of the chance of the 'previous' bridge being unattached.

I'm a bit unclear about what you mean about the order part. If a kms driver
wants to create a chain: encoder->bridge1->bridge2, it should ideally do:

drm_bridge_attach(encoder, bridge1, NULL);
drm_bridge_attach(encoder, bridge2, bridge1);

We can't do much if the kms driver does the opposite:

drm_bridge_attach(encoder, bridge2, NULL);
drm_bridge_attach(encoder, bridge2, bridge1);


> I'm fine losing that ability, as your proposal makes the API simpler. I'll let
> you decide, which option do you prefer ?

I prefer the simpler API. I guess the main aim of the patch was to prevent the
driver setting up the encoder<->bridge links, which will be done anyway.

Thanks,
Archit

>
>>> +
>>> +	if (previous && (!previous->dev || previous->encoder != encoder))
>>>  		return -EINVAL;
>>>  	
>>>  	if (bridge->dev)
>>>  		return -EBUSY;
>>>
>>> -	bridge->dev = dev;
>>> +	bridge->dev = encoder->dev;
>>> +	bridge->encoder = encoder;
>>> +
>>> +	if (bridge->funcs->attach) {
>>> +		ret = bridge->funcs->attach(bridge);
>>> +		if (ret < 0) {
>>> +			bridge->dev = NULL;
>>> +			bridge->encoder = NULL;
>>> +			return ret;
>>> +		}
>>> +	}
>>>
>>> -	if (bridge->funcs->attach)
>>> -		return bridge->funcs->attach(bridge);
>>> +	if (previous)
>>> +		previous->next = bridge;
>>> +	else
>>> +		encoder->bridge = bridge;
>>>
>>>  	return 0;
>>>  }
>>
>> <snip>
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-30  5:05         ` Archit Taneja
@ 2016-11-30 10:23           ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-30 10:23 UTC (permalink / raw)
  To: Archit Taneja
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard, Vincent Abriou, Maxime Ripard

Hi Archit,

On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
> >> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> >>> Instead of linking encoders and bridges in every driver (and getting it
> >>> wrong half of the time, as many drivers forget to set the drm_bridge
> >>> encoder pointer), do so in core code. The drm_bridge_attach() function
> >>> needs the encoder and optional previous bridge to perform that task,
> >>> update all the callers.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >>> ---
> >>> 
> >>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >>>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++-----
> >>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >>>  include/drm/drm_bridge.h                           |  3 +-
> >>>  23 files changed, 83 insertions(+), 103 deletions(-)
> > 
> > [snip]
> > 
> >>> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> >>> index 0ee052b7c21a..850bd6509ef1 100644
> >>> --- a/drivers/gpu/drm/drm_bridge.c
> >>> +++ b/drivers/gpu/drm/drm_bridge.c
> > 
> > [snip]
> > 
> >>> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> >>>  EXPORT_SYMBOL(drm_bridge_remove);
> >>>  
> >>>  /**
> >>> - * drm_bridge_attach - associate given bridge to our DRM device
> >>> + * drm_bridge_attach - attach the bridge to an encoder's chain
> >>>   *
> >>> - * @dev: DRM device
> >>> - * @bridge: bridge control structure
> >>> + * @encoder: DRM encoder
> >>> + * @bridge: bridge to attach
> >>> + * @previous: previous bridge in the chain (optional)
> >>>   *
> >>> - * Called by a kms driver to link one of our encoder/bridge to the
> >>> given
> >>> - * bridge.
> >>> + * Called by a kms driver to link the bridge to an encoder's chain. The
> >>> previous
> >>> + * argument specifies the previous bridge in the chain. If NULL, the
> >>> bridge is
> >>> + * linked directly at the encoder's output. Otherwise it is linked at
> >>> the
> >>> + * previous bridge's output.
> >>>   *
> >>> - * Note that setting up links between the bridge and our encoder/bridge
> >>> - * objects needs to be handled by the kms driver itself.
> >>> + * If non-NULL the previous bridge must be already attached by a call
> >>> to this
> >>> + * function.
> >>>   *
> >>>   * RETURNS:
> >>>   * Zero on success, error code on failure
> >>>   */
> >>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
> >>> *bridge)
> >>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> >>> *bridge,
> >>> +		      struct drm_bridge *previous)
> >>>  {
> >>> -	if (!dev || !bridge)
> >>> +	int ret;
> >>> +
> >>> +	if (!encoder || !bridge)
> >>> +		return -EINVAL;
> >> 
> >> I think we could derive previous from the encoder itself. Something like:
> >> 	previous = encoder->bridge;
> >> 	while (previous && previous->next)
> >> 	
> >> 		previous = previous->next;
> > 
> > That's a very good point. It would however prevent us from catching
> > drivers that attach bridges in the wrong order, which the !previous->dev
> > currently allows us to do (and it should be turned into a WARN_ON as
> > Daniel proposed).
>
> With the simpler API, I don't think we will ever hit the case of
> !previous->dev. The previous bridge (if it exists) in the chain would
> already have a dev attached to it. In other words, we would remove the
> risk of the chance of the 'previous' bridge being unattached.
> 
> I'm a bit unclear about what you mean about the order part. If a kms driver
> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
> 
> drm_bridge_attach(encoder, bridge1, NULL);
> drm_bridge_attach(encoder, bridge2, bridge1);

Correct.

> We can't do much if the kms driver does the opposite:
> 
> drm_bridge_attach(encoder, bridge2, NULL);
> drm_bridge_attach(encoder, bridge2, bridge1);

That would certainly be a very stupid thing for a driver to do :-) The problem 
that we could catch with my current proposal is

drm_bridge_attach(encoder, bridge2, bridge1);
...
drm_bridge_attach(encoder, bridge1, NULL);

which I expect to happen from time to time as the two bridge can be attached 
through separate code paths sometimes a bit difficult to trace. It's not a big 
deal though, you could convince me that the advantages of a simpler API exceed 
its drawbacks.

> > I'm fine losing that ability, as your proposal makes the API simpler. I'll
> > let you decide, which option do you prefer ?
> 
> I prefer the simpler API. I guess the main aim of the patch was to prevent
> the driver setting up the encoder<->bridge links, which will be done
> anyway.

If you still prefer the simpler API after reading the above, I'll update my 
patch.

> >>> +
> >>> +	if (previous && (!previous->dev || previous->encoder != encoder))
> >>>  		return -EINVAL;
> >>>  	
> >>>  	if (bridge->dev)
> >>>  		return -EBUSY;
> >>> 
> >>> -	bridge->dev = dev;
> >>> +	bridge->dev = encoder->dev;
> >>> +	bridge->encoder = encoder;
> >>> +
> >>> +	if (bridge->funcs->attach) {
> >>> +		ret = bridge->funcs->attach(bridge);
> >>> +		if (ret < 0) {
> >>> +			bridge->dev = NULL;
> >>> +			bridge->encoder = NULL;
> >>> +			return ret;
> >>> +		}
> >>> +	}
> >>> 
> >>> -	if (bridge->funcs->attach)
> >>> -		return bridge->funcs->attach(bridge);
> >>> +	if (previous)
> >>> +		previous->next = bridge;
> >>> +	else
> >>> +		encoder->bridge = bridge;
> >>> 
> >>>  	return 0;
> >>>  }
> >> 
> >> <snip>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-30 10:23           ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-30 10:23 UTC (permalink / raw)
  To: Archit Taneja
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard

Hi Archit,

On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
> >> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> >>> Instead of linking encoders and bridges in every driver (and getting it
> >>> wrong half of the time, as many drivers forget to set the drm_bridge
> >>> encoder pointer), do so in core code. The drm_bridge_attach() function
> >>> needs the encoder and optional previous bridge to perform that task,
> >>> update all the callers.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >>> ---
> >>> 
> >>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
> >>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
> >>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
> >>>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++-----
> >>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
> >>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
> >>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
> >>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
> >>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
> >>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
> >>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
> >>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
> >>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
> >>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
> >>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
> >>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
> >>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
> >>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
> >>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
> >>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
> >>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
> >>>  include/drm/drm_bridge.h                           |  3 +-
> >>>  23 files changed, 83 insertions(+), 103 deletions(-)
> > 
> > [snip]
> > 
> >>> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> >>> index 0ee052b7c21a..850bd6509ef1 100644
> >>> --- a/drivers/gpu/drm/drm_bridge.c
> >>> +++ b/drivers/gpu/drm/drm_bridge.c
> > 
> > [snip]
> > 
> >>> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
> >>>  EXPORT_SYMBOL(drm_bridge_remove);
> >>>  
> >>>  /**
> >>> - * drm_bridge_attach - associate given bridge to our DRM device
> >>> + * drm_bridge_attach - attach the bridge to an encoder's chain
> >>>   *
> >>> - * @dev: DRM device
> >>> - * @bridge: bridge control structure
> >>> + * @encoder: DRM encoder
> >>> + * @bridge: bridge to attach
> >>> + * @previous: previous bridge in the chain (optional)
> >>>   *
> >>> - * Called by a kms driver to link one of our encoder/bridge to the
> >>> given
> >>> - * bridge.
> >>> + * Called by a kms driver to link the bridge to an encoder's chain. The
> >>> previous
> >>> + * argument specifies the previous bridge in the chain. If NULL, the
> >>> bridge is
> >>> + * linked directly at the encoder's output. Otherwise it is linked at
> >>> the
> >>> + * previous bridge's output.
> >>>   *
> >>> - * Note that setting up links between the bridge and our encoder/bridge
> >>> - * objects needs to be handled by the kms driver itself.
> >>> + * If non-NULL the previous bridge must be already attached by a call
> >>> to this
> >>> + * function.
> >>>   *
> >>>   * RETURNS:
> >>>   * Zero on success, error code on failure
> >>>   */
> >>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
> >>> *bridge)
> >>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
> >>> *bridge,
> >>> +		      struct drm_bridge *previous)
> >>>  {
> >>> -	if (!dev || !bridge)
> >>> +	int ret;
> >>> +
> >>> +	if (!encoder || !bridge)
> >>> +		return -EINVAL;
> >> 
> >> I think we could derive previous from the encoder itself. Something like:
> >> 	previous = encoder->bridge;
> >> 	while (previous && previous->next)
> >> 	
> >> 		previous = previous->next;
> > 
> > That's a very good point. It would however prevent us from catching
> > drivers that attach bridges in the wrong order, which the !previous->dev
> > currently allows us to do (and it should be turned into a WARN_ON as
> > Daniel proposed).
>
> With the simpler API, I don't think we will ever hit the case of
> !previous->dev. The previous bridge (if it exists) in the chain would
> already have a dev attached to it. In other words, we would remove the
> risk of the chance of the 'previous' bridge being unattached.
> 
> I'm a bit unclear about what you mean about the order part. If a kms driver
> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
> 
> drm_bridge_attach(encoder, bridge1, NULL);
> drm_bridge_attach(encoder, bridge2, bridge1);

Correct.

> We can't do much if the kms driver does the opposite:
> 
> drm_bridge_attach(encoder, bridge2, NULL);
> drm_bridge_attach(encoder, bridge2, bridge1);

That would certainly be a very stupid thing for a driver to do :-) The problem 
that we could catch with my current proposal is

drm_bridge_attach(encoder, bridge2, bridge1);
...
drm_bridge_attach(encoder, bridge1, NULL);

which I expect to happen from time to time as the two bridge can be attached 
through separate code paths sometimes a bit difficult to trace. It's not a big 
deal though, you could convince me that the advantages of a simpler API exceed 
its drawbacks.

> > I'm fine losing that ability, as your proposal makes the API simpler. I'll
> > let you decide, which option do you prefer ?
> 
> I prefer the simpler API. I guess the main aim of the patch was to prevent
> the driver setting up the encoder<->bridge links, which will be done
> anyway.

If you still prefer the simpler API after reading the above, I'll update my 
patch.

> >>> +
> >>> +	if (previous && (!previous->dev || previous->encoder != encoder))
> >>>  		return -EINVAL;
> >>>  	
> >>>  	if (bridge->dev)
> >>>  		return -EBUSY;
> >>> 
> >>> -	bridge->dev = dev;
> >>> +	bridge->dev = encoder->dev;
> >>> +	bridge->encoder = encoder;
> >>> +
> >>> +	if (bridge->funcs->attach) {
> >>> +		ret = bridge->funcs->attach(bridge);
> >>> +		if (ret < 0) {
> >>> +			bridge->dev = NULL;
> >>> +			bridge->encoder = NULL;
> >>> +			return ret;
> >>> +		}
> >>> +	}
> >>> 
> >>> -	if (bridge->funcs->attach)
> >>> -		return bridge->funcs->attach(bridge);
> >>> +	if (previous)
> >>> +		previous->next = bridge;
> >>> +	else
> >>> +		encoder->bridge = bridge;
> >>> 
> >>>  	return 0;
> >>>  }
> >> 
> >> <snip>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-30 10:23           ` Laurent Pinchart
@ 2016-11-30 11:00             ` Archit Taneja
  -1 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-30 11:00 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard, Vincent Abriou, Maxime Ripard



On 11/30/2016 03:53 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
>> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
>>> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
>>>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
>>>>> Instead of linking encoders and bridges in every driver (and getting it
>>>>> wrong half of the time, as many drivers forget to set the drm_bridge
>>>>> encoder pointer), do so in core code. The drm_bridge_attach() function
>>>>> needs the encoder and optional previous bridge to perform that task,
>>>>> update all the callers.
>>>>>
>>>>> Signed-off-by: Laurent Pinchart
>>>>> <laurent.pinchart+renesas@ideasonboard.com>
>>>>> ---
>>>>>
>>>>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>>>>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>>>>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>>>>>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++-----
>>>>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>>>>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>>>>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>>>>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>>>>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>>>>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>>>>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>>>>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>>>>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>>>>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>>>>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>>>>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>>>>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>>>>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>>>>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>>>>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>>>>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>>>>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>>>>>  include/drm/drm_bridge.h                           |  3 +-
>>>>>  23 files changed, 83 insertions(+), 103 deletions(-)
>>>
>>> [snip]
>>>
>>>>> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
>>>>> index 0ee052b7c21a..850bd6509ef1 100644
>>>>> --- a/drivers/gpu/drm/drm_bridge.c
>>>>> +++ b/drivers/gpu/drm/drm_bridge.c
>>>
>>> [snip]
>>>
>>>>> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>>>>>  EXPORT_SYMBOL(drm_bridge_remove);
>>>>>
>>>>>  /**
>>>>> - * drm_bridge_attach - associate given bridge to our DRM device
>>>>> + * drm_bridge_attach - attach the bridge to an encoder's chain
>>>>>   *
>>>>> - * @dev: DRM device
>>>>> - * @bridge: bridge control structure
>>>>> + * @encoder: DRM encoder
>>>>> + * @bridge: bridge to attach
>>>>> + * @previous: previous bridge in the chain (optional)
>>>>>   *
>>>>> - * Called by a kms driver to link one of our encoder/bridge to the
>>>>> given
>>>>> - * bridge.
>>>>> + * Called by a kms driver to link the bridge to an encoder's chain. The
>>>>> previous
>>>>> + * argument specifies the previous bridge in the chain. If NULL, the
>>>>> bridge is
>>>>> + * linked directly at the encoder's output. Otherwise it is linked at
>>>>> the
>>>>> + * previous bridge's output.
>>>>>   *
>>>>> - * Note that setting up links between the bridge and our encoder/bridge
>>>>> - * objects needs to be handled by the kms driver itself.
>>>>> + * If non-NULL the previous bridge must be already attached by a call
>>>>> to this
>>>>> + * function.
>>>>>   *
>>>>>   * RETURNS:
>>>>>   * Zero on success, error code on failure
>>>>>   */
>>>>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
>>>>> *bridge)
>>>>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
>>>>> *bridge,
>>>>> +		      struct drm_bridge *previous)
>>>>>  {
>>>>> -	if (!dev || !bridge)
>>>>> +	int ret;
>>>>> +
>>>>> +	if (!encoder || !bridge)
>>>>> +		return -EINVAL;
>>>>
>>>> I think we could derive previous from the encoder itself. Something like:
>>>> 	previous = encoder->bridge;
>>>> 	while (previous && previous->next)
>>>> 	
>>>> 		previous = previous->next;
>>>
>>> That's a very good point. It would however prevent us from catching
>>> drivers that attach bridges in the wrong order, which the !previous->dev
>>> currently allows us to do (and it should be turned into a WARN_ON as
>>> Daniel proposed).
>>
>> With the simpler API, I don't think we will ever hit the case of
>> !previous->dev. The previous bridge (if it exists) in the chain would
>> already have a dev attached to it. In other words, we would remove the
>> risk of the chance of the 'previous' bridge being unattached.
>>
>> I'm a bit unclear about what you mean about the order part. If a kms driver
>> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
>>
>> drm_bridge_attach(encoder, bridge1, NULL);
>> drm_bridge_attach(encoder, bridge2, bridge1);
>
> Correct.
>
>> We can't do much if the kms driver does the opposite:
>>
>> drm_bridge_attach(encoder, bridge2, NULL);
>> drm_bridge_attach(encoder, bridge2, bridge1);
>
> That would certainly be a very stupid thing for a driver to do :-) The problem
> that we could catch with my current proposal is
>
> drm_bridge_attach(encoder, bridge2, bridge1);
> ...
> drm_bridge_attach(encoder, bridge1, NULL);
>
> which I expect to happen from time to time as the two bridge can be attached
> through separate code paths sometimes a bit difficult to trace. It's not a big
> deal though, you could convince me that the advantages of a simpler API exceed
> its drawbacks.

Having no 'previous' argument would prevent the possibility of this altogether,
won't it?

With no 'previous' arg in the API, the driver can only do:

drm_bridge_attach(encoder, bridge1);
drm_bridge_attach(encoder, bridge2);

or

drm_bridge_attach(encoder, bridge2);
drm_bridge_attach(encoder, bridge1);

For the latter, we can't do much as discussed above.

Archit

>
>>> I'm fine losing that ability, as your proposal makes the API simpler. I'll
>>> let you decide, which option do you prefer ?
>>
>> I prefer the simpler API. I guess the main aim of the patch was to prevent
>> the driver setting up the encoder<->bridge links, which will be done
>> anyway.
>
> If you still prefer the simpler API after reading the above, I'll update my
> patch.
>
>>>>> +
>>>>> +	if (previous && (!previous->dev || previous->encoder != encoder))
>>>>>  		return -EINVAL;
>>>>>  	
>>>>>  	if (bridge->dev)
>>>>>  		return -EBUSY;
>>>>>
>>>>> -	bridge->dev = dev;
>>>>> +	bridge->dev = encoder->dev;
>>>>> +	bridge->encoder = encoder;
>>>>> +
>>>>> +	if (bridge->funcs->attach) {
>>>>> +		ret = bridge->funcs->attach(bridge);
>>>>> +		if (ret < 0) {
>>>>> +			bridge->dev = NULL;
>>>>> +			bridge->encoder = NULL;
>>>>> +			return ret;
>>>>> +		}
>>>>> +	}
>>>>>
>>>>> -	if (bridge->funcs->attach)
>>>>> -		return bridge->funcs->attach(bridge);
>>>>> +	if (previous)
>>>>> +		previous->next = bridge;
>>>>> +	else
>>>>> +		encoder->bridge = bridge;
>>>>>
>>>>>  	return 0;
>>>>>  }
>>>>
>>>> <snip>
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-30 11:00             ` Archit Taneja
  0 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-30 11:00 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, Alison Wang, Jingoo Han, Seung-Woo Kim,
	Xinwei Kong, dri-devel, linux-renesas-soc, Kyungmin Park,
	Xinliang Liu, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou



On 11/30/2016 03:53 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
>> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
>>> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
>>>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
>>>>> Instead of linking encoders and bridges in every driver (and getting it
>>>>> wrong half of the time, as many drivers forget to set the drm_bridge
>>>>> encoder pointer), do so in core code. The drm_bridge_attach() function
>>>>> needs the encoder and optional previous bridge to perform that task,
>>>>> update all the callers.
>>>>>
>>>>> Signed-off-by: Laurent Pinchart
>>>>> <laurent.pinchart+renesas@ideasonboard.com>
>>>>> ---
>>>>>
>>>>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>>>>>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>>>>>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>>>>>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++-----
>>>>>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>>>>>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>>>>>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>>>>>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>>>>>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>>>>>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>>>>>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>>>>>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>>>>>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>>>>>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>>>>>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>>>>>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>>>>>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>>>>>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>>>>>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>>>>>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>>>>>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-
>>>>>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>>>>>  include/drm/drm_bridge.h                           |  3 +-
>>>>>  23 files changed, 83 insertions(+), 103 deletions(-)
>>>
>>> [snip]
>>>
>>>>> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
>>>>> index 0ee052b7c21a..850bd6509ef1 100644
>>>>> --- a/drivers/gpu/drm/drm_bridge.c
>>>>> +++ b/drivers/gpu/drm/drm_bridge.c
>>>
>>> [snip]
>>>
>>>>> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>>>>>  EXPORT_SYMBOL(drm_bridge_remove);
>>>>>
>>>>>  /**
>>>>> - * drm_bridge_attach - associate given bridge to our DRM device
>>>>> + * drm_bridge_attach - attach the bridge to an encoder's chain
>>>>>   *
>>>>> - * @dev: DRM device
>>>>> - * @bridge: bridge control structure
>>>>> + * @encoder: DRM encoder
>>>>> + * @bridge: bridge to attach
>>>>> + * @previous: previous bridge in the chain (optional)
>>>>>   *
>>>>> - * Called by a kms driver to link one of our encoder/bridge to the
>>>>> given
>>>>> - * bridge.
>>>>> + * Called by a kms driver to link the bridge to an encoder's chain. The
>>>>> previous
>>>>> + * argument specifies the previous bridge in the chain. If NULL, the
>>>>> bridge is
>>>>> + * linked directly at the encoder's output. Otherwise it is linked at
>>>>> the
>>>>> + * previous bridge's output.
>>>>>   *
>>>>> - * Note that setting up links between the bridge and our encoder/bridge
>>>>> - * objects needs to be handled by the kms driver itself.
>>>>> + * If non-NULL the previous bridge must be already attached by a call
>>>>> to this
>>>>> + * function.
>>>>>   *
>>>>>   * RETURNS:
>>>>>   * Zero on success, error code on failure
>>>>>   */
>>>>> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge
>>>>> *bridge)
>>>>> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge
>>>>> *bridge,
>>>>> +		      struct drm_bridge *previous)
>>>>>  {
>>>>> -	if (!dev || !bridge)
>>>>> +	int ret;
>>>>> +
>>>>> +	if (!encoder || !bridge)
>>>>> +		return -EINVAL;
>>>>
>>>> I think we could derive previous from the encoder itself. Something like:
>>>> 	previous = encoder->bridge;
>>>> 	while (previous && previous->next)
>>>> 	
>>>> 		previous = previous->next;
>>>
>>> That's a very good point. It would however prevent us from catching
>>> drivers that attach bridges in the wrong order, which the !previous->dev
>>> currently allows us to do (and it should be turned into a WARN_ON as
>>> Daniel proposed).
>>
>> With the simpler API, I don't think we will ever hit the case of
>> !previous->dev. The previous bridge (if it exists) in the chain would
>> already have a dev attached to it. In other words, we would remove the
>> risk of the chance of the 'previous' bridge being unattached.
>>
>> I'm a bit unclear about what you mean about the order part. If a kms driver
>> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
>>
>> drm_bridge_attach(encoder, bridge1, NULL);
>> drm_bridge_attach(encoder, bridge2, bridge1);
>
> Correct.
>
>> We can't do much if the kms driver does the opposite:
>>
>> drm_bridge_attach(encoder, bridge2, NULL);
>> drm_bridge_attach(encoder, bridge2, bridge1);
>
> That would certainly be a very stupid thing for a driver to do :-) The problem
> that we could catch with my current proposal is
>
> drm_bridge_attach(encoder, bridge2, bridge1);
> ...
> drm_bridge_attach(encoder, bridge1, NULL);
>
> which I expect to happen from time to time as the two bridge can be attached
> through separate code paths sometimes a bit difficult to trace. It's not a big
> deal though, you could convince me that the advantages of a simpler API exceed
> its drawbacks.

Having no 'previous' argument would prevent the possibility of this altogether,
won't it?

With no 'previous' arg in the API, the driver can only do:

drm_bridge_attach(encoder, bridge1);
drm_bridge_attach(encoder, bridge2);

or

drm_bridge_attach(encoder, bridge2);
drm_bridge_attach(encoder, bridge1);

For the latter, we can't do much as discussed above.

Archit

>
>>> I'm fine losing that ability, as your proposal makes the API simpler. I'll
>>> let you decide, which option do you prefer ?
>>
>> I prefer the simpler API. I guess the main aim of the patch was to prevent
>> the driver setting up the encoder<->bridge links, which will be done
>> anyway.
>
> If you still prefer the simpler API after reading the above, I'll update my
> patch.
>
>>>>> +
>>>>> +	if (previous && (!previous->dev || previous->encoder != encoder))
>>>>>  		return -EINVAL;
>>>>>  	
>>>>>  	if (bridge->dev)
>>>>>  		return -EBUSY;
>>>>>
>>>>> -	bridge->dev = dev;
>>>>> +	bridge->dev = encoder->dev;
>>>>> +	bridge->encoder = encoder;
>>>>> +
>>>>> +	if (bridge->funcs->attach) {
>>>>> +		ret = bridge->funcs->attach(bridge);
>>>>> +		if (ret < 0) {
>>>>> +			bridge->dev = NULL;
>>>>> +			bridge->encoder = NULL;
>>>>> +			return ret;
>>>>> +		}
>>>>> +	}
>>>>>
>>>>> -	if (bridge->funcs->attach)
>>>>> -		return bridge->funcs->attach(bridge);
>>>>> +	if (previous)
>>>>> +		previous->next = bridge;
>>>>> +	else
>>>>> +		encoder->bridge = bridge;
>>>>>
>>>>>  	return 0;
>>>>>  }
>>>>
>>>> <snip>
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-30 11:00             ` Archit Taneja
@ 2016-11-30 11:05               ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-30 11:05 UTC (permalink / raw)
  To: Archit Taneja
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard, Vincent Abriou, Maxime Ripard

Hi Archit,

On Wednesday 30 Nov 2016 16:30:53 Archit Taneja wrote:
> On 11/30/2016 03:53 PM, Laurent Pinchart wrote:
> > On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
> >> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
> >>> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
> >>>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> >>>>> Instead of linking encoders and bridges in every driver (and getting
> >>>>> it wrong half of the time, as many drivers forget to set the
> >>>>> drm_bridge encoder pointer), do so in core code. The
> >>>>> drm_bridge_attach() function needs the encoder and optional previous
> >>>>> bridge to perform that task, update all the callers.
> >>>>> 
> >>>>> Signed-off-by: Laurent Pinchart
> >>>>> <laurent.pinchart+renesas@ideasonboard.com>
> >>>>> ---

[snip]

> >>>> I think we could derive previous from the encoder itself. Something
> >>>> like:
> >>>>
> >>>> 	previous = encoder->bridge;
> >>>> 	while (previous && previous->next)
> >>>> 		previous = previous->next;
> >>> 
> >>> That's a very good point. It would however prevent us from catching
> >>> drivers that attach bridges in the wrong order, which the !previous->dev
> >>> currently allows us to do (and it should be turned into a WARN_ON as
> >>> Daniel proposed).
> >> 
> >> With the simpler API, I don't think we will ever hit the case of
> >> !previous->dev. The previous bridge (if it exists) in the chain would
> >> already have a dev attached to it. In other words, we would remove the
> >> risk of the chance of the 'previous' bridge being unattached.
> >> 
> >> I'm a bit unclear about what you mean about the order part. If a kms
> >> driver
> >> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
> >> 
> >> drm_bridge_attach(encoder, bridge1, NULL);
> >> drm_bridge_attach(encoder, bridge2, bridge1);
> > 
> > Correct.
> > 
> >> We can't do much if the kms driver does the opposite:
> >> 
> >> drm_bridge_attach(encoder, bridge2, NULL);
> >> drm_bridge_attach(encoder, bridge2, bridge1);
> > 
> > That would certainly be a very stupid thing for a driver to do :-) The
> > problem that we could catch with my current proposal is
> > 
> > drm_bridge_attach(encoder, bridge2, bridge1);
> > ...
> > drm_bridge_attach(encoder, bridge1, NULL);
> > 
> > which I expect to happen from time to time as the two bridge can be
> > attached through separate code paths sometimes a bit difficult to trace.
> > It's not a big deal though, you could convince me that the advantages of
> > a simpler API exceed its drawbacks.
> 
> Having no 'previous' argument would prevent the possibility of this
> altogether, won't it?
> 
> With no 'previous' arg in the API, the driver can only do:
> 
> drm_bridge_attach(encoder, bridge1);
> drm_bridge_attach(encoder, bridge2);
> 
> or
> 
> drm_bridge_attach(encoder, bridge2);
> drm_bridge_attach(encoder, bridge1);

Correct.

> For the latter, we can't do much as discussed above.

Except that with the currently proposed API the code would be

drm_bridge_attach(encoder, bridge2, bridge1);
drm_bridge_attach(encoder, bridge1, NULL);

(correct case)

or

drm_bridge_attach(encoder, bridge2, bridge1);
drm_bridge_attach(encoder, bridge1, NULL);

(incorrect case)

The second one could be caught by the drm_bridge_attach() function as bridge1-
>dev will be NULL when attaching bridge2 in the incorrect case.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-30 11:05               ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2016-11-30 11:05 UTC (permalink / raw)
  To: Archit Taneja
  Cc: Laurent Pinchart, Alison Wang, Jingoo Han, Seung-Woo Kim,
	Xinwei Kong, dri-devel, linux-renesas-soc, Kyungmin Park,
	Xinliang Liu, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou

Hi Archit,

On Wednesday 30 Nov 2016 16:30:53 Archit Taneja wrote:
> On 11/30/2016 03:53 PM, Laurent Pinchart wrote:
> > On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
> >> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
> >>> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
> >>>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
> >>>>> Instead of linking encoders and bridges in every driver (and getting
> >>>>> it wrong half of the time, as many drivers forget to set the
> >>>>> drm_bridge encoder pointer), do so in core code. The
> >>>>> drm_bridge_attach() function needs the encoder and optional previous
> >>>>> bridge to perform that task, update all the callers.
> >>>>> 
> >>>>> Signed-off-by: Laurent Pinchart
> >>>>> <laurent.pinchart+renesas@ideasonboard.com>
> >>>>> ---

[snip]

> >>>> I think we could derive previous from the encoder itself. Something
> >>>> like:
> >>>>
> >>>> 	previous = encoder->bridge;
> >>>> 	while (previous && previous->next)
> >>>> 		previous = previous->next;
> >>> 
> >>> That's a very good point. It would however prevent us from catching
> >>> drivers that attach bridges in the wrong order, which the !previous->dev
> >>> currently allows us to do (and it should be turned into a WARN_ON as
> >>> Daniel proposed).
> >> 
> >> With the simpler API, I don't think we will ever hit the case of
> >> !previous->dev. The previous bridge (if it exists) in the chain would
> >> already have a dev attached to it. In other words, we would remove the
> >> risk of the chance of the 'previous' bridge being unattached.
> >> 
> >> I'm a bit unclear about what you mean about the order part. If a kms
> >> driver
> >> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
> >> 
> >> drm_bridge_attach(encoder, bridge1, NULL);
> >> drm_bridge_attach(encoder, bridge2, bridge1);
> > 
> > Correct.
> > 
> >> We can't do much if the kms driver does the opposite:
> >> 
> >> drm_bridge_attach(encoder, bridge2, NULL);
> >> drm_bridge_attach(encoder, bridge2, bridge1);
> > 
> > That would certainly be a very stupid thing for a driver to do :-) The
> > problem that we could catch with my current proposal is
> > 
> > drm_bridge_attach(encoder, bridge2, bridge1);
> > ...
> > drm_bridge_attach(encoder, bridge1, NULL);
> > 
> > which I expect to happen from time to time as the two bridge can be
> > attached through separate code paths sometimes a bit difficult to trace.
> > It's not a big deal though, you could convince me that the advantages of
> > a simpler API exceed its drawbacks.
> 
> Having no 'previous' argument would prevent the possibility of this
> altogether, won't it?
> 
> With no 'previous' arg in the API, the driver can only do:
> 
> drm_bridge_attach(encoder, bridge1);
> drm_bridge_attach(encoder, bridge2);
> 
> or
> 
> drm_bridge_attach(encoder, bridge2);
> drm_bridge_attach(encoder, bridge1);

Correct.

> For the latter, we can't do much as discussed above.

Except that with the currently proposed API the code would be

drm_bridge_attach(encoder, bridge2, bridge1);
drm_bridge_attach(encoder, bridge1, NULL);

(correct case)

or

drm_bridge_attach(encoder, bridge2, bridge1);
drm_bridge_attach(encoder, bridge1, NULL);

(incorrect case)

The second one could be caught by the drm_bridge_attach() function as bridge1-
>dev will be NULL when attaching bridge2 in the incorrect case.

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-30 11:05               ` Laurent Pinchart
@ 2016-11-30 13:27                 ` Archit Taneja
  -1 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-30 13:27 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, linux-renesas-soc, Boris Brezillon,
	Jingoo Han, Inki Dae, Joonyoung Shim, Seung-Woo Kim,
	Kyungmin Park, Stefan Agner, Alison Wang, Xinliang Liu,
	Rongrong Zou, Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu,
	Rob Clark, Benjamin Gaignard, Vincent Abriou, Maxime Ripard



On 11/30/2016 4:35 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Wednesday 30 Nov 2016 16:30:53 Archit Taneja wrote:
>> On 11/30/2016 03:53 PM, Laurent Pinchart wrote:
>>> On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
>>>> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
>>>>> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
>>>>>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
>>>>>>> Instead of linking encoders and bridges in every driver (and getting
>>>>>>> it wrong half of the time, as many drivers forget to set the
>>>>>>> drm_bridge encoder pointer), do so in core code. The
>>>>>>> drm_bridge_attach() function needs the encoder and optional previous
>>>>>>> bridge to perform that task, update all the callers.
>>>>>>>
>>>>>>> Signed-off-by: Laurent Pinchart
>>>>>>> <laurent.pinchart+renesas@ideasonboard.com>
>>>>>>> ---
>
> [snip]
>
>>>>>> I think we could derive previous from the encoder itself. Something
>>>>>> like:
>>>>>>
>>>>>> 	previous = encoder->bridge;
>>>>>> 	while (previous && previous->next)
>>>>>> 		previous = previous->next;
>>>>>
>>>>> That's a very good point. It would however prevent us from catching
>>>>> drivers that attach bridges in the wrong order, which the !previous->dev
>>>>> currently allows us to do (and it should be turned into a WARN_ON as
>>>>> Daniel proposed).
>>>>
>>>> With the simpler API, I don't think we will ever hit the case of
>>>> !previous->dev. The previous bridge (if it exists) in the chain would
>>>> already have a dev attached to it. In other words, we would remove the
>>>> risk of the chance of the 'previous' bridge being unattached.
>>>>
>>>> I'm a bit unclear about what you mean about the order part. If a kms
>>>> driver
>>>> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
>>>>
>>>> drm_bridge_attach(encoder, bridge1, NULL);
>>>> drm_bridge_attach(encoder, bridge2, bridge1);
>>>
>>> Correct.
>>>
>>>> We can't do much if the kms driver does the opposite:
>>>>
>>>> drm_bridge_attach(encoder, bridge2, NULL);
>>>> drm_bridge_attach(encoder, bridge2, bridge1);
>>>
>>> That would certainly be a very stupid thing for a driver to do :-) The
>>> problem that we could catch with my current proposal is
>>>
>>> drm_bridge_attach(encoder, bridge2, bridge1);
>>> ...
>>> drm_bridge_attach(encoder, bridge1, NULL);
>>>
>>> which I expect to happen from time to time as the two bridge can be
>>> attached through separate code paths sometimes a bit difficult to trace.
>>> It's not a big deal though, you could convince me that the advantages of
>>> a simpler API exceed its drawbacks.
>>
>> Having no 'previous' argument would prevent the possibility of this
>> altogether, won't it?
>>
>> With no 'previous' arg in the API, the driver can only do:
>>
>> drm_bridge_attach(encoder, bridge1);
>> drm_bridge_attach(encoder, bridge2);
>>
>> or
>>
>> drm_bridge_attach(encoder, bridge2);
>> drm_bridge_attach(encoder, bridge1);
>
> Correct.
>
>> For the latter, we can't do much as discussed above.
>
> Except that with the currently proposed API the code would be
>
> drm_bridge_attach(encoder, bridge2, bridge1);
> drm_bridge_attach(encoder, bridge1, NULL);
>
> (correct case)
>
> or
>
> drm_bridge_attach(encoder, bridge2, bridge1);
> drm_bridge_attach(encoder, bridge1, NULL);
>
> (incorrect case)
>
> The second one could be caught by the drm_bridge_attach() function as bridge1-
>> dev will be NULL when attaching bridge2 in the incorrect case.

Okay, I got it now.

As you said, it does make sense for cases like analogix_dp, where one
attach is in the bridge driver, and the other is in the kms driver.
It makes things more legible too. Passing 'previous' as NULL makes it
clear in the code that we're attaching first bridge in the chain.
Let's stick to your proposal.

One additional thing we could do is to compare the 'previous' arg
passed by the API with the last bridge in the chain, and return
an error if they aren't the same, just as an additional safety
measure.

Archit

>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-30 13:27                 ` Archit Taneja
  0 siblings, 0 replies; 100+ messages in thread
From: Archit Taneja @ 2016-11-30 13:27 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, Alison Wang, Jingoo Han, Seung-Woo Kim,
	Xinwei Kong, dri-devel, linux-renesas-soc, Kyungmin Park,
	Xinliang Liu, Chen Feng, Rongrong Zou, Maxime Ripard,
	Vincent Abriou



On 11/30/2016 4:35 PM, Laurent Pinchart wrote:
> Hi Archit,
>
> On Wednesday 30 Nov 2016 16:30:53 Archit Taneja wrote:
>> On 11/30/2016 03:53 PM, Laurent Pinchart wrote:
>>> On Wednesday 30 Nov 2016 10:35:02 Archit Taneja wrote:
>>>> On 11/29/2016 11:27 PM, Laurent Pinchart wrote:
>>>>> On Tuesday 29 Nov 2016 15:57:06 Archit Taneja wrote:
>>>>>> On 11/29/2016 02:34 PM, Laurent Pinchart wrote:
>>>>>>> Instead of linking encoders and bridges in every driver (and getting
>>>>>>> it wrong half of the time, as many drivers forget to set the
>>>>>>> drm_bridge encoder pointer), do so in core code. The
>>>>>>> drm_bridge_attach() function needs the encoder and optional previous
>>>>>>> bridge to perform that task, update all the callers.
>>>>>>>
>>>>>>> Signed-off-by: Laurent Pinchart
>>>>>>> <laurent.pinchart+renesas@ideasonboard.com>
>>>>>>> ---
>
> [snip]
>
>>>>>> I think we could derive previous from the encoder itself. Something
>>>>>> like:
>>>>>>
>>>>>> 	previous = encoder->bridge;
>>>>>> 	while (previous && previous->next)
>>>>>> 		previous = previous->next;
>>>>>
>>>>> That's a very good point. It would however prevent us from catching
>>>>> drivers that attach bridges in the wrong order, which the !previous->dev
>>>>> currently allows us to do (and it should be turned into a WARN_ON as
>>>>> Daniel proposed).
>>>>
>>>> With the simpler API, I don't think we will ever hit the case of
>>>> !previous->dev. The previous bridge (if it exists) in the chain would
>>>> already have a dev attached to it. In other words, we would remove the
>>>> risk of the chance of the 'previous' bridge being unattached.
>>>>
>>>> I'm a bit unclear about what you mean about the order part. If a kms
>>>> driver
>>>> wants to create a chain: encoder->bridge1->bridge2, it should ideally do:
>>>>
>>>> drm_bridge_attach(encoder, bridge1, NULL);
>>>> drm_bridge_attach(encoder, bridge2, bridge1);
>>>
>>> Correct.
>>>
>>>> We can't do much if the kms driver does the opposite:
>>>>
>>>> drm_bridge_attach(encoder, bridge2, NULL);
>>>> drm_bridge_attach(encoder, bridge2, bridge1);
>>>
>>> That would certainly be a very stupid thing for a driver to do :-) The
>>> problem that we could catch with my current proposal is
>>>
>>> drm_bridge_attach(encoder, bridge2, bridge1);
>>> ...
>>> drm_bridge_attach(encoder, bridge1, NULL);
>>>
>>> which I expect to happen from time to time as the two bridge can be
>>> attached through separate code paths sometimes a bit difficult to trace.
>>> It's not a big deal though, you could convince me that the advantages of
>>> a simpler API exceed its drawbacks.
>>
>> Having no 'previous' argument would prevent the possibility of this
>> altogether, won't it?
>>
>> With no 'previous' arg in the API, the driver can only do:
>>
>> drm_bridge_attach(encoder, bridge1);
>> drm_bridge_attach(encoder, bridge2);
>>
>> or
>>
>> drm_bridge_attach(encoder, bridge2);
>> drm_bridge_attach(encoder, bridge1);
>
> Correct.
>
>> For the latter, we can't do much as discussed above.
>
> Except that with the currently proposed API the code would be
>
> drm_bridge_attach(encoder, bridge2, bridge1);
> drm_bridge_attach(encoder, bridge1, NULL);
>
> (correct case)
>
> or
>
> drm_bridge_attach(encoder, bridge2, bridge1);
> drm_bridge_attach(encoder, bridge1, NULL);
>
> (incorrect case)
>
> The second one could be caught by the drm_bridge_attach() function as bridge1-
>> dev will be NULL when attaching bridge2 in the incorrect case.

Okay, I got it now.

As you said, it does make sense for cases like analogix_dp, where one
attach is in the bridge driver, and the other is in the kms driver.
It makes things more legible too. Passing 'previous' as NULL makes it
clear in the code that we're attaching first bridge in the chain.
Let's stick to your proposal.

One additional thing we could do is to compare the 'previous' arg
passed by the API with the last bridge in the chain, and return
an error if they aren't the same, just as an additional safety
measure.

Archit

>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 11/13] drm: Set on-chip bridges' encoder type
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-30 15:28     ` Vincent ABRIOU
  -1 siblings, 0 replies; 100+ messages in thread
From: Vincent ABRIOU @ 2016-11-30 15:28 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Dae, Joonyoung Shim,
	Seung-Woo Kim, Kyungmin Park, CK Hu, Philipp Zabel,
	Benjamin Gaignard



On 11/29/2016 10:04 AM, Laurent Pinchart wrote:
> Initialize the new drm_bridge::encoder_type field to the right value for
> all bridges that model on-SoC IP cores.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_mic.c | 2 ++
>  drivers/gpu/drm/mediatek/mtk_hdmi.c     | 2 ++
>  drivers/gpu/drm/sti/sti_dvo.c           | 2 ++
>  3 files changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> index a0def0be6d65..7175ecda36e8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -390,6 +390,8 @@ static int exynos_mic_bind(struct device *dev, struct device *master,
>  	mic->bridge.funcs = &mic_bridge_funcs;
>  	mic->bridge.of_node = dev->of_node;
>  	mic->bridge.driver_private = mic;
> +	mic->bridge.encoder_type = DRM_MODE_ENCODER_DSI;
> +
>  	ret = drm_bridge_add(&mic->bridge);
>  	if (ret)
>  		DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 5ca1b0fbf937..bb5cf594c721 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1712,6 +1712,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
>
>  	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
>  	hdmi->bridge.of_node = pdev->dev.of_node;
> +	hdmi->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
> +
>  	ret = drm_bridge_add(&hdmi->bridge);
>  	if (ret) {
>  		dev_err(dev, "failed to add bridge, ret = %d\n", ret);
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index 411dc6ec976e..8912c932078f 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -472,6 +472,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  	bridge->driver_private = dvo;
>  	bridge->funcs = &sti_dvo_bridge_funcs;
>  	bridge->of_node = dvo->dev.of_node;
> +	bridge->encoder_type = DRM_MODE_ENCODER_LVDS;
> +
>  	err = drm_bridge_add(bridge);
>  	if (err) {
>  		DRM_ERROR("Failed to add bridge\n");

For the sti dvo part:
Acked-by: Vincent Abriou <vincent.abriou@st.com>

Vincent
>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 11/13] drm: Set on-chip bridges' encoder type
@ 2016-11-30 15:28     ` Vincent ABRIOU
  0 siblings, 0 replies; 100+ messages in thread
From: Vincent ABRIOU @ 2016-11-30 15:28 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: Seung-Woo Kim, linux-renesas-soc, Kyungmin Park



On 11/29/2016 10:04 AM, Laurent Pinchart wrote:
> Initialize the new drm_bridge::encoder_type field to the right value for
> all bridges that model on-SoC IP cores.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_mic.c | 2 ++
>  drivers/gpu/drm/mediatek/mtk_hdmi.c     | 2 ++
>  drivers/gpu/drm/sti/sti_dvo.c           | 2 ++
>  3 files changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> index a0def0be6d65..7175ecda36e8 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
> @@ -390,6 +390,8 @@ static int exynos_mic_bind(struct device *dev, struct device *master,
>  	mic->bridge.funcs = &mic_bridge_funcs;
>  	mic->bridge.of_node = dev->of_node;
>  	mic->bridge.driver_private = mic;
> +	mic->bridge.encoder_type = DRM_MODE_ENCODER_DSI;
> +
>  	ret = drm_bridge_add(&mic->bridge);
>  	if (ret)
>  		DRM_ERROR("mic: Failed to add MIC to the global bridge list\n");
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 5ca1b0fbf937..bb5cf594c721 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -1712,6 +1712,8 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev)
>
>  	hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
>  	hdmi->bridge.of_node = pdev->dev.of_node;
> +	hdmi->bridge.encoder_type = DRM_MODE_ENCODER_TMDS;
> +
>  	ret = drm_bridge_add(&hdmi->bridge);
>  	if (ret) {
>  		dev_err(dev, "failed to add bridge, ret = %d\n", ret);
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index 411dc6ec976e..8912c932078f 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -472,6 +472,8 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>  	bridge->driver_private = dvo;
>  	bridge->funcs = &sti_dvo_bridge_funcs;
>  	bridge->of_node = dvo->dev.of_node;
> +	bridge->encoder_type = DRM_MODE_ENCODER_LVDS;
> +
>  	err = drm_bridge_add(bridge);
>  	if (err) {
>  		DRM_ERROR("Failed to add bridge\n");

For the sti dvo part:
Acked-by: Vincent Abriou <vincent.abriou@st.com>

Vincent
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
  2016-11-29  9:04   ` Laurent Pinchart
@ 2016-11-30 15:30     ` Vincent ABRIOU
  -1 siblings, 0 replies; 100+ messages in thread
From: Vincent ABRIOU @ 2016-11-30 15:30 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: linux-renesas-soc, Archit Taneja, Boris Brezillon, Jingoo Han,
	Inki Dae, Joonyoung Shim, Seung-Woo Kim, Kyungmin Park,
	Stefan Agner, Alison Wang, Xinliang Liu, Rongrong Zou,
	Xinwei Kong, Chen Feng, Philipp Zabel, CK Hu, Rob Clark,
	Benjamin Gaignard, Maxime Ripard



On 11/29/2016 10:04 AM, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-

Hi Laurent,

For sti dvo, hda and hdmi:
Acked-by: Vincent Abriou <vincent.abriou@st.com>

Vincent

>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
>
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>         of_node_put(np);
>
>         if (bridge) {
> -               output->encoder.bridge = bridge;
> -               bridge->encoder = &output->encoder;
> -               ret = drm_bridge_attach(dev, bridge);
> +               ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>                 if (!ret)
>                         return 0;
>         }
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>
>         dp->bridge = bridge;
>
> -       dp->encoder->bridge = bridge;
>         bridge->driver_private = dp;
> -       bridge->encoder = dp->encoder;
>         bridge->funcs = &analogix_dp_bridge_funcs;
>
> -       ret = drm_bridge_attach(drm_dev, bridge);
> +       ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>         if (ret) {
>                 DRM_ERROR("failed to attach drm bridge\n");
>                 return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>         hdmi->bridge = bridge;
>         bridge->driver_private = hdmi;
>         bridge->funcs = &dw_hdmi_bridge_funcs;
> -       ret = drm_bridge_attach(drm, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret) {
>                 DRM_ERROR("Failed to initialize bridge with drm\n");
>                 return -EINVAL;
>         }
>
> -       encoder->bridge = bridge;
>         hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>
>         drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +                     struct drm_bridge *previous)
>  {
> -       if (!dev || !bridge)
> +       int ret;
> +
> +       if (!encoder || !bridge)
> +               return -EINVAL;
> +
> +       if (previous && (!previous->dev || previous->encoder != encoder))
>                 return -EINVAL;
>
>         if (bridge->dev)
>                 return -EBUSY;
>
> -       bridge->dev = dev;
> +       bridge->dev = encoder->dev;
> +       bridge->encoder = encoder;
> +
> +       if (bridge->funcs->attach) {
> +               ret = bridge->funcs->attach(bridge);
> +               if (ret < 0) {
> +                       bridge->dev = NULL;
> +                       bridge->encoder = NULL;
> +                       return ret;
> +               }
> +       }
>
> -       if (bridge->funcs->attach)
> -               return bridge->funcs->attach(bridge);
> +       if (previous)
> +               previous->next = bridge;
> +       else
> +               encoder->bridge = bridge;
>
>         return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>                                           struct drm_bridge *bridge)
>  {
> -       bridge->encoder = &pipe->encoder;
> -       pipe->encoder.bridge = bridge;
> -       return drm_bridge_attach(pipe->encoder.dev, bridge);
> +       return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>                                    struct drm_connector *connector)
>  {
>         struct exynos_dp_device *dp = to_dp(plat_data);
> -       struct drm_encoder *encoder = &dp->encoder;
>         int ret;
>
>         drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>
>         /* Pre-empt DP connector creation if there's a bridge */
>         if (dp->ptn_bridge) {
> -               bridge->next = dp->ptn_bridge;
> -               dp->ptn_bridge->encoder = encoder;
> -               ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +               ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>                 if (ret) {
>                         DRM_ERROR("Failed to attach bridge to drm\n");
>                         bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>         }
>
>         bridge = of_drm_find_bridge(dsi->bridge_node);
> -       if (bridge) {
> -               encoder->bridge = bridge;
> -               drm_bridge_attach(drm_dev, bridge);
> -       }
> +       if (bridge)
> +               drm_bridge_attach(encoder, bridge, NULL);
>
>         return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
>         if (!bridge)
>                 return -ENODEV;
>
> -       fsl_dev->encoder.bridge = bridge;
> -       bridge->encoder = &fsl_dev->encoder;
> -
> -       return drm_bridge_attach(fsl_dev->drm, bridge);
> +       return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>         int ret;
>
>         /* associate the bridge to dsi encoder */
> -       encoder->bridge = bridge;
> -       bridge->encoder = encoder;
> -
> -       ret = drm_bridge_attach(dev, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret) {
>                 DRM_ERROR("failed to attach external bridge\n");
>                 return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>                          DRM_MODE_ENCODER_LVDS, NULL);
>
>         if (imx_ldb_ch->bridge) {
> -               imx_ldb_ch->bridge->encoder = encoder;
> -
> -               imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -               ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +               ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +                                       imx_ldb_ch->bridge, NULL);
>                 if (ret) {
>                         DRM_ERROR("Failed to initialize bridge with drm\n");
>                         return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>                 drm_panel_attach(imxpd->panel, &imxpd->connector);
>
>         if (imxpd->bridge) {
> -               imxpd->bridge->encoder = encoder;
> -               encoder->bridge = imxpd->bridge;
> -               ret = drm_bridge_attach(drm, imxpd->bridge);
> +               ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>                 if (ret < 0) {
>                         dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>                                 ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>         struct mtk_ddp_comp ddp_comp;
>         struct drm_encoder encoder;
> +       struct drm_bridge *bridge;
>         void __iomem *regs;
>         struct device *dev;
>         struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>         /* Currently DPI0 is fixed to be driven by OVL1 */
>         dpi->encoder.possible_crtcs = BIT(1);
>
> -       dpi->encoder.bridge->encoder = &dpi->encoder;
> -       ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +       ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>         if (ret) {
>                 dev_err(dev, "Failed to attach bridge: %d\n", ret);
>                 goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>
>         dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>
> -       dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +       dpi->bridge = of_drm_find_bridge(bridge_node);
>         of_node_put(bridge_node);
> -       if (!dpi->encoder.bridge)
> +       if (!dpi->bridge)
>                 return -EPROBE_DEFER;
>
>         comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>         .get_modes = mtk_dsi_connector_get_modes,
>  };
>
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -                                struct drm_encoder *encoder)
> -{
> -       int ret;
> -
> -       if (!bridge)
> -               return -ENOENT;
> -
> -       encoder->bridge = bridge;
> -       bridge->encoder = encoder;
> -       ret = drm_bridge_attach(encoder->dev, bridge);
> -       if (ret) {
> -               DRM_ERROR("Failed to attach bridge to drm\n");
> -               encoder->bridge = NULL;
> -               bridge->encoder = NULL;
> -       }
> -
> -       return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>         dsi->encoder.possible_crtcs = 1;
>
>         /* If there's a bridge, attach to it and let it create the connector */
> -       ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +       ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>         if (ret) {
> +               DRM_ERROR("Failed to attach bridge to drm\n");
> +
>                 /* Otherwise create our own connector and attach to a panel */
>                 ret = mtk_dsi_create_connector(drm, dsi);
>                 if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>
>  struct mtk_hdmi {
>         struct drm_bridge bridge;
> +       struct drm_bridge *next_bridge;
>         struct drm_connector conn;
>         struct device *dev;
>         struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>                 return ret;
>         }
>
> -       if (bridge->next) {
> -               bridge->next->encoder = bridge->encoder;
> -               ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +       if (hdmi->next_bridge) {
> +               ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +                                       bridge);
>                 if (ret) {
>                         dev_err(hdmi->dev,
>                                 "Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>         of_node_put(ep);
>
>         if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -               hdmi->bridge.next = of_drm_find_bridge(remote);
> -               if (!hdmi->bridge.next) {
> +               hdmi->next_bridge = of_drm_find_bridge(remote);
> +               if (!hdmi->next_bridge) {
>                         dev_err(dev, "Waiting for external bridge\n");
>                         of_node_put(remote);
>                         return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>         struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>         struct drm_bridge *bridge = NULL;
>         struct dsi_bridge *dsi_bridge;
> +       struct drm_encoder *encoder;
>         int ret;
>
>         dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>
>         dsi_bridge->id = id;
>
> +       /*
> +        * HACK: we may not know the external DSI bridge device's mode
> +        * flags here. We'll get to know them only when the device
> +        * attaches to the dsi host. For now, assume the bridge supports
> +        * DSI video mode
> +        */
> +       encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>         bridge = &dsi_bridge->base;
>         bridge->funcs = &dsi_mgr_bridge_funcs;
>
> -       ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret)
>                 goto fail;
>
> @@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>         encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>
>         /* link the internal dsi bridge to the external bridge */
> -       int_bridge->next = ext_bridge;
> -       /* set the external bridge's encoder as dsi's encoder */
> -       ext_bridge->encoder = encoder;
> -
> -       drm_bridge_attach(dev, ext_bridge);
> +       drm_bridge_attach(encoder, ext_bridge, int_bridge);
>
>         /*
>          * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>         bridge = &edp_bridge->base;
>         bridge->funcs = &edp_bridge_funcs;
>
> -       ret = drm_bridge_attach(edp->dev, bridge);
> +       ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>         if (ret)
>                 goto fail;
>
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>         bridge = &hdmi_bridge->base;
>         bridge->funcs = &msm_hdmi_bridge_funcs;
>
> -       ret = drm_bridge_attach(hdmi->dev, bridge);
> +       ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>         if (ret)
>                 goto fail;
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>         hdmienc->renc = renc;
>
>         /* Link the bridge to the encoder. */
> -       bridge->encoder = encoder;
> -       encoder->bridge = bridge;
> -
> -       ret = drm_bridge_attach(rcdu->ddev, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret) {
>                 drm_encoder_cleanup(encoder);
>                 return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>                 return err;
>         }
>
> -       err = drm_bridge_attach(drm_dev, bridge);
> +       err = drm_bridge_attach(encoder, bridge, NULL);
>         if (err) {
>                 DRM_ERROR("Failed to attach bridge\n");
>                 return err;
>         }
>
>         dvo->bridge = bridge;
> -       encoder->bridge = bridge;
>         connector->encoder = encoder;
>         dvo->encoder = encoder;
>
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>
>         bridge->driver_private = hda;
>         bridge->funcs = &sti_hda_bridge_funcs;
> -       drm_bridge_attach(drm_dev, bridge);
> +       drm_bridge_attach(encoder, bridge, NULL);
>
> -       encoder->bridge = bridge;
>         connector->encoder = encoder;
>
>         drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         bridge->driver_private = hdmi;
>         bridge->funcs = &sti_hdmi_bridge_funcs;
> -       drm_bridge_attach(drm_dev, bridge);
> +       drm_bridge_attach(encoder, bridge, NULL);
>
> -       encoder->bridge = bridge;
>         connector->encoder = encoder;
>
>         drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>         struct sun4i_drv *drv = drm->dev_private;
>         struct sun4i_tcon *tcon = drv->tcon;
>         struct drm_encoder *encoder;
> +       struct drm_bridge *bridge;
>         struct sun4i_rgb *rgb;
>         int ret;
>
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>         encoder = &rgb->encoder;
>
>         tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -       encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -       if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +       bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +       if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>                 dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>                 return 0;
>         }
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>                 }
>         }
>
> -       if (!IS_ERR(encoder->bridge)) {
> -               encoder->bridge->encoder = &rgb->encoder;
> -
> -               ret = drm_bridge_attach(drm, encoder->bridge);
> +       if (!IS_ERR(bridge)) {
> +               ret = drm_bridge_attach(encoder, bridge, NULL);
>                 if (ret) {
>                         dev_err(drm->dev, "Couldn't attach our bridge\n");
>                         goto err_cleanup_connector;
>                 }
> -       } else {
> -               encoder->bridge = NULL;
>         }
>
>         return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +                     struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
> --
> Regards,
>
> Laurent Pinchart
>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code
@ 2016-11-30 15:30     ` Vincent ABRIOU
  0 siblings, 0 replies; 100+ messages in thread
From: Vincent ABRIOU @ 2016-11-30 15:30 UTC (permalink / raw)
  To: Laurent Pinchart, dri-devel
  Cc: Alison Wang, Jingoo Han, Seung-Woo Kim, Xinwei Kong,
	linux-renesas-soc, Kyungmin Park, Xinliang Liu, Chen Feng,
	Rongrong Zou, Maxime Ripard



On 11/29/2016 10:04 AM, Laurent Pinchart wrote:
> Instead of linking encoders and bridges in every driver (and getting it
> wrong half of the time, as many drivers forget to set the drm_bridge
> encoder pointer), do so in core code. The drm_bridge_attach() function
> needs the encoder and optional previous bridge to perform that task,
> update all the callers.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c   |  4 +-
>  drivers/gpu/drm/bridge/analogix/analogix_dp_core.c |  4 +-
>  drivers/gpu/drm/bridge/dw-hdmi.c                   |  3 +-
>  drivers/gpu/drm/drm_bridge.c                       | 46 ++++++++++++++++------
>  drivers/gpu/drm/drm_simple_kms_helper.c            |  4 +-
>  drivers/gpu/drm/exynos/exynos_dp.c                 |  5 +--
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c            |  6 +--
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |  5 +--
>  drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c       |  5 +--
>  drivers/gpu/drm/imx/imx-ldb.c                      |  6 +--
>  drivers/gpu/drm/imx/parallel-display.c             |  4 +-
>  drivers/gpu/drm/mediatek/mtk_dpi.c                 |  8 ++--
>  drivers/gpu/drm/mediatek/mtk_dsi.c                 | 24 ++---------
>  drivers/gpu/drm/mediatek/mtk_hdmi.c                | 11 +++---
>  drivers/gpu/drm/msm/dsi/dsi_manager.c              | 17 +++++---
>  drivers/gpu/drm/msm/edp/edp_bridge.c               |  2 +-
>  drivers/gpu/drm/msm/hdmi/hdmi_bridge.c             |  2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c          |  5 +--
>  drivers/gpu/drm/sti/sti_dvo.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hda.c                      |  3 +-
>  drivers/gpu/drm/sti/sti_hdmi.c                     |  3 +-

Hi Laurent,

For sti dvo, hda and hdmi:
Acked-by: Vincent Abriou <vincent.abriou@st.com>

Vincent

>  drivers/gpu/drm/sun4i/sun4i_rgb.c                  | 13 +++---
>  include/drm/drm_bridge.h                           |  3 +-
>  23 files changed, 83 insertions(+), 103 deletions(-)
>
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> index 6119b5085501..e7799b6ee829 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
> @@ -230,9 +230,7 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
>         of_node_put(np);
>
>         if (bridge) {
> -               output->encoder.bridge = bridge;
> -               bridge->encoder = &output->encoder;
> -               ret = drm_bridge_attach(dev, bridge);
> +               ret = drm_bridge_attach(&output->encoder, bridge, NULL);
>                 if (!ret)
>                         return 0;
>         }
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 6e0447f329a2..1835f1fdad19 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -1227,12 +1227,10 @@ static int analogix_dp_create_bridge(struct drm_device *drm_dev,
>
>         dp->bridge = bridge;
>
> -       dp->encoder->bridge = bridge;
>         bridge->driver_private = dp;
> -       bridge->encoder = dp->encoder;
>         bridge->funcs = &analogix_dp_bridge_funcs;
>
> -       ret = drm_bridge_attach(drm_dev, bridge);
> +       ret = drm_bridge_attach(dp->encoder, bridge, NULL);
>         if (ret) {
>                 DRM_ERROR("failed to attach drm bridge\n");
>                 return -EINVAL;
> diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
> index b71088dab268..432e0e3fff72 100644
> --- a/drivers/gpu/drm/bridge/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/dw-hdmi.c
> @@ -1841,13 +1841,12 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
>         hdmi->bridge = bridge;
>         bridge->driver_private = hdmi;
>         bridge->funcs = &dw_hdmi_bridge_funcs;
> -       ret = drm_bridge_attach(drm, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret) {
>                 DRM_ERROR("Failed to initialize bridge with drm\n");
>                 return -EINVAL;
>         }
>
> -       encoder->bridge = bridge;
>         hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
>
>         drm_connector_helper_add(&hdmi->connector,
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index 0ee052b7c21a..850bd6509ef1 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -26,6 +26,7 @@
>  #include <linux/mutex.h>
>
>  #include <drm/drm_bridge.h>
> +#include <drm/drm_encoder.h>
>
>  /**
>   * DOC: overview
> @@ -92,32 +93,53 @@ void drm_bridge_remove(struct drm_bridge *bridge)
>  EXPORT_SYMBOL(drm_bridge_remove);
>
>  /**
> - * drm_bridge_attach - associate given bridge to our DRM device
> + * drm_bridge_attach - attach the bridge to an encoder's chain
>   *
> - * @dev: DRM device
> - * @bridge: bridge control structure
> + * @encoder: DRM encoder
> + * @bridge: bridge to attach
> + * @previous: previous bridge in the chain (optional)
>   *
> - * Called by a kms driver to link one of our encoder/bridge to the given
> - * bridge.
> + * Called by a kms driver to link the bridge to an encoder's chain. The previous
> + * argument specifies the previous bridge in the chain. If NULL, the bridge is
> + * linked directly at the encoder's output. Otherwise it is linked at the
> + * previous bridge's output.
>   *
> - * Note that setting up links between the bridge and our encoder/bridge
> - * objects needs to be handled by the kms driver itself.
> + * If non-NULL the previous bridge must be already attached by a call to this
> + * function.
>   *
>   * RETURNS:
>   * Zero on success, error code on failure
>   */
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge)
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +                     struct drm_bridge *previous)
>  {
> -       if (!dev || !bridge)
> +       int ret;
> +
> +       if (!encoder || !bridge)
> +               return -EINVAL;
> +
> +       if (previous && (!previous->dev || previous->encoder != encoder))
>                 return -EINVAL;
>
>         if (bridge->dev)
>                 return -EBUSY;
>
> -       bridge->dev = dev;
> +       bridge->dev = encoder->dev;
> +       bridge->encoder = encoder;
> +
> +       if (bridge->funcs->attach) {
> +               ret = bridge->funcs->attach(bridge);
> +               if (ret < 0) {
> +                       bridge->dev = NULL;
> +                       bridge->encoder = NULL;
> +                       return ret;
> +               }
> +       }
>
> -       if (bridge->funcs->attach)
> -               return bridge->funcs->attach(bridge);
> +       if (previous)
> +               previous->next = bridge;
> +       else
> +               encoder->bridge = bridge;
>
>         return 0;
>  }
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 7bae08c2bf0a..ba7be6169339 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -182,9 +182,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
>  int drm_simple_display_pipe_attach_bridge(struct drm_simple_display_pipe *pipe,
>                                           struct drm_bridge *bridge)
>  {
> -       bridge->encoder = &pipe->encoder;
> -       pipe->encoder.bridge = bridge;
> -       return drm_bridge_attach(pipe->encoder.dev, bridge);
> +       return drm_bridge_attach(&pipe->encoder, bridge, NULL);
>  }
>  EXPORT_SYMBOL(drm_simple_display_pipe_attach_bridge);
>
> diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
> index 528229faffe4..1ef0be338b85 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp.c
> @@ -99,7 +99,6 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>                                    struct drm_connector *connector)
>  {
>         struct exynos_dp_device *dp = to_dp(plat_data);
> -       struct drm_encoder *encoder = &dp->encoder;
>         int ret;
>
>         drm_connector_register(connector);
> @@ -107,9 +106,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
>
>         /* Pre-empt DP connector creation if there's a bridge */
>         if (dp->ptn_bridge) {
> -               bridge->next = dp->ptn_bridge;
> -               dp->ptn_bridge->encoder = encoder;
> -               ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +               ret = drm_bridge_attach(&dp->encoder, dp->ptn_bridge, bridge);
>                 if (ret) {
>                         DRM_ERROR("Failed to attach bridge to drm\n");
>                         bridge->next = NULL;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index e07cb1fe4860..812e2ec0761d 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -1718,10 +1718,8 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>         }
>
>         bridge = of_drm_find_bridge(dsi->bridge_node);
> -       if (bridge) {
> -               encoder->bridge = bridge;
> -               drm_bridge_attach(drm_dev, bridge);
> -       }
> +       if (bridge)
> +               drm_bridge_attach(encoder, bridge, NULL);
>
>         return mipi_dsi_host_register(&dsi->dsi_host);
>  }
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> index e1dd75b18118..3ad76423c60d 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
> @@ -167,10 +167,7 @@ static int fsl_dcu_attach_endpoint(struct fsl_dcu_drm_device *fsl_dev,
>         if (!bridge)
>                 return -ENODEV;
>
> -       fsl_dev->encoder.bridge = bridge;
> -       bridge->encoder = &fsl_dev->encoder;
> -
> -       return drm_bridge_attach(fsl_dev->drm, bridge);
> +       return drm_bridge_attach(&fsl_dev->encoder, bridge, NULL);
>  }
>
>  int fsl_dcu_create_outputs(struct fsl_dcu_drm_device *fsl_dev)
> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> index 998452ad0fcb..1737e98bc10a 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
> @@ -709,10 +709,7 @@ static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
>         int ret;
>
>         /* associate the bridge to dsi encoder */
> -       encoder->bridge = bridge;
> -       bridge->encoder = encoder;
> -
> -       ret = drm_bridge_attach(dev, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret) {
>                 DRM_ERROR("failed to attach external bridge\n");
>                 return ret;
> diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
> index b300998dce7d..2fcb579f5489 100644
> --- a/drivers/gpu/drm/imx/imx-ldb.c
> +++ b/drivers/gpu/drm/imx/imx-ldb.c
> @@ -461,10 +461,8 @@ static int imx_ldb_register(struct drm_device *drm,
>                          DRM_MODE_ENCODER_LVDS, NULL);
>
>         if (imx_ldb_ch->bridge) {
> -               imx_ldb_ch->bridge->encoder = encoder;
> -
> -               imx_ldb_ch->encoder.bridge = imx_ldb_ch->bridge;
> -               ret = drm_bridge_attach(drm, imx_ldb_ch->bridge);
> +               ret = drm_bridge_attach(&imx_ldb_ch->encoder,
> +                                       imx_ldb_ch->bridge, NULL);
>                 if (ret) {
>                         DRM_ERROR("Failed to initialize bridge with drm\n");
>                         return ret;
> diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
> index d796ada2a47a..2d80c769f56b 100644
> --- a/drivers/gpu/drm/imx/parallel-display.c
> +++ b/drivers/gpu/drm/imx/parallel-display.c
> @@ -198,9 +198,7 @@ static int imx_pd_register(struct drm_device *drm,
>                 drm_panel_attach(imxpd->panel, &imxpd->connector);
>
>         if (imxpd->bridge) {
> -               imxpd->bridge->encoder = encoder;
> -               encoder->bridge = imxpd->bridge;
> -               ret = drm_bridge_attach(drm, imxpd->bridge);
> +               ret = drm_bridge_attach(encoder, imxpd->bridge, NULL);
>                 if (ret < 0) {
>                         dev_err(imxpd->dev, "failed to attach bridge: %d\n",
>                                 ret);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
> index 0186e500d2a5..3cced1c522fd 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dpi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
> @@ -63,6 +63,7 @@ enum mtk_dpi_out_color_format {
>  struct mtk_dpi {
>         struct mtk_ddp_comp ddp_comp;
>         struct drm_encoder encoder;
> +       struct drm_bridge *bridge;
>         void __iomem *regs;
>         struct device *dev;
>         struct clk *engine_clk;
> @@ -615,8 +616,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
>         /* Currently DPI0 is fixed to be driven by OVL1 */
>         dpi->encoder.possible_crtcs = BIT(1);
>
> -       dpi->encoder.bridge->encoder = &dpi->encoder;
> -       ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
> +       ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL);
>         if (ret) {
>                 dev_err(dev, "Failed to attach bridge: %d\n", ret);
>                 goto err_cleanup;
> @@ -713,9 +713,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
>
>         dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
>
> -       dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
> +       dpi->bridge = of_drm_find_bridge(bridge_node);
>         of_node_put(bridge_node);
> -       if (!dpi->encoder.bridge)
> +       if (!dpi->bridge)
>                 return -EPROBE_DEFER;
>
>         comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 28b2044ed9f2..2ac0f1abba86 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -597,26 +597,6 @@ static const struct drm_connector_helper_funcs
>         .get_modes = mtk_dsi_connector_get_modes,
>  };
>
> -static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
> -                                struct drm_encoder *encoder)
> -{
> -       int ret;
> -
> -       if (!bridge)
> -               return -ENOENT;
> -
> -       encoder->bridge = bridge;
> -       bridge->encoder = encoder;
> -       ret = drm_bridge_attach(encoder->dev, bridge);
> -       if (ret) {
> -               DRM_ERROR("Failed to attach bridge to drm\n");
> -               encoder->bridge = NULL;
> -               bridge->encoder = NULL;
> -       }
> -
> -       return ret;
> -}
> -
>  static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
>  {
>         int ret;
> @@ -667,8 +647,10 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
>         dsi->encoder.possible_crtcs = 1;
>
>         /* If there's a bridge, attach to it and let it create the connector */
> -       ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
> +       ret = drm_bridge_attach(&dsi->encoder, dsi->bridge, NULL);
>         if (ret) {
> +               DRM_ERROR("Failed to attach bridge to drm\n");
> +
>                 /* Otherwise create our own connector and attach to a panel */
>                 ret = mtk_dsi_create_connector(drm, dsi);
>                 if (ret)
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 71227deef21b..5ca1b0fbf937 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -149,6 +149,7 @@ struct hdmi_audio_param {
>
>  struct mtk_hdmi {
>         struct drm_bridge bridge;
> +       struct drm_bridge *next_bridge;
>         struct drm_connector conn;
>         struct device *dev;
>         struct phy *phy;
> @@ -1320,9 +1321,9 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
>                 return ret;
>         }
>
> -       if (bridge->next) {
> -               bridge->next->encoder = bridge->encoder;
> -               ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
> +       if (hdmi->next_bridge) {
> +               ret = drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
> +                                       bridge);
>                 if (ret) {
>                         dev_err(hdmi->dev,
>                                 "Failed to attach external bridge: %d\n", ret);
> @@ -1505,8 +1506,8 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
>         of_node_put(ep);
>
>         if (!of_device_is_compatible(remote, "hdmi-connector")) {
> -               hdmi->bridge.next = of_drm_find_bridge(remote);
> -               if (!hdmi->bridge.next) {
> +               hdmi->next_bridge = of_drm_find_bridge(remote);
> +               if (!hdmi->next_bridge) {
>                         dev_err(dev, "Waiting for external bridge\n");
>                         of_node_put(remote);
>                         return -EPROBE_DEFER;
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> index c8d1f19c9a6d..2bd8dad76105 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
> @@ -579,6 +579,7 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>         struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
>         struct drm_bridge *bridge = NULL;
>         struct dsi_bridge *dsi_bridge;
> +       struct drm_encoder *encoder;
>         int ret;
>
>         dsi_bridge = devm_kzalloc(msm_dsi->dev->dev,
> @@ -590,10 +591,18 @@ struct drm_bridge *msm_dsi_manager_bridge_init(u8 id)
>
>         dsi_bridge->id = id;
>
> +       /*
> +        * HACK: we may not know the external DSI bridge device's mode
> +        * flags here. We'll get to know them only when the device
> +        * attaches to the dsi host. For now, assume the bridge supports
> +        * DSI video mode
> +        */
> +       encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
> +
>         bridge = &dsi_bridge->base;
>         bridge->funcs = &dsi_mgr_bridge_funcs;
>
> -       ret = drm_bridge_attach(msm_dsi->dev, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret)
>                 goto fail;
>
> @@ -628,11 +637,7 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
>         encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
>
>         /* link the internal dsi bridge to the external bridge */
> -       int_bridge->next = ext_bridge;
> -       /* set the external bridge's encoder as dsi's encoder */
> -       ext_bridge->encoder = encoder;
> -
> -       drm_bridge_attach(dev, ext_bridge);
> +       drm_bridge_attach(encoder, ext_bridge, int_bridge);
>
>         /*
>          * we need the drm_connector created by the external bridge
> diff --git a/drivers/gpu/drm/msm/edp/edp_bridge.c b/drivers/gpu/drm/msm/edp/edp_bridge.c
> index 2bc73f82f3f5..931a5c97cccf 100644
> --- a/drivers/gpu/drm/msm/edp/edp_bridge.c
> +++ b/drivers/gpu/drm/msm/edp/edp_bridge.c
> @@ -106,7 +106,7 @@ struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp)
>         bridge = &edp_bridge->base;
>         bridge->funcs = &edp_bridge_funcs;
>
> -       ret = drm_bridge_attach(edp->dev, bridge);
> +       ret = drm_bridge_attach(edp->encoder, bridge, NULL);
>         if (ret)
>                 goto fail;
>
> diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> index bacbd5d8df0e..4e6d1bf27474 100644
> --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
> @@ -227,7 +227,7 @@ struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
>         bridge = &hdmi_bridge->base;
>         bridge->funcs = &msm_hdmi_bridge_funcs;
>
> -       ret = drm_bridge_attach(hdmi->dev, bridge);
> +       ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
>         if (ret)
>                 goto fail;
>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> index a1a2c5e7822c..933a2547798e 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
> @@ -124,10 +124,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
>         hdmienc->renc = renc;
>
>         /* Link the bridge to the encoder. */
> -       bridge->encoder = encoder;
> -       encoder->bridge = bridge;
> -
> -       ret = drm_bridge_attach(rcdu->ddev, bridge);
> +       ret = drm_bridge_attach(encoder, bridge, NULL);
>         if (ret) {
>                 drm_encoder_cleanup(encoder);
>                 return ret;
> diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
> index e8c1ed08a9f7..411dc6ec976e 100644
> --- a/drivers/gpu/drm/sti/sti_dvo.c
> +++ b/drivers/gpu/drm/sti/sti_dvo.c
> @@ -478,14 +478,13 @@ static int sti_dvo_bind(struct device *dev, struct device *master, void *data)
>                 return err;
>         }
>
> -       err = drm_bridge_attach(drm_dev, bridge);
> +       err = drm_bridge_attach(encoder, bridge, NULL);
>         if (err) {
>                 DRM_ERROR("Failed to attach bridge\n");
>                 return err;
>         }
>
>         dvo->bridge = bridge;
> -       encoder->bridge = bridge;
>         connector->encoder = encoder;
>         dvo->encoder = encoder;
>
> diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
> index e7c243f70870..5b1855e44f87 100644
> --- a/drivers/gpu/drm/sti/sti_hda.c
> +++ b/drivers/gpu/drm/sti/sti_hda.c
> @@ -714,9 +714,8 @@ static int sti_hda_bind(struct device *dev, struct device *master, void *data)
>
>         bridge->driver_private = hda;
>         bridge->funcs = &sti_hda_bridge_funcs;
> -       drm_bridge_attach(drm_dev, bridge);
> +       drm_bridge_attach(encoder, bridge, NULL);
>
> -       encoder->bridge = bridge;
>         connector->encoder = encoder;
>
>         drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index 376b0763c874..f0af1ae82ee9 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -1308,9 +1308,8 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         bridge->driver_private = hdmi;
>         bridge->funcs = &sti_hdmi_bridge_funcs;
> -       drm_bridge_attach(drm_dev, bridge);
> +       drm_bridge_attach(encoder, bridge, NULL);
>
> -       encoder->bridge = bridge;
>         connector->encoder = encoder;
>
>         drm_connector = (struct drm_connector *)connector;
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index c3ff10f559cc..ce071c17134b 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -219,6 +219,7 @@ int sun4i_rgb_init(struct drm_device *drm)
>         struct sun4i_drv *drv = drm->dev_private;
>         struct sun4i_tcon *tcon = drv->tcon;
>         struct drm_encoder *encoder;
> +       struct drm_bridge *bridge;
>         struct sun4i_rgb *rgb;
>         int ret;
>
> @@ -229,8 +230,8 @@ int sun4i_rgb_init(struct drm_device *drm)
>         encoder = &rgb->encoder;
>
>         tcon->panel = sun4i_tcon_find_panel(tcon->dev->of_node);
> -       encoder->bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> -       if (IS_ERR(tcon->panel) && IS_ERR(encoder->bridge)) {
> +       bridge = sun4i_tcon_find_bridge(tcon->dev->of_node);
> +       if (IS_ERR(tcon->panel) && IS_ERR(bridge)) {
>                 dev_info(drm->dev, "No panel or bridge found... RGB output disabled\n");
>                 return 0;
>         }
> @@ -271,16 +272,12 @@ int sun4i_rgb_init(struct drm_device *drm)
>                 }
>         }
>
> -       if (!IS_ERR(encoder->bridge)) {
> -               encoder->bridge->encoder = &rgb->encoder;
> -
> -               ret = drm_bridge_attach(drm, encoder->bridge);
> +       if (!IS_ERR(bridge)) {
> +               ret = drm_bridge_attach(encoder, bridge, NULL);
>                 if (ret) {
>                         dev_err(drm->dev, "Couldn't attach our bridge\n");
>                         goto err_cleanup_connector;
>                 }
> -       } else {
> -               encoder->bridge = NULL;
>         }
>
>         return 0;
> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
> index 530a1d6e8cde..94e5ee96b3b5 100644
> --- a/include/drm/drm_bridge.h
> +++ b/include/drm/drm_bridge.h
> @@ -201,7 +201,8 @@ struct drm_bridge {
>  int drm_bridge_add(struct drm_bridge *bridge);
>  void drm_bridge_remove(struct drm_bridge *bridge);
>  struct drm_bridge *of_drm_find_bridge(struct device_node *np);
> -int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
> +int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
> +                     struct drm_bridge *previous);
>  void drm_bridge_detach(struct drm_bridge *bridge);
>
>  bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
> --
> Regards,
>
> Laurent Pinchart
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
  2016-11-29  9:04 ` [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h> Laurent Pinchart
@ 2016-12-02 21:21     ` Sinclair Yeh
  2016-12-02 21:21     ` Sinclair Yeh
  1 sibling, 0 replies; 100+ messages in thread
From: Sinclair Yeh @ 2016-12-02 21:21 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, Archit Taneja, Alex Deucher,
	Christian König, Stefan Agner, Alison Wang,
	Patrik Jakobsson, Daniel Vetter, Jani Nikula, Ben Skeggs,
	Thierry Reding, Eric Anholt, Thomas Hellstrom


vmwgfx part:  Reviewed-by: Sinclair Yeh <syeh@vmware.com>

On Tue, Nov 29, 2016 at 11:04:31AM +0200, Laurent Pinchart wrote:
> <drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
> now been split into separate files for each object type, but still
> includes most other KMS headers to avoid breaking driver compilation.
> 
> As a step towards fixing that problem, remove the inclusion of
> <drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
> appropriate. Also remove the forward declarations of the drm_encoder and
> drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
> needed in the header.
> 
> <drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
> forward declaration of struct drm_encoder in order to allow including it
> as the first header in a compilation unit.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
>  drivers/gpu/drm/ast/ast_drv.h               | 1 +
>  drivers/gpu/drm/bochs/bochs.h               | 1 +
>  drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
>  drivers/gpu/drm/drm_connector.c             | 1 +
>  drivers/gpu/drm/drm_crtc_helper.c           | 1 +
>  drivers/gpu/drm/drm_edid.c                  | 1 +
>  drivers/gpu/drm/drm_mode_config.c           | 1 +
>  drivers/gpu/drm/drm_of.c                    | 1 +
>  drivers/gpu/drm/drm_plane_helper.c          | 1 +
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
>  drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
>  drivers/gpu/drm/i915/intel_drv.h            | 1 +
>  drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
>  drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
>  drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
>  drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
>  drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
>  drivers/gpu/drm/tegra/drm.h                 | 1 +
>  drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
>  drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
>  include/drm/drm_crtc.h                      | 3 ---
>  include/drm/drm_encoder.h                   | 3 +++
>  include/drm/drm_encoder_slave.h             | 1 +
>  include/drm/drm_modeset_helper_vtables.h    | 1 +
>  27 files changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 1e23334b07fb..fac06064a8f5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_fixed.h>
>  #include <drm/drm_crtc_helper.h>
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index 908011d2c8f5..6f3b6f50cf52 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -28,6 +28,7 @@
>  #ifndef __AST_DRV_H__
>  #define __AST_DRV_H__
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
> index 32dfe418cc98..f626bab7f5e3 100644
> --- a/drivers/gpu/drm/bochs/bochs.h
> +++ b/drivers/gpu/drm/bochs/bochs.h
> @@ -4,6 +4,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/drm_gem.h>
> diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
> index 2188d6b61b3e..b59aeef4635a 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> @@ -13,6 +13,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index b5c6a8ee831e..5f1e1f190d30 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -23,6 +23,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5d2cb138eba6..b3fc23313cc3 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -36,6 +36,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_fb_helper.h>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 7eec18925b70..a9e3cc3990c1 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -35,6 +35,7 @@
>  #include <linux/vga_switcheroo.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_displayid.h>
>  
>  #define version_greater(edid, maj, min) \
> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
> index 2735a5847ffa..09b1d8f267a6 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -20,6 +20,7 @@
>   * OF THIS SOFTWARE.
>   */
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_mode_config.h>
>  #include <drm/drmP.h>
>  
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b5f2f0fece99 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -4,6 +4,7 @@
>  #include <linux/of_graph.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 7a7dddf604d7..191a5f095cf9 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -29,6 +29,7 @@
>  #include <drm/drm_rect.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_atomic_helper.h>
>  
>  #define SUBPIXEL_MASK 0xffff
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> index 3b371fe7491e..4c22edd4c746 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> @@ -12,6 +12,8 @@
>  #ifndef __FSL_DCU_DRM_DRV_H__
>  #define __FSL_DCU_DRM_DRV_H__
>  
> +#include <drm/drm_encoder.h>
> +
>  #include "fsl_dcu_drm_crtc.h"
>  #include "fsl_dcu_drm_output.h"
>  #include "fsl_dcu_drm_plane.h"
> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
> index 2a3b7c684db2..6a10215fc42d 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> @@ -23,6 +23,7 @@
>  #include <linux/i2c-algo-bit.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <linux/gpio.h>
>  #include "gma_display.h"
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 398195bf6dd1..7fb8ac824b01 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -32,6 +32,7 @@
>  #include "i915_drv.h"
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_dp_dual_mode_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
> index 3e02ac20777c..87e0934773de 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> @@ -15,6 +15,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/ttm/ttm_bo_api.h>
>  #include <drm/ttm/ttm_bo_driver.h>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
> index 096983c42a1f..a4d1a059bd3d 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
> @@ -30,6 +30,7 @@
>  #include <nvif/notify.h>
>  
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include "nouveau_crtc.h"
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 84995ebc6ffc..56df6b4ddbab 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -43,6 +43,7 @@
>  #include <ttm/ttm_placement.h>
>  #include <ttm/ttm_module.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_gem.h>
>  
>  /* just for ttm_validate_buffer */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index bb75201a24ba..7ceea8ffd0db 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
>  #include <drm/drm_fixed.h>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> index 269fbab15907..b79b2f075a74 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> @@ -15,6 +15,7 @@
>  #define __RCAR_DU_ENCODER_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct drm_panel;
>  struct rcar_du_device;
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> index 38ed4ff8aaf2..818b31549ddc 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> @@ -16,6 +16,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct backlight_device;
>  struct shmob_drm_device;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 0ddcce1b420d..5205790dd679 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -17,6 +17,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_fixed.h>
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index fef172804345..f89a95cb98cf 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -9,6 +9,8 @@
>  #include "drmP.h"
>  #include "drm_gem_cma_helper.h"
>  
> +#include <drm/drm_encoder.h>
> +
>  struct vc4_dev {
>  	struct drm_device *dev;
>  
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
> index ec1ebdcfe80b..475ac93848c3 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> @@ -35,6 +35,7 @@
>  #include <drm/drm_gem.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <ttm/ttm_bo_api.h>
>  #include <ttm/ttm_bo_driver.h>
>  #include <ttm/ttm_placement.h>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index ff4803c107bc..5ee25fb07ea2 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -30,6 +30,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include "vmwgfx_drv.h"
>  
>  /**
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 946672f97e1e..9ef0ac0ce69f 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -39,7 +39,6 @@
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_modes.h>
>  #include <drm/drm_connector.h>
> -#include <drm/drm_encoder.h>
>  #include <drm/drm_property.h>
>  #include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
> @@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
>  }
>  
>  struct drm_crtc;
> -struct drm_encoder;
>  struct drm_pending_vblank_event;
>  struct drm_plane;
>  struct drm_bridge;
>  struct drm_atomic_state;
>  
>  struct drm_crtc_helper_funcs;
> -struct drm_encoder_helper_funcs;
>  struct drm_plane_helper_funcs;
>  
>  /**
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index c7438ff0d609..cec6ac45c6cc 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -25,8 +25,11 @@
>  
>  #include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <drm/drm_mode.h>
>  #include <drm/drm_mode_object.h>
>  
> +struct drm_encoder;
> +
>  /**
>   * struct drm_encoder_funcs - encoder controls
>   *
> diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
> index 82cdf611393d..1107b4b1c599 100644
> --- a/include/drm/drm_encoder_slave.h
> +++ b/include/drm/drm_encoder_slave.h
> @@ -29,6 +29,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 72478cf82147..21d9823d4872 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -30,6 +30,7 @@
>  #define __DRM_MODESET_HELPER_VTABLES_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> -- 
> Regards,
> 
> Laurent Pinchart
> 

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h>
@ 2016-12-02 21:21     ` Sinclair Yeh
  0 siblings, 0 replies; 100+ messages in thread
From: Sinclair Yeh @ 2016-12-02 21:21 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Alison Wang, Thomas Hellstrom, dri-devel, linux-renesas-soc,
	Alex Deucher, Daniel Vetter, Christian König, Ben Skeggs


vmwgfx part:  Reviewed-by: Sinclair Yeh <syeh@vmware.com>

On Tue, Nov 29, 2016 at 11:04:31AM +0200, Laurent Pinchart wrote:
> <drm/drm_crtc.h> used to define most of the in-kernel KMS API. It has
> now been split into separate files for each object type, but still
> includes most other KMS headers to avoid breaking driver compilation.
> 
> As a step towards fixing that problem, remove the inclusion of
> <drm/drm_encoder.h> from <drm/drm_crtc.h> and include it instead where
> appropriate. Also remove the forward declarations of the drm_encoder and
> drm_encoder_helper_funcs structures from <drm/drm_crtc.h> as they're not
> needed in the header.
> 
> <drm/drm_encoder.h> now has to include <drm/drm_mode.h> and contain a
> forward declaration of struct drm_encoder in order to allow including it
> as the first header in a compilation unit.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h    | 1 +
>  drivers/gpu/drm/ast/ast_drv.h               | 1 +
>  drivers/gpu/drm/bochs/bochs.h               | 1 +
>  drivers/gpu/drm/cirrus/cirrus_drv.h         | 1 +
>  drivers/gpu/drm/drm_connector.c             | 1 +
>  drivers/gpu/drm/drm_crtc_helper.c           | 1 +
>  drivers/gpu/drm/drm_edid.c                  | 1 +
>  drivers/gpu/drm/drm_mode_config.c           | 1 +
>  drivers/gpu/drm/drm_of.c                    | 1 +
>  drivers/gpu/drm/drm_plane_helper.c          | 1 +
>  drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h   | 2 ++
>  drivers/gpu/drm/gma500/psb_intel_drv.h      | 1 +
>  drivers/gpu/drm/i915/intel_drv.h            | 1 +
>  drivers/gpu/drm/mgag200/mgag200_drv.h       | 1 +
>  drivers/gpu/drm/nouveau/nouveau_connector.h | 1 +
>  drivers/gpu/drm/qxl/qxl_drv.h               | 1 +
>  drivers/gpu/drm/radeon/radeon_mode.h        | 1 +
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h   | 1 +
>  drivers/gpu/drm/shmobile/shmob_drm_crtc.h   | 1 +
>  drivers/gpu/drm/tegra/drm.h                 | 1 +
>  drivers/gpu/drm/vc4/vc4_drv.h               | 2 ++
>  drivers/gpu/drm/virtio/virtgpu_drv.h        | 1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h         | 1 +
>  include/drm/drm_crtc.h                      | 3 ---
>  include/drm/drm_encoder.h                   | 3 +++
>  include/drm/drm_encoder_slave.h             | 1 +
>  include/drm/drm_modeset_helper_vtables.h    | 1 +
>  27 files changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> index 1e23334b07fb..fac06064a8f5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_fixed.h>
>  #include <drm/drm_crtc_helper.h>
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index 908011d2c8f5..6f3b6f50cf52 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -28,6 +28,7 @@
>  #ifndef __AST_DRV_H__
>  #define __AST_DRV_H__
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
> index 32dfe418cc98..f626bab7f5e3 100644
> --- a/drivers/gpu/drm/bochs/bochs.h
> +++ b/drivers/gpu/drm/bochs/bochs.h
> @@ -4,6 +4,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/drm_gem.h>
> diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
> index 2188d6b61b3e..b59aeef4635a 100644
> --- a/drivers/gpu/drm/cirrus/cirrus_drv.h
> +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
> @@ -13,6 +13,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  
>  #include <drm/ttm/ttm_bo_api.h>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index b5c6a8ee831e..5f1e1f190d30 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -23,6 +23,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5d2cb138eba6..b3fc23313cc3 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -36,6 +36,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_fb_helper.h>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 7eec18925b70..a9e3cc3990c1 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -35,6 +35,7 @@
>  #include <linux/vga_switcheroo.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_displayid.h>
>  
>  #define version_greater(edid, maj, min) \
> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
> index 2735a5847ffa..09b1d8f267a6 100644
> --- a/drivers/gpu/drm/drm_mode_config.c
> +++ b/drivers/gpu/drm/drm_mode_config.c
> @@ -20,6 +20,7 @@
>   * OF THIS SOFTWARE.
>   */
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_mode_config.h>
>  #include <drm/drmP.h>
>  
> diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
> index 47848ed8ca48..b5f2f0fece99 100644
> --- a/drivers/gpu/drm/drm_of.c
> +++ b/drivers/gpu/drm/drm_of.c
> @@ -4,6 +4,7 @@
>  #include <linux/of_graph.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_of.h>
>  
>  static void drm_release_of(struct device *dev, void *data)
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 7a7dddf604d7..191a5f095cf9 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -29,6 +29,7 @@
>  #include <drm/drm_rect.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_atomic_helper.h>
>  
>  #define SUBPIXEL_MASK 0xffff
> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> index 3b371fe7491e..4c22edd4c746 100644
> --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
> @@ -12,6 +12,8 @@
>  #ifndef __FSL_DCU_DRM_DRV_H__
>  #define __FSL_DCU_DRM_DRV_H__
>  
> +#include <drm/drm_encoder.h>
> +
>  #include "fsl_dcu_drm_crtc.h"
>  #include "fsl_dcu_drm_output.h"
>  #include "fsl_dcu_drm_plane.h"
> diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
> index 2a3b7c684db2..6a10215fc42d 100644
> --- a/drivers/gpu/drm/gma500/psb_intel_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
> @@ -23,6 +23,7 @@
>  #include <linux/i2c-algo-bit.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <linux/gpio.h>
>  #include "gma_display.h"
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 398195bf6dd1..7fb8ac824b01 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -32,6 +32,7 @@
>  #include "i915_drv.h"
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_dp_dual_mode_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
> diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
> index 3e02ac20777c..87e0934773de 100644
> --- a/drivers/gpu/drm/mgag200/mgag200_drv.h
> +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
> @@ -15,6 +15,7 @@
>  
>  #include <video/vga.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/ttm/ttm_bo_api.h>
>  #include <drm/ttm/ttm_bo_driver.h>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
> index 096983c42a1f..a4d1a059bd3d 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_connector.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
> @@ -30,6 +30,7 @@
>  #include <nvif/notify.h>
>  
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include "nouveau_crtc.h"
>  
> diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
> index 84995ebc6ffc..56df6b4ddbab 100644
> --- a/drivers/gpu/drm/qxl/qxl_drv.h
> +++ b/drivers/gpu/drm/qxl/qxl_drv.h
> @@ -43,6 +43,7 @@
>  #include <ttm/ttm_placement.h>
>  #include <ttm/ttm_module.h>
>  
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_gem.h>
>  
>  /* just for ttm_validate_buffer */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index bb75201a24ba..7ceea8ffd0db 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -32,6 +32,7 @@
>  
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_dp_helper.h>
>  #include <drm/drm_dp_mst_helper.h>
>  #include <drm/drm_fixed.h>
> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> index 269fbab15907..b79b2f075a74 100644
> --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
> @@ -15,6 +15,7 @@
>  #define __RCAR_DU_ENCODER_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct drm_panel;
>  struct rcar_du_device;
> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> index 38ed4ff8aaf2..818b31549ddc 100644
> --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
> @@ -16,6 +16,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  struct backlight_device;
>  struct shmob_drm_device;
> diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
> index 0ddcce1b420d..5205790dd679 100644
> --- a/drivers/gpu/drm/tegra/drm.h
> +++ b/drivers/gpu/drm/tegra/drm.h
> @@ -17,6 +17,7 @@
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
>  #include <drm/drm_edid.h>
> +#include <drm/drm_encoder.h>
>  #include <drm/drm_fb_helper.h>
>  #include <drm/drm_fixed.h>
>  
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index fef172804345..f89a95cb98cf 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -9,6 +9,8 @@
>  #include "drmP.h"
>  #include "drm_gem_cma_helper.h"
>  
> +#include <drm/drm_encoder.h>
> +
>  struct vc4_dev {
>  	struct drm_device *dev;
>  
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
> index ec1ebdcfe80b..475ac93848c3 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> @@ -35,6 +35,7 @@
>  #include <drm/drm_gem.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include <ttm/ttm_bo_api.h>
>  #include <ttm/ttm_bo_driver.h>
>  #include <ttm/ttm_placement.h>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index ff4803c107bc..5ee25fb07ea2 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -30,6 +30,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
> +#include <drm/drm_encoder.h>
>  #include "vmwgfx_drv.h"
>  
>  /**
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 946672f97e1e..9ef0ac0ce69f 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -39,7 +39,6 @@
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_modes.h>
>  #include <drm/drm_connector.h>
> -#include <drm/drm_encoder.h>
>  #include <drm/drm_property.h>
>  #include <drm/drm_bridge.h>
>  #include <drm/drm_edid.h>
> @@ -68,14 +67,12 @@ static inline uint64_t I642U64(int64_t val)
>  }
>  
>  struct drm_crtc;
> -struct drm_encoder;
>  struct drm_pending_vblank_event;
>  struct drm_plane;
>  struct drm_bridge;
>  struct drm_atomic_state;
>  
>  struct drm_crtc_helper_funcs;
> -struct drm_encoder_helper_funcs;
>  struct drm_plane_helper_funcs;
>  
>  /**
> diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
> index c7438ff0d609..cec6ac45c6cc 100644
> --- a/include/drm/drm_encoder.h
> +++ b/include/drm/drm_encoder.h
> @@ -25,8 +25,11 @@
>  
>  #include <linux/list.h>
>  #include <linux/ctype.h>
> +#include <drm/drm_mode.h>
>  #include <drm/drm_mode_object.h>
>  
> +struct drm_encoder;
> +
>  /**
>   * struct drm_encoder_funcs - encoder controls
>   *
> diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
> index 82cdf611393d..1107b4b1c599 100644
> --- a/include/drm/drm_encoder_slave.h
> +++ b/include/drm/drm_encoder_slave.h
> @@ -29,6 +29,7 @@
>  
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * struct drm_encoder_slave_funcs - Entry points exposed by a slave encoder driver
> diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
> index 72478cf82147..21d9823d4872 100644
> --- a/include/drm/drm_modeset_helper_vtables.h
> +++ b/include/drm/drm_modeset_helper_vtables.h
> @@ -30,6 +30,7 @@
>  #define __DRM_MODESET_HELPER_VTABLES_H__
>  
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_encoder.h>
>  
>  /**
>   * DOC: overview
> -- 
> Regards,
> 
> Laurent Pinchart
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 12/13] drm: rcar-du: Replace manual bridge implementation with DRM bridge
  2016-11-29  9:04 ` [PATCH v3 12/13] drm: rcar-du: Replace manual bridge implementation with DRM bridge Laurent Pinchart
@ 2016-12-27 12:40     ` Geert Uytterhoeven
  0 siblings, 0 replies; 100+ messages in thread
From: Geert Uytterhoeven @ 2016-12-27 12:40 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: DRI Development, Linux-Renesas, Archit Taneja

Hi Laurent,

On Tue, Nov 29, 2016 at 10:04 AM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> The rcar-du driver contains a manual implementation of HDMI and VGA
> bridges. Use DRM bridges to replace it.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/Kconfig           |   6 --
>  drivers/gpu/drm/rcar-du/Makefile          |   5 +-
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 104 +++++++++++++----------
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h |   2 -
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 134 ------------------------------
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h |  35 --------
>  drivers/gpu/drm/rcar-du/rcar_du_vgacon.c  |  82 ------------------
>  drivers/gpu/drm/rcar-du/rcar_du_vgacon.h  |  23 -----
>  8 files changed, 60 insertions(+), 331 deletions(-)
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
>
> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> index 2bab449add76..06121eeba9e5 100644
> --- a/drivers/gpu/drm/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> @@ -11,12 +11,6 @@ config DRM_RCAR_DU
>           Choose this option if you have an R-Car chipset.
>           If M is selected the module will be called rcar-du-drm.
>
> -config DRM_RCAR_HDMI
> -       bool "R-Car DU HDMI Encoder Support"
> -       depends on DRM_RCAR_DU
> -       help
> -         Enable support for external HDMI encoders.
> -

Please note this symbol is selected in several defconfigs, so these should
be updated with its replacement symbol.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 12/13] drm: rcar-du: Replace manual bridge implementation with DRM bridge
@ 2016-12-27 12:40     ` Geert Uytterhoeven
  0 siblings, 0 replies; 100+ messages in thread
From: Geert Uytterhoeven @ 2016-12-27 12:40 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: Linux-Renesas, DRI Development

Hi Laurent,

On Tue, Nov 29, 2016 at 10:04 AM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> The rcar-du driver contains a manual implementation of HDMI and VGA
> bridges. Use DRM bridges to replace it.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
>  drivers/gpu/drm/rcar-du/Kconfig           |   6 --
>  drivers/gpu/drm/rcar-du/Makefile          |   5 +-
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 104 +++++++++++++----------
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h |   2 -
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 134 ------------------------------
>  drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h |  35 --------
>  drivers/gpu/drm/rcar-du/rcar_du_vgacon.c  |  82 ------------------
>  drivers/gpu/drm/rcar-du/rcar_du_vgacon.h  |  23 -----
>  8 files changed, 60 insertions(+), 331 deletions(-)
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
>
> diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
> index 2bab449add76..06121eeba9e5 100644
> --- a/drivers/gpu/drm/rcar-du/Kconfig
> +++ b/drivers/gpu/drm/rcar-du/Kconfig
> @@ -11,12 +11,6 @@ config DRM_RCAR_DU
>           Choose this option if you have an R-Car chipset.
>           If M is selected the module will be called rcar-du-drm.
>
> -config DRM_RCAR_HDMI
> -       bool "R-Car DU HDMI Encoder Support"
> -       depends on DRM_RCAR_DU
> -       help
> -         Enable support for external HDMI encoders.
> -

Please note this symbol is selected in several defconfigs, so these should
be updated with its replacement symbol.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2016-11-29 20:57       ` Laurent Pinchart
  (?)
@ 2017-01-04  1:33       ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04  1:33 UTC (permalink / raw)
  To: dri-devel; +Cc: Daniel Vetter, linux-renesas-soc

Hi Daniel,

On Tuesday 29 Nov 2016 22:57:07 Laurent Pinchart wrote:
> On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> >> The LVDS encoder driver is a DRM bridge driver that supports the
> >> parallel to LVDS encoders that don't require any configuration. The
> >> driver thus doesn't interact with the device, but creates an LVDS
> >> connector for the panel and exposes its size and timing based on
> >> information retrieved from DT.
> >> 
> >> Signed-off-by: Laurent Pinchart
> >> <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > Since it's 100% dummy, why put LVDS into the name? This little thing here
> > could be our generic "wrap drm_panel and attach it to a chain" helper. So
> > what about calling this _The_ drm_panel_bridge, and also linking it into
> > docs to feature it a bit more prominently.
> 
> I'm not opposed to that, except that this driver should not be considered as
> just a helper to link a panel. It should only be used to support a real
> hardware bridge that requires no control.
> 
> > I came up with this because I spotted some refactoring belows for building
> > this helper, until I realized that this driver _is_ the helper I think we
> > want ;-) Only thing missing is an exported function to instantiate a
> > bridge with just a drm_panel as the parameter. And putting it into the
> > drm_kms_helper.ko module.
> 
> What would that be used for ? The bridge should be instantiated by this
> bridge driver, bound to a bridge device instantiated from DT (or the
> platform firmware of your choice).

Ping ?

> >> +static enum drm_connector_status
> >> +lvds_connector_detect(struct drm_connector *connector, bool force)
> >> +{
> >> +	return connector_status_connected;
> >> +}
> > 
> > We have piles of this exact dummy callback all over, maybe make it the
> > default and rip them all out?
> 
> Done, "[PATCH] drm: Make the connector .detect() callback optional".

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2016-11-29 20:57       ` Laurent Pinchart
@ 2017-01-04  8:18         ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2017-01-04  8:18 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Vetter, Laurent Pinchart, dri-devel, linux-renesas-soc

On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> > > The LVDS encoder driver is a DRM bridge driver that supports the
> > > parallel to LVDS encoders that don't require any configuration. The
> > > driver thus doesn't interact with the device, but creates an LVDS
> > > connector for the panel and exposes its size and timing based on
> > > information retrieved from DT.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > Since it's 100% dummy, why put LVDS into the name? This little thing here
> > could be our generic "wrap drm_panel and attach it to a chain" helper. So
> > what about calling this _The_ drm_panel_bridge, and also linking it into
> > docs to feature it a bit more prominently.
> 
> I'm not opposed to that, except that this driver should not be considered as 
> just a helper to link a panel. It should only be used to support a real 
> hardware bridge that requires no control.
> 
> > I came up with this because I spotted some refactoring belows for building
> > this helper, until I realized that this driver _is_ the helper I think we
> > want ;-) Only thing missing is an exported function to instantiate a
> > bridge with just a drm_panel as the parameter. And putting it into the
> > drm_kms_helper.ko module.
> 
> What would that be used for ? The bridge should be instantiated by this bridge 
> driver, bound to a bridge device instantiated from DT (or the platform 
> firmware of your choice).

Atm every driver using drm_panel needs a bit of glue to bind it into it's
display chain. With this code, and bridge chaining, you'd get that for
free, and I think that would be rather useful. And from a software point
of view I'd say if it quacks like a bridge, and walks like a bridge, it
probably _is_ a bridge. Even if no one calls that, or if physical the only
thing on the board at that spot are a bunch of dumb wires.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-01-04  8:18         ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2017-01-04  8:18 UTC (permalink / raw)
  To: Laurent Pinchart; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> > On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> > > The LVDS encoder driver is a DRM bridge driver that supports the
> > > parallel to LVDS encoders that don't require any configuration. The
> > > driver thus doesn't interact with the device, but creates an LVDS
> > > connector for the panel and exposes its size and timing based on
> > > information retrieved from DT.
> > > 
> > > Signed-off-by: Laurent Pinchart
> > > <laurent.pinchart+renesas@ideasonboard.com>
> > 
> > Since it's 100% dummy, why put LVDS into the name? This little thing here
> > could be our generic "wrap drm_panel and attach it to a chain" helper. So
> > what about calling this _The_ drm_panel_bridge, and also linking it into
> > docs to feature it a bit more prominently.
> 
> I'm not opposed to that, except that this driver should not be considered as 
> just a helper to link a panel. It should only be used to support a real 
> hardware bridge that requires no control.
> 
> > I came up with this because I spotted some refactoring belows for building
> > this helper, until I realized that this driver _is_ the helper I think we
> > want ;-) Only thing missing is an exported function to instantiate a
> > bridge with just a drm_panel as the parameter. And putting it into the
> > drm_kms_helper.ko module.
> 
> What would that be used for ? The bridge should be instantiated by this bridge 
> driver, bound to a bridge device instantiated from DT (or the platform 
> firmware of your choice).

Atm every driver using drm_panel needs a bit of glue to bind it into it's
display chain. With this code, and bridge chaining, you'd get that for
free, and I think that would be rather useful. And from a software point
of view I'd say if it quacks like a bridge, and walks like a bridge, it
probably _is_ a bridge. Even if no one calls that, or if physical the only
thing on the board at that spot are a bunch of dumb wires.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-01-04  8:18         ` Daniel Vetter
@ 2017-01-04 13:08           ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04 13:08 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Laurent Pinchart, dri-devel, linux-renesas-soc

Hi Daniel,

On Wednesday 04 Jan 2017 09:18:18 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> >>> The LVDS encoder driver is a DRM bridge driver that supports the
> >>> parallel to LVDS encoders that don't require any configuration. The
> >>> driver thus doesn't interact with the device, but creates an LVDS
> >>> connector for the panel and exposes its size and timing based on
> >>> information retrieved from DT.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >> 
> >> Since it's 100% dummy, why put LVDS into the name? This little thing
> >> here could be our generic "wrap drm_panel and attach it to a chain"
> >> helper. So what about calling this _The_ drm_panel_bridge, and also
> >> linking it into docs to feature it a bit more prominently.
> > 
> > I'm not opposed to that, except that this driver should not be considered
> > as just a helper to link a panel. It should only be used to support a
> > real hardware bridge that requires no control.
> > 
> >> I came up with this because I spotted some refactoring belows for
> >> building this helper, until I realized that this driver _is_ the helper I
> >> think we want ;-) Only thing missing is an exported function to
> >> instantiate a bridge with just a drm_panel as the parameter. And putting
> >> it into the drm_kms_helper.ko module.
> > 
> > What would that be used for ? The bridge should be instantiated by this
> > bridge driver, bound to a bridge device instantiated from DT (or the
> > platform firmware of your choice).
> 
> Atm every driver using drm_panel needs a bit of glue to bind it into it's
> display chain. With this code, and bridge chaining, you'd get that for
> free, and I think that would be rather useful.

You would trade the bit of panel glue for a bit of bridge glue. Bridge 
chaining could perhaps help slightly at runtime there, but at init time the 
amount of glue would be similar.

I've noticed one piece of code that is LVDS-specific in this driver, and 
that's connector creation. The connector type is hardcoded to LVDS. To make 
the driver more generic, we would need a way to find the connector type at 
runtime. I'm wondering whether I should do this now, or keep the driver LVDS-
specific until someone comes up with a similar need. Without several potential 
users it's often hard to design a properly generic API.

> And from a software point of view I'd say if it quacks like a bridge, and
> walks like a bridge, it probably _is_ a bridge. Even if no one calls that,
> or if physical the only thing on the board at that spot are a bunch of dumb
> wires.

I dream of moving all encoders to DRM bridge, and then unifying drm_bridge and 
drm_panel with a common set of operations that could be invoked on both 
objects. That way the core could chain bridges and panels quite easily. I plan 
to experiment with this when moving the omapdrm driver to DRM bridge and DRM 
panel (it currently includes a bunch of custom encoder and panel drivers).

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-01-04 13:08           ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04 13:08 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: linux-renesas-soc, Laurent Pinchart, dri-devel

Hi Daniel,

On Wednesday 04 Jan 2017 09:18:18 Daniel Vetter wrote:
> On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
> > On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> >>> The LVDS encoder driver is a DRM bridge driver that supports the
> >>> parallel to LVDS encoders that don't require any configuration. The
> >>> driver thus doesn't interact with the device, but creates an LVDS
> >>> connector for the panel and exposes its size and timing based on
> >>> information retrieved from DT.
> >>> 
> >>> Signed-off-by: Laurent Pinchart
> >>> <laurent.pinchart+renesas@ideasonboard.com>
> >> 
> >> Since it's 100% dummy, why put LVDS into the name? This little thing
> >> here could be our generic "wrap drm_panel and attach it to a chain"
> >> helper. So what about calling this _The_ drm_panel_bridge, and also
> >> linking it into docs to feature it a bit more prominently.
> > 
> > I'm not opposed to that, except that this driver should not be considered
> > as just a helper to link a panel. It should only be used to support a
> > real hardware bridge that requires no control.
> > 
> >> I came up with this because I spotted some refactoring belows for
> >> building this helper, until I realized that this driver _is_ the helper I
> >> think we want ;-) Only thing missing is an exported function to
> >> instantiate a bridge with just a drm_panel as the parameter. And putting
> >> it into the drm_kms_helper.ko module.
> > 
> > What would that be used for ? The bridge should be instantiated by this
> > bridge driver, bound to a bridge device instantiated from DT (or the
> > platform firmware of your choice).
> 
> Atm every driver using drm_panel needs a bit of glue to bind it into it's
> display chain. With this code, and bridge chaining, you'd get that for
> free, and I think that would be rather useful.

You would trade the bit of panel glue for a bit of bridge glue. Bridge 
chaining could perhaps help slightly at runtime there, but at init time the 
amount of glue would be similar.

I've noticed one piece of code that is LVDS-specific in this driver, and 
that's connector creation. The connector type is hardcoded to LVDS. To make 
the driver more generic, we would need a way to find the connector type at 
runtime. I'm wondering whether I should do this now, or keep the driver LVDS-
specific until someone comes up with a similar need. Without several potential 
users it's often hard to design a properly generic API.

> And from a software point of view I'd say if it quacks like a bridge, and
> walks like a bridge, it probably _is_ a bridge. Even if no one calls that,
> or if physical the only thing on the board at that spot are a bunch of dumb
> wires.

I dream of moving all encoders to DRM bridge, and then unifying drm_bridge and 
drm_panel with a common set of operations that could be invoked on both 
objects. That way the core could chain bridges and panels quite easily. I plan 
to experiment with this when moving the omapdrm driver to DRM bridge and DRM 
panel (it currently includes a bunch of custom encoder and panel drivers).

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-01-04 13:08           ` Laurent Pinchart
  (?)
@ 2017-01-04 13:51           ` Daniel Vetter
  2017-01-04 14:33               ` Laurent Pinchart
  -1 siblings, 1 reply; 100+ messages in thread
From: Daniel Vetter @ 2017-01-04 13:51 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Laurent Pinchart, dri-devel, open list:DRM DRIVERS FOR RENESAS

On Wed, Jan 4, 2017 at 2:08 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Daniel,
>
> On Wednesday 04 Jan 2017 09:18:18 Daniel Vetter wrote:
>> On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
>> > On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
>> >> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
>> >>> The LVDS encoder driver is a DRM bridge driver that supports the
>> >>> parallel to LVDS encoders that don't require any configuration. The
>> >>> driver thus doesn't interact with the device, but creates an LVDS
>> >>> connector for the panel and exposes its size and timing based on
>> >>> information retrieved from DT.
>> >>>
>> >>> Signed-off-by: Laurent Pinchart
>> >>> <laurent.pinchart+renesas@ideasonboard.com>
>> >>
>> >> Since it's 100% dummy, why put LVDS into the name? This little thing
>> >> here could be our generic "wrap drm_panel and attach it to a chain"
>> >> helper. So what about calling this _The_ drm_panel_bridge, and also
>> >> linking it into docs to feature it a bit more prominently.
>> >
>> > I'm not opposed to that, except that this driver should not be considered
>> > as just a helper to link a panel. It should only be used to support a
>> > real hardware bridge that requires no control.
>> >
>> >> I came up with this because I spotted some refactoring belows for
>> >> building this helper, until I realized that this driver _is_ the helper I
>> >> think we want ;-) Only thing missing is an exported function to
>> >> instantiate a bridge with just a drm_panel as the parameter. And putting
>> >> it into the drm_kms_helper.ko module.
>> >
>> > What would that be used for ? The bridge should be instantiated by this
>> > bridge driver, bound to a bridge device instantiated from DT (or the
>> > platform firmware of your choice).
>>
>> Atm every driver using drm_panel needs a bit of glue to bind it into it's
>> display chain. With this code, and bridge chaining, you'd get that for
>> free, and I think that would be rather useful.
>
> You would trade the bit of panel glue for a bit of bridge glue. Bridge
> chaining could perhaps help slightly at runtime there, but at init time the
> amount of glue would be similar.

Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
enough, or not? My idea is to use this for the case where the only
thing in dt is the panel, with no real bridge chip. And I think we
don't need anything beyond that one _init function, plus maybe some
additional paramaters ...

> I've noticed one piece of code that is LVDS-specific in this driver, and
> that's connector creation. The connector type is hardcoded to LVDS. To make
> the driver more generic, we would need a way to find the connector type at
> runtime. I'm wondering whether I should do this now, or keep the driver LVDS-
> specific until someone comes up with a similar need. Without several potential
> users it's often hard to design a properly generic API.

... like whether the panel is dsi or lvds or soemthing else. Or maybe
we should just use LVDS for everything, because it's a panel, and
userspace shouldn't really care beyond that ;-)

>> And from a software point of view I'd say if it quacks like a bridge, and
>> walks like a bridge, it probably _is_ a bridge. Even if no one calls that,
>> or if physical the only thing on the board at that spot are a bunch of dumb
>> wires.
>
> I dream of moving all encoders to DRM bridge, and then unifying drm_bridge and
> drm_panel with a common set of operations that could be invoked on both
> objects. That way the core could chain bridges and panels quite easily. I plan
> to experiment with this when moving the omapdrm driver to DRM bridge and DRM
> panel (it currently includes a bunch of custom encoder and panel drivers).

Agreed on that dream, auto-wrapping panels in dummy bridges would be a
first step towards that. The other one is making drm_encoders entirely
dummies, and I think we're 90% there already.

End result isn't quite as clean as a complete rewrite, but probably
good enough. And because uapi we can't get rid of drm_encoder anyway,
and keeping drm_panel as the internal thing embedded into a
drm_panel_bridge struct seems reasonable too. That way panel drivers
can cope with a slightly simpler interface than full bridges.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-01-04 13:51           ` Daniel Vetter
@ 2017-01-04 14:33               ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04 14:33 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Laurent Pinchart, dri-devel, open list:DRM DRIVERS FOR RENESAS

Hi Daniel,

On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> On Wed, Jan 4, 2017 at 2:08 PM, Laurent Pinchart wrote:
> > On Wednesday 04 Jan 2017 09:18:18 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
> >>> On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> >>>> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> >>>>> The LVDS encoder driver is a DRM bridge driver that supports the
> >>>>> parallel to LVDS encoders that don't require any configuration. The
> >>>>> driver thus doesn't interact with the device, but creates an LVDS
> >>>>> connector for the panel and exposes its size and timing based on
> >>>>> information retrieved from DT.
> >>>>> 
> >>>>> Signed-off-by: Laurent Pinchart
> >>>>> <laurent.pinchart+renesas@ideasonboard.com>
> >>>> 
> >>>> Since it's 100% dummy, why put LVDS into the name? This little thing
> >>>> here could be our generic "wrap drm_panel and attach it to a chain"
> >>>> helper. So what about calling this _The_ drm_panel_bridge, and also
> >>>> linking it into docs to feature it a bit more prominently.
> >>> 
> >>> I'm not opposed to that, except that this driver should not be
> >>> considered as just a helper to link a panel. It should only be used to
> >>> support a real hardware bridge that requires no control.
> >>> 
> >>>> I came up with this because I spotted some refactoring belows for
> >>>> building this helper, until I realized that this driver _is_ the
> >>>> helper I think we want ;-) Only thing missing is an exported function
> >>>> to instantiate a bridge with just a drm_panel as the parameter. And
> >>>> putting it into the drm_kms_helper.ko module.
> >>> 
> >>> What would that be used for ? The bridge should be instantiated by this
> >>> bridge driver, bound to a bridge device instantiated from DT (or the
> >>> platform firmware of your choice).
> >> 
> >> Atm every driver using drm_panel needs a bit of glue to bind it into it's
> >> display chain. With this code, and bridge chaining, you'd get that for
> >> free, and I think that would be rather useful.
> > 
> > You would trade the bit of panel glue for a bit of bridge glue. Bridge
> > chaining could perhaps help slightly at runtime there, but at init time
> > the
> > amount of glue would be similar.
> 
> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> enough, or not? My idea is to use this for the case where the only
> thing in dt is the panel, with no real bridge chip. And I think we
> don't need anything beyond that one _init function, plus maybe some
> additional paramaters ...

There should be no bridge then. If you want the DRM core to manage panels 
automatically, then we should create specific helpers for that, not abuse the 
bridge infrastructure. Bridges should be instantiated from a hardware device 
and bound to drivers as usual.

> > I've noticed one piece of code that is LVDS-specific in this driver, and
> > that's connector creation. The connector type is hardcoded to LVDS. To
> > make the driver more generic, we would need a way to find the connector
> > type at runtime. I'm wondering whether I should do this now, or keep the
> > driver LVDS- specific until someone comes up with a similar need. Without
> > several potential users it's often hard to design a properly generic API.
> 
> ... like whether the panel is dsi or lvds or soemthing else. Or maybe
> we should just use LVDS for everything, because it's a panel, and
> userspace shouldn't really care beyond that ;-)

Feel free to propose a panel connector type :-)

> >> And from a software point of view I'd say if it quacks like a bridge, and
> >> walks like a bridge, it probably _is_ a bridge. Even if no one calls
> >> that, or if physical the only thing on the board at that spot are a bunch
> >> of dumb wires.
> > 
> > I dream of moving all encoders to DRM bridge, and then unifying drm_bridge
> > and drm_panel with a common set of operations that could be invoked on
> > both objects. That way the core could chain bridges and panels quite
> > easily. I plan to experiment with this when moving the omapdrm driver to
> > DRM bridge and DRM panel (it currently includes a bunch of custom encoder
> > and panel drivers).
>
> Agreed on that dream, auto-wrapping panels in dummy bridges would be a
> first step towards that.

But I think that's a step in the wrong direction. Ideally I'd like the 
encoders/bridges not to have to care about connectors and panels. There are 
multiple options, but a dummy bridge isn't a good idea in my opinion.

> The other one is making drm_encoders entirely dummies, and I think we're 90%
> there already.

We need to convert everything to drm_bridge first, we're not quite there yet 
:-)

> End result isn't quite as clean as a complete rewrite, but probably
> good enough. And because uapi we can't get rid of drm_encoder anyway,
> and keeping drm_panel as the internal thing embedded into a
> drm_panel_bridge struct seems reasonable too. That way panel drivers
> can cope with a slightly simpler interface than full bridges.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-01-04 14:33               ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04 14:33 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: open list:DRM DRIVERS FOR RENESAS, Laurent Pinchart, dri-devel

Hi Daniel,

On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> On Wed, Jan 4, 2017 at 2:08 PM, Laurent Pinchart wrote:
> > On Wednesday 04 Jan 2017 09:18:18 Daniel Vetter wrote:
> >> On Tue, Nov 29, 2016 at 10:57:07PM +0200, Laurent Pinchart wrote:
> >>> On Tuesday 29 Nov 2016 10:54:09 Daniel Vetter wrote:
> >>>> On Tue, Nov 29, 2016 at 11:04:36AM +0200, Laurent Pinchart wrote:
> >>>>> The LVDS encoder driver is a DRM bridge driver that supports the
> >>>>> parallel to LVDS encoders that don't require any configuration. The
> >>>>> driver thus doesn't interact with the device, but creates an LVDS
> >>>>> connector for the panel and exposes its size and timing based on
> >>>>> information retrieved from DT.
> >>>>> 
> >>>>> Signed-off-by: Laurent Pinchart
> >>>>> <laurent.pinchart+renesas@ideasonboard.com>
> >>>> 
> >>>> Since it's 100% dummy, why put LVDS into the name? This little thing
> >>>> here could be our generic "wrap drm_panel and attach it to a chain"
> >>>> helper. So what about calling this _The_ drm_panel_bridge, and also
> >>>> linking it into docs to feature it a bit more prominently.
> >>> 
> >>> I'm not opposed to that, except that this driver should not be
> >>> considered as just a helper to link a panel. It should only be used to
> >>> support a real hardware bridge that requires no control.
> >>> 
> >>>> I came up with this because I spotted some refactoring belows for
> >>>> building this helper, until I realized that this driver _is_ the
> >>>> helper I think we want ;-) Only thing missing is an exported function
> >>>> to instantiate a bridge with just a drm_panel as the parameter. And
> >>>> putting it into the drm_kms_helper.ko module.
> >>> 
> >>> What would that be used for ? The bridge should be instantiated by this
> >>> bridge driver, bound to a bridge device instantiated from DT (or the
> >>> platform firmware of your choice).
> >> 
> >> Atm every driver using drm_panel needs a bit of glue to bind it into it's
> >> display chain. With this code, and bridge chaining, you'd get that for
> >> free, and I think that would be rather useful.
> > 
> > You would trade the bit of panel glue for a bit of bridge glue. Bridge
> > chaining could perhaps help slightly at runtime there, but at init time
> > the
> > amount of glue would be similar.
> 
> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> enough, or not? My idea is to use this for the case where the only
> thing in dt is the panel, with no real bridge chip. And I think we
> don't need anything beyond that one _init function, plus maybe some
> additional paramaters ...

There should be no bridge then. If you want the DRM core to manage panels 
automatically, then we should create specific helpers for that, not abuse the 
bridge infrastructure. Bridges should be instantiated from a hardware device 
and bound to drivers as usual.

> > I've noticed one piece of code that is LVDS-specific in this driver, and
> > that's connector creation. The connector type is hardcoded to LVDS. To
> > make the driver more generic, we would need a way to find the connector
> > type at runtime. I'm wondering whether I should do this now, or keep the
> > driver LVDS- specific until someone comes up with a similar need. Without
> > several potential users it's often hard to design a properly generic API.
> 
> ... like whether the panel is dsi or lvds or soemthing else. Or maybe
> we should just use LVDS for everything, because it's a panel, and
> userspace shouldn't really care beyond that ;-)

Feel free to propose a panel connector type :-)

> >> And from a software point of view I'd say if it quacks like a bridge, and
> >> walks like a bridge, it probably _is_ a bridge. Even if no one calls
> >> that, or if physical the only thing on the board at that spot are a bunch
> >> of dumb wires.
> > 
> > I dream of moving all encoders to DRM bridge, and then unifying drm_bridge
> > and drm_panel with a common set of operations that could be invoked on
> > both objects. That way the core could chain bridges and panels quite
> > easily. I plan to experiment with this when moving the omapdrm driver to
> > DRM bridge and DRM panel (it currently includes a bunch of custom encoder
> > and panel drivers).
>
> Agreed on that dream, auto-wrapping panels in dummy bridges would be a
> first step towards that.

But I think that's a step in the wrong direction. Ideally I'd like the 
encoders/bridges not to have to care about connectors and panels. There are 
multiple options, but a dummy bridge isn't a good idea in my opinion.

> The other one is making drm_encoders entirely dummies, and I think we're 90%
> there already.

We need to convert everything to drm_bridge first, we're not quite there yet 
:-)

> End result isn't quite as clean as a complete rewrite, but probably
> good enough. And because uapi we can't get rid of drm_encoder anyway,
> and keeping drm_panel as the internal thing embedded into a
> drm_panel_bridge struct seems reasonable too. That way panel drivers
> can cope with a slightly simpler interface than full bridges.

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-01-04 14:33               ` Laurent Pinchart
@ 2017-01-04 14:58                 ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2017-01-04 14:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Vetter, Laurent Pinchart, dri-devel,
	open list:DRM DRIVERS FOR RENESAS

On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> > Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> > enough, or not? My idea is to use this for the case where the only
> > thing in dt is the panel, with no real bridge chip. And I think we
> > don't need anything beyond that one _init function, plus maybe some
> > additional paramaters ...
> 
> There should be no bridge then. If you want the DRM core to manage panels 
> automatically, then we should create specific helpers for that, not abuse the 
> bridge infrastructure. Bridges should be instantiated from a hardware device 
> and bound to drivers as usual.

I guess that's the part where I disagree: Just because there's physically
no bridge doesn't mean we shouldn't just treat it as one in the software
abstraction. If it looks and acts like a bridge (even an empty one), then
imo it can be a bridge.

If you insist on panels being panels, then I guess we need some other kind
of glue to bind them into arbitrary bridge chains. But given that the
callbacks match very closely, I don't see the point.

In an idea world a panel would probably derive from a drm_bridge, but
we're not in that universe unfortunately ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-01-04 14:58                 ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2017-01-04 14:58 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: open list:DRM DRIVERS FOR RENESAS, Laurent Pinchart, dri-devel

On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> > Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> > enough, or not? My idea is to use this for the case where the only
> > thing in dt is the panel, with no real bridge chip. And I think we
> > don't need anything beyond that one _init function, plus maybe some
> > additional paramaters ...
> 
> There should be no bridge then. If you want the DRM core to manage panels 
> automatically, then we should create specific helpers for that, not abuse the 
> bridge infrastructure. Bridges should be instantiated from a hardware device 
> and bound to drivers as usual.

I guess that's the part where I disagree: Just because there's physically
no bridge doesn't mean we shouldn't just treat it as one in the software
abstraction. If it looks and acts like a bridge (even an empty one), then
imo it can be a bridge.

If you insist on panels being panels, then I guess we need some other kind
of glue to bind them into arbitrary bridge chains. But given that the
callbacks match very closely, I don't see the point.

In an idea world a panel would probably derive from a drm_bridge, but
we're not in that universe unfortunately ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-01-04 14:58                 ` Daniel Vetter
@ 2017-01-04 15:13                   ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04 15:13 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Laurent Pinchart, dri-devel, open list:DRM DRIVERS FOR RENESAS

Hi Daniel,

On Wednesday 04 Jan 2017 15:58:25 Daniel Vetter wrote:
> On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> > On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> >> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> >> enough, or not? My idea is to use this for the case where the only
> >> thing in dt is the panel, with no real bridge chip. And I think we
> >> don't need anything beyond that one _init function, plus maybe some
> >> additional paramaters ...
> > 
> > There should be no bridge then. If you want the DRM core to manage panels
> > automatically, then we should create specific helpers for that, not abuse
> > the bridge infrastructure. Bridges should be instantiated from a hardware
> > device and bound to drivers as usual.
> 
> I guess that's the part where I disagree: Just because there's physically
> no bridge doesn't mean we shouldn't just treat it as one in the software
> abstraction. If it looks and acts like a bridge (even an empty one), then
> imo it can be a bridge.
> 
> If you insist on panels being panels, then I guess we need some other kind
> of glue to bind them into arbitrary bridge chains. But given that the
> callbacks match very closely, I don't see the point.
> 
> In an idea world a panel would probably derive from a drm_bridge, but
> we're not in that universe unfortunately ;-)

Or both would derive from another object, but I agree that's how it should 
work. That's what I want to achieve, one step at a time. Creating dummy 
bridges isn't a step in that direction in my opinion, so I'd rather not do 
that, but work towards the right abstraction.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-01-04 15:13                   ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-01-04 15:13 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: open list:DRM DRIVERS FOR RENESAS, Laurent Pinchart, dri-devel

Hi Daniel,

On Wednesday 04 Jan 2017 15:58:25 Daniel Vetter wrote:
> On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> > On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> >> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> >> enough, or not? My idea is to use this for the case where the only
> >> thing in dt is the panel, with no real bridge chip. And I think we
> >> don't need anything beyond that one _init function, plus maybe some
> >> additional paramaters ...
> > 
> > There should be no bridge then. If you want the DRM core to manage panels
> > automatically, then we should create specific helpers for that, not abuse
> > the bridge infrastructure. Bridges should be instantiated from a hardware
> > device and bound to drivers as usual.
> 
> I guess that's the part where I disagree: Just because there's physically
> no bridge doesn't mean we shouldn't just treat it as one in the software
> abstraction. If it looks and acts like a bridge (even an empty one), then
> imo it can be a bridge.
> 
> If you insist on panels being panels, then I guess we need some other kind
> of glue to bind them into arbitrary bridge chains. But given that the
> callbacks match very closely, I don't see the point.
> 
> In an idea world a panel would probably derive from a drm_bridge, but
> we're not in that universe unfortunately ;-)

Or both would derive from another object, but I agree that's how it should 
work. That's what I want to achieve, one step at a time. Creating dummy 
bridges isn't a step in that direction in my opinion, so I'd rather not do 
that, but work towards the right abstraction.

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-01-04 15:13                   ` Laurent Pinchart
@ 2017-03-02  0:30                     ` Laurent Pinchart
  -1 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-03-02  0:30 UTC (permalink / raw)
  To: dri-devel
  Cc: Daniel Vetter, open list:DRM DRIVERS FOR RENESAS, Laurent Pinchart

Hi Daniel,

On Wednesday 04 Jan 2017 17:13:23 Laurent Pinchart wrote:
> On Wednesday 04 Jan 2017 15:58:25 Daniel Vetter wrote:
> > On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> >> On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> >>> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> >>> enough, or not? My idea is to use this for the case where the only
> >>> thing in dt is the panel, with no real bridge chip. And I think we
> >>> don't need anything beyond that one _init function, plus maybe some
> >>> additional paramaters ...
> >> 
> >> There should be no bridge then. If you want the DRM core to manage
> >> panels automatically, then we should create specific helpers for that,
> >> not abuse the bridge infrastructure. Bridges should be instantiated from
> >> a hardware device and bound to drivers as usual.
> > 
> > I guess that's the part where I disagree: Just because there's physically
> > no bridge doesn't mean we shouldn't just treat it as one in the software
> > abstraction. If it looks and acts like a bridge (even an empty one), then
> > imo it can be a bridge.
> > 
> > If you insist on panels being panels, then I guess we need some other kind
> > of glue to bind them into arbitrary bridge chains. But given that the
> > callbacks match very closely, I don't see the point.
> > 
> > In an idea world a panel would probably derive from a drm_bridge, but
> > we're not in that universe unfortunately ;-)
> 
> Or both would derive from another object, but I agree that's how it should
> work. That's what I want to achieve, one step at a time. Creating dummy
> bridges isn't a step in that direction in my opinion, so I'd rather not do
> that, but work towards the right abstraction.

Do you object getting this patch merged as-is as a first step in the right 
direction ? :-)

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-03-02  0:30                     ` Laurent Pinchart
  0 siblings, 0 replies; 100+ messages in thread
From: Laurent Pinchart @ 2017-03-02  0:30 UTC (permalink / raw)
  To: dri-devel; +Cc: open list:DRM DRIVERS FOR RENESAS, Laurent Pinchart

Hi Daniel,

On Wednesday 04 Jan 2017 17:13:23 Laurent Pinchart wrote:
> On Wednesday 04 Jan 2017 15:58:25 Daniel Vetter wrote:
> > On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> >> On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> >>> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> >>> enough, or not? My idea is to use this for the case where the only
> >>> thing in dt is the panel, with no real bridge chip. And I think we
> >>> don't need anything beyond that one _init function, plus maybe some
> >>> additional paramaters ...
> >> 
> >> There should be no bridge then. If you want the DRM core to manage
> >> panels automatically, then we should create specific helpers for that,
> >> not abuse the bridge infrastructure. Bridges should be instantiated from
> >> a hardware device and bound to drivers as usual.
> > 
> > I guess that's the part where I disagree: Just because there's physically
> > no bridge doesn't mean we shouldn't just treat it as one in the software
> > abstraction. If it looks and acts like a bridge (even an empty one), then
> > imo it can be a bridge.
> > 
> > If you insist on panels being panels, then I guess we need some other kind
> > of glue to bind them into arbitrary bridge chains. But given that the
> > callbacks match very closely, I don't see the point.
> > 
> > In an idea world a panel would probably derive from a drm_bridge, but
> > we're not in that universe unfortunately ;-)
> 
> Or both would derive from another object, but I agree that's how it should
> work. That's what I want to achieve, one step at a time. Creating dummy
> bridges isn't a step in that direction in my opinion, so I'd rather not do
> that, but work towards the right abstraction.

Do you object getting this patch merged as-is as a first step in the right 
direction ? :-)

-- 
Regards,

Laurent Pinchart

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
  2017-03-02  0:30                     ` Laurent Pinchart
@ 2017-03-02  7:05                       ` Daniel Vetter
  -1 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2017-03-02  7:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, Daniel Vetter, open list:DRM DRIVERS FOR RENESAS,
	Laurent Pinchart

On Thu, Mar 02, 2017 at 02:30:09AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Wednesday 04 Jan 2017 17:13:23 Laurent Pinchart wrote:
> > On Wednesday 04 Jan 2017 15:58:25 Daniel Vetter wrote:
> > > On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> > >> On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> > >>> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> > >>> enough, or not? My idea is to use this for the case where the only
> > >>> thing in dt is the panel, with no real bridge chip. And I think we
> > >>> don't need anything beyond that one _init function, plus maybe some
> > >>> additional paramaters ...
> > >> 
> > >> There should be no bridge then. If you want the DRM core to manage
> > >> panels automatically, then we should create specific helpers for that,
> > >> not abuse the bridge infrastructure. Bridges should be instantiated from
> > >> a hardware device and bound to drivers as usual.
> > > 
> > > I guess that's the part where I disagree: Just because there's physically
> > > no bridge doesn't mean we shouldn't just treat it as one in the software
> > > abstraction. If it looks and acts like a bridge (even an empty one), then
> > > imo it can be a bridge.
> > > 
> > > If you insist on panels being panels, then I guess we need some other kind
> > > of glue to bind them into arbitrary bridge chains. But given that the
> > > callbacks match very closely, I don't see the point.
> > > 
> > > In an idea world a panel would probably derive from a drm_bridge, but
> > > we're not in that universe unfortunately ;-)
> > 
> > Or both would derive from another object, but I agree that's how it should
> > work. That's what I want to achieve, one step at a time. Creating dummy
> > bridges isn't a step in that direction in my opinion, so I'd rather not do
> > that, but work towards the right abstraction.
> 
> Do you object getting this patch merged as-is as a first step in the right 
> direction ? :-)

Well, I'm definitely no fan at all of typing code that's only there to
satisfy some fairly arbitrary normative choices we attach to the words we
pick for our abstraction.

But I'm also not going to stop you, just don't complain if I ask the next
dummy panel to reuse your LVDS bridge :-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver
@ 2017-03-02  7:05                       ` Daniel Vetter
  0 siblings, 0 replies; 100+ messages in thread
From: Daniel Vetter @ 2017-03-02  7:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: open list:DRM DRIVERS FOR RENESAS, Laurent Pinchart, dri-devel

On Thu, Mar 02, 2017 at 02:30:09AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Wednesday 04 Jan 2017 17:13:23 Laurent Pinchart wrote:
> > On Wednesday 04 Jan 2017 15:58:25 Daniel Vetter wrote:
> > > On Wed, Jan 04, 2017 at 04:33:57PM +0200, Laurent Pinchart wrote:
> > >> On Wednesday 04 Jan 2017 14:51:48 Daniel Vetter wrote:
> > >>> Hm, something like drm_bridge_panel_bridge_init(dev, panel) should be
> > >>> enough, or not? My idea is to use this for the case where the only
> > >>> thing in dt is the panel, with no real bridge chip. And I think we
> > >>> don't need anything beyond that one _init function, plus maybe some
> > >>> additional paramaters ...
> > >> 
> > >> There should be no bridge then. If you want the DRM core to manage
> > >> panels automatically, then we should create specific helpers for that,
> > >> not abuse the bridge infrastructure. Bridges should be instantiated from
> > >> a hardware device and bound to drivers as usual.
> > > 
> > > I guess that's the part where I disagree: Just because there's physically
> > > no bridge doesn't mean we shouldn't just treat it as one in the software
> > > abstraction. If it looks and acts like a bridge (even an empty one), then
> > > imo it can be a bridge.
> > > 
> > > If you insist on panels being panels, then I guess we need some other kind
> > > of glue to bind them into arbitrary bridge chains. But given that the
> > > callbacks match very closely, I don't see the point.
> > > 
> > > In an idea world a panel would probably derive from a drm_bridge, but
> > > we're not in that universe unfortunately ;-)
> > 
> > Or both would derive from another object, but I agree that's how it should
> > work. That's what I want to achieve, one step at a time. Creating dummy
> > bridges isn't a step in that direction in my opinion, so I'd rather not do
> > that, but work towards the right abstraction.
> 
> Do you object getting this patch merged as-is as a first step in the right 
> direction ? :-)

Well, I'm definitely no fan at all of typing code that's only there to
satisfy some fairly arbitrary normative choices we attach to the words we
pick for our abstraction.

But I'm also not going to stop you, just don't complain if I ask the next
dummy panel to reuse your LVDS bridge :-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 100+ messages in thread

end of thread, other threads:[~2017-03-02  7:05 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-29  9:04 [PATCH v3 00/13] R-Car DU: Use drm bridge API Laurent Pinchart
2016-11-29  9:04 ` Laurent Pinchart
2016-11-29  9:04 ` [PATCH v3 01/13] drm: Don't include <drm/drm_encoder.h> in <drm/drm_crtc.h> Laurent Pinchart
2016-11-29  9:30   ` Daniel Vetter
2016-11-29  9:30     ` Daniel Vetter
2016-11-29  9:37     ` Laurent Pinchart
2016-11-29  9:37       ` Laurent Pinchart
2016-12-02 21:21   ` Sinclair Yeh
2016-12-02 21:21     ` Sinclair Yeh
2016-11-29  9:04 ` [PATCH v3 02/13] drm: Fix compilation warning caused by static inline forward declaration Laurent Pinchart
2016-11-29  9:04   ` Laurent Pinchart
2016-11-29  9:31   ` Daniel Vetter
2016-11-29  9:31     ` Daniel Vetter
2016-11-29  9:04 ` [PATCH v3 03/13] drm: bridge: Link encoder and bridge in core code Laurent Pinchart
2016-11-29  9:04   ` Laurent Pinchart
2016-11-29  9:35   ` Daniel Vetter
2016-11-29  9:35     ` Daniel Vetter
2016-11-29  9:43     ` Laurent Pinchart
2016-11-29 10:05       ` Daniel Vetter
2016-11-29 10:05         ` Daniel Vetter
2016-11-29 18:02         ` Laurent Pinchart
2016-11-29 18:02           ` Laurent Pinchart
2016-11-29 18:51           ` Laurent Pinchart
2016-11-29 10:27   ` Archit Taneja
2016-11-29 10:27     ` Archit Taneja
2016-11-29 17:57     ` Laurent Pinchart
2016-11-29 17:57       ` Laurent Pinchart
2016-11-30  5:05       ` Archit Taneja
2016-11-30  5:05         ` Archit Taneja
2016-11-30 10:23         ` Laurent Pinchart
2016-11-30 10:23           ` Laurent Pinchart
2016-11-30 11:00           ` Archit Taneja
2016-11-30 11:00             ` Archit Taneja
2016-11-30 11:05             ` Laurent Pinchart
2016-11-30 11:05               ` Laurent Pinchart
2016-11-30 13:27               ` Archit Taneja
2016-11-30 13:27                 ` Archit Taneja
2016-11-29 17:01   ` Stefan Agner
2016-11-29 17:01     ` Stefan Agner
2016-11-29 19:58   ` Boris Brezillon
2016-11-29 19:58     ` Boris Brezillon
2016-11-30 15:30   ` Vincent ABRIOU
2016-11-30 15:30     ` Vincent ABRIOU
2016-11-29  9:04 ` [PATCH v3 04/13] drm: bridge: Detach bridge from encoder at encoder cleanup time Laurent Pinchart
2016-11-29  9:04   ` Laurent Pinchart
2016-11-29  9:48   ` Daniel Vetter
2016-11-29  9:48     ` Daniel Vetter
2016-11-29 19:00     ` Laurent Pinchart
2016-11-29 10:34   ` Archit Taneja
2016-11-29 18:56     ` Laurent Pinchart
2016-11-29 18:56       ` Laurent Pinchart
2016-11-29 20:22       ` Daniel Vetter
2016-11-29 20:22         ` Daniel Vetter
2016-11-29 21:54         ` [PATCH] drm: bridge: Detach all bridges in a chain " Laurent Pinchart
     [not found] ` <1480410283-28698-1-git-send-email-laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
2016-11-29  9:04   ` [PATCH v3 05/13] drm: bridge: Add LVDS encoder DT bindings Laurent Pinchart
2016-11-29  9:04     ` Laurent Pinchart
2016-11-29  9:04 ` [PATCH v3 06/13] drm: bridge: Add LVDS encoder driver Laurent Pinchart
2016-11-29  9:54   ` Daniel Vetter
2016-11-29 20:57     ` Laurent Pinchart
2016-11-29 20:57       ` Laurent Pinchart
2017-01-04  1:33       ` Laurent Pinchart
2017-01-04  8:18       ` Daniel Vetter
2017-01-04  8:18         ` Daniel Vetter
2017-01-04 13:08         ` Laurent Pinchart
2017-01-04 13:08           ` Laurent Pinchart
2017-01-04 13:51           ` Daniel Vetter
2017-01-04 14:33             ` Laurent Pinchart
2017-01-04 14:33               ` Laurent Pinchart
2017-01-04 14:58               ` Daniel Vetter
2017-01-04 14:58                 ` Daniel Vetter
2017-01-04 15:13                 ` Laurent Pinchart
2017-01-04 15:13                   ` Laurent Pinchart
2017-03-02  0:30                   ` Laurent Pinchart
2017-03-02  0:30                     ` Laurent Pinchart
2017-03-02  7:05                     ` Daniel Vetter
2017-03-02  7:05                       ` Daniel Vetter
2016-11-29  9:04 ` [PATCH v3 07/13] drm: bridge: vga-dac: Add adi,adv7123 compatible string Laurent Pinchart
2016-11-29  9:04   ` [PATCH v3 07/13] drm: bridge: vga-dac: Add adi, adv7123 " Laurent Pinchart
2016-11-29  9:50   ` [PATCH v3 07/13] drm: bridge: vga-dac: Add adi,adv7123 " Maxime Ripard
2016-11-29  9:50     ` Maxime Ripard
2016-11-29  9:04 ` [PATCH v3 08/13] drm: bridge: lvds-encoder: Add thine,thc63lvdm83d " Laurent Pinchart
2016-11-29  9:04   ` [PATCH v3 08/13] drm: bridge: lvds-encoder: Add thine, thc63lvdm83d " Laurent Pinchart
2016-11-29  9:04 ` [PATCH v3 09/13] drm: Add encoder_type field to the drm_bridge structure Laurent Pinchart
2016-11-29  9:56   ` Daniel Vetter
2016-11-29  9:58     ` Laurent Pinchart
2016-11-29  9:58       ` Laurent Pinchart
2016-11-29 10:27       ` Daniel Vetter
2016-11-29 10:27         ` Daniel Vetter
2016-11-29 17:49         ` Laurent Pinchart
2016-11-29 20:25           ` Daniel Vetter
2016-11-29 22:42             ` Laurent Pinchart
2016-11-29  9:04 ` [PATCH v3 10/13] drm: bridge: Set bridges' encoder type Laurent Pinchart
2016-11-29  9:04 ` [PATCH v3 11/13] drm: Set on-chip " Laurent Pinchart
2016-11-29  9:04   ` Laurent Pinchart
2016-11-30 15:28   ` Vincent ABRIOU
2016-11-30 15:28     ` Vincent ABRIOU
2016-11-29  9:04 ` [PATCH v3 12/13] drm: rcar-du: Replace manual bridge implementation with DRM bridge Laurent Pinchart
2016-12-27 12:40   ` Geert Uytterhoeven
2016-12-27 12:40     ` Geert Uytterhoeven
2016-11-29  9:04 ` [PATCH v3 13/13] drm: rcar-du: Initialize encoder's type based on the bridge's type Laurent Pinchart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.