All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-08 17:41   ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard, devicetree, Kamal Dasu, linux-clk,
	Michael Turquette, Philipp Zabel, Rob Herring, Stephen Boyd

Hi everyone,

Here's a (pretty long) series to introduce support in the VC4 DRM driver
for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).

The main differences are that there's two HDMI controllers and that there's
more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
have only 3 FIFOs. Both of those differences are breaking a bunch of
expectations in the driver, so we first need a good bunch of cleanup and
reworks to introduce support for the new controllers.

Similarly, the HDMI controller has all its registers shuffled and split in
multiple controllers now, so we need a bunch of changes to support this as
well.

Only the HDMI support is enabled for now (even though the DPI and DSI
outputs have been tested too).

Let me know if you have any comments
Maxime

Cc: bcm-kernel-feedback-list@broadcom.com
Cc: devicetree@vger.kernel.org
Cc: Kamal Dasu <kdasu.kdev@gmail.com>
Cc: linux-clk@vger.kernel.org
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>

Changes from v3:
  - Rebased on top of next-20200708
  - Added a name to the HDMI audio codec component
  - Only disable the BCM2711 HDMI pixelvalves at boot
  - Fixed an error in the HVS binding
  - Fix a framebuffer size condition that was inverted
  - Changed the channel allocation algorithm using Eric's suggestion
  - Always write the muxing values instead of updating if needed
  - Improved a bit the hvs_available_channels comment in the structure
  - Change atomic_complete_commit code to use for_each_new_crtc_in_state
  - Change the muxing code to take into account disparities between the
    BCM2711 and previous SoCs.
  - Only change the clock rate on BCM2711 during a modeset
  - Fix a crash at atomic_disable
  - Use clk_set_min_rate for the core clock too
  - Add a few defines, and simplify the FIFO level stuff
  - Reordered the patches according to Eric's reviews
  - Fixed a regression with VID_CTL setting on RPI3

Changes from v2:
  - Rebased on top of next-20200526
  - Split the firmware clock series away
  - Removed the stuck pixel (with all the subsequent pixels being shifted
    by one
  - Fixed the writeback issue too.
  - Fix the dual output
  - Fixed the return value of phy_get_cp_current
  - Enhanced the comment on the reset delay
  - Increase the max width and height
  - Made a proper Kconfig option for the DVP clock driver
  - Fixed the alsa card name collision

Changes from v1:
  - Rebased on top of 5.7-rc1
  - Run checkpatch
  - Added audio support
  - Fixed some HDMI timeouts
  - Swiched to clk_hw_register_gate_parent_data
  - Reorder Kconfig symbols in drivers/i2c/busses
  - Make the firmware clocks a child of the firmware node
  - Switch DVP clock driver to clk_hw interface
  - constify raspberrypi_clk_data in raspberrypi_clock_property
  - Don't mark firmware clocks as IGNORE_UNUSED
  - Change from reset_ms to reset_us in reset-simple, and add a bit more
    comments
  - Remove generic clk patch to test if a NULL pointer is returned
  - Removed misleading message in the is_prepared renaming patch commit
    message
  - Constify HDMI controller variants
  - Fix a bug in the allocation size of the clk data array
  - Added a mention in the DT binding conversion patches about the breakage
  - Merged a few fixes from kbuild
  - Fixed a few bisection and CEC build issues
  - Collected Acked-by and Reviewed-by
  - Change Dave email address to raspberrypi.com

Dave Stevenson (7):
  drm/vc4: Add support for the BCM2711 HVS5
  drm/vc4: plane: Change LBM alignment constraint on LBM
  drm/vc4: plane: Optimize the LBM allocation size
  drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
  drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
  drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
  drm/vc4: hdmi: Add audio-related callbacks

Maxime Ripard (71):
  dt-bindings: display: Add support for the BCM2711 HVS
  drm/vc4: hvs: Boost the core clock during modeset
  drm/vc4: plane: Create more planes
  drm/vc4: crtc: Deal with different number of pixel per clock
  drm/vc4: crtc: Use a shared interrupt
  drm/vc4: crtc: Move the cob allocation outside of bind
  drm/vc4: crtc: Rename HVS channel to output
  drm/vc4: crtc: Use local chan variable
  drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
  drm/vc4: kms: Convert to for_each_new_crtc_state
  drm/vc4: crtc: Assign output to channel automatically
  drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
  drm/vc4: crtc: Add function to compute FIFO level bits
  drm/vc4: crtc: Rename HDMI encoder type to HDMI0
  drm/vc4: crtc: Add HDMI1 encoder type
  drm/vc4: crtc: Disable color management for HVS5
  drm/vc4: crtc: Turn pixelvalve reset into a function
  drm/vc4: crtc: Move PV dump to config_pv
  drm/vc4: crtc: Move HVS init and close to a function
  drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
  drm/vc4: hvs: Make sure our channel is reset
  drm/vc4: crtc: Remove mode_set_nofb
  drm/vc4: crtc: Remove redundant pixelvalve reset
  drm/vc4: crtc: Move HVS channel init before the PV initialisation
  drm/vc4: encoder: Add finer-grained encoder callbacks
  drm/vc4: crtc: Add a delay after disabling the PixelValve output
  drm/vc4: crtc: Clear the PixelValve FIFO on disable
  drm/vc4: crtc: Clear the PixelValve FIFO during configuration
  drm/vc4: hvs: Make the stop_channel function public
  drm/vc4: hvs: Introduce a function to get the assigned FIFO
  drm/vc4: crtc: Move the CRTC disable out
  drm/vc4: drv: Disable the CRTC at boot time
  dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
  drm/vc4: crtc: Add BCM2711 pixelvalves
  drm/vc4: hdmi: Use debugfs private field
  drm/vc4: hdmi: Move structure to header
  drm/vc4: hdmi: rework connectors and encoders
  drm/vc4: hdmi: Remove DDC argument to connector_init
  drm/vc4: hdmi: Rename hdmi to vc4_hdmi
  drm/vc4: hdmi: Move accessors to vc4_hdmi
  drm/vc4: hdmi: Use local vc4_hdmi directly
  drm/vc4: hdmi: Add container_of macros for encoders and connectors
  drm/vc4: hdmi: Pass vc4_hdmi to CEC code
  drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
  drm/vc4: hdmi: Remove vc4_dev hdmi pointer
  drm/vc4: hdmi: Remove vc4_hdmi_connector
  drm/vc4: hdmi: Introduce resource init and variant
  drm/vc4: hdmi: Implement a register layout abstraction
  drm/vc4: hdmi: Add reset callback
  drm/vc4: hdmi: Add PHY init and disable function
  drm/vc4: hdmi: Add PHY RNG enable / disable function
  drm/vc4: hdmi: Add a CSC setup callback
  drm/vc4: hdmi: Store the encoder type in the variant structure
  drm/vc4: hdmi: Deal with multiple debugfs files
  drm/vc4: hdmi: Move CEC init to its own function
  drm/vc4: hdmi: Add CEC support flag
  drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
  drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
  drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  drm/vc4: hdmi: Use clk_set_min_rate instead
  drm/vc4: hdmi: Deal with multiple ALSA cards
  drm/vc4: hdmi: Remove register dumps in enable
  drm/vc4: hdmi: Always recenter the HDMI FIFO
  drm/vc4: hdmi: Implement finer-grained hooks
  drm/vc4: hdmi: Do the VID_CTL configuration at once
  drm/vc4: hdmi: Switch to blank pixels when disabled
  drm/vc4: hdmi: Support the BCM2711 HDMI controllers
  dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
  dt-bindings: display: vc4: Document BCM2711 VC5
  drm/vc4: drv: Support BCM2711
  ARM: dts: bcm2711: Enable the display pipeline

 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
 arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
 drivers/gpu/drm/vc4/Makefile                                            |    1 +-
 drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
 drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
 drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
 drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
 drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
 drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
 drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
 19 files changed, 3331 insertions(+), 1008 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h

base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
-- 
git-series 0.9.1

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

* [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-08 17:41   ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
	Michael Turquette, Kamal Dasu, linux-kernel, dri-devel,
	linux-clk, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Philipp Zabel, Phil Elwell, linux-arm-kernel,
	Maxime Ripard

Hi everyone,

Here's a (pretty long) series to introduce support in the VC4 DRM driver
for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).

The main differences are that there's two HDMI controllers and that there's
more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
have only 3 FIFOs. Both of those differences are breaking a bunch of
expectations in the driver, so we first need a good bunch of cleanup and
reworks to introduce support for the new controllers.

Similarly, the HDMI controller has all its registers shuffled and split in
multiple controllers now, so we need a bunch of changes to support this as
well.

Only the HDMI support is enabled for now (even though the DPI and DSI
outputs have been tested too).

Let me know if you have any comments
Maxime

Cc: bcm-kernel-feedback-list@broadcom.com
Cc: devicetree@vger.kernel.org
Cc: Kamal Dasu <kdasu.kdev@gmail.com>
Cc: linux-clk@vger.kernel.org
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>

Changes from v3:
  - Rebased on top of next-20200708
  - Added a name to the HDMI audio codec component
  - Only disable the BCM2711 HDMI pixelvalves at boot
  - Fixed an error in the HVS binding
  - Fix a framebuffer size condition that was inverted
  - Changed the channel allocation algorithm using Eric's suggestion
  - Always write the muxing values instead of updating if needed
  - Improved a bit the hvs_available_channels comment in the structure
  - Change atomic_complete_commit code to use for_each_new_crtc_in_state
  - Change the muxing code to take into account disparities between the
    BCM2711 and previous SoCs.
  - Only change the clock rate on BCM2711 during a modeset
  - Fix a crash at atomic_disable
  - Use clk_set_min_rate for the core clock too
  - Add a few defines, and simplify the FIFO level stuff
  - Reordered the patches according to Eric's reviews
  - Fixed a regression with VID_CTL setting on RPI3

Changes from v2:
  - Rebased on top of next-20200526
  - Split the firmware clock series away
  - Removed the stuck pixel (with all the subsequent pixels being shifted
    by one
  - Fixed the writeback issue too.
  - Fix the dual output
  - Fixed the return value of phy_get_cp_current
  - Enhanced the comment on the reset delay
  - Increase the max width and height
  - Made a proper Kconfig option for the DVP clock driver
  - Fixed the alsa card name collision

Changes from v1:
  - Rebased on top of 5.7-rc1
  - Run checkpatch
  - Added audio support
  - Fixed some HDMI timeouts
  - Swiched to clk_hw_register_gate_parent_data
  - Reorder Kconfig symbols in drivers/i2c/busses
  - Make the firmware clocks a child of the firmware node
  - Switch DVP clock driver to clk_hw interface
  - constify raspberrypi_clk_data in raspberrypi_clock_property
  - Don't mark firmware clocks as IGNORE_UNUSED
  - Change from reset_ms to reset_us in reset-simple, and add a bit more
    comments
  - Remove generic clk patch to test if a NULL pointer is returned
  - Removed misleading message in the is_prepared renaming patch commit
    message
  - Constify HDMI controller variants
  - Fix a bug in the allocation size of the clk data array
  - Added a mention in the DT binding conversion patches about the breakage
  - Merged a few fixes from kbuild
  - Fixed a few bisection and CEC build issues
  - Collected Acked-by and Reviewed-by
  - Change Dave email address to raspberrypi.com

Dave Stevenson (7):
  drm/vc4: Add support for the BCM2711 HVS5
  drm/vc4: plane: Change LBM alignment constraint on LBM
  drm/vc4: plane: Optimize the LBM allocation size
  drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
  drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
  drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
  drm/vc4: hdmi: Add audio-related callbacks

Maxime Ripard (71):
  dt-bindings: display: Add support for the BCM2711 HVS
  drm/vc4: hvs: Boost the core clock during modeset
  drm/vc4: plane: Create more planes
  drm/vc4: crtc: Deal with different number of pixel per clock
  drm/vc4: crtc: Use a shared interrupt
  drm/vc4: crtc: Move the cob allocation outside of bind
  drm/vc4: crtc: Rename HVS channel to output
  drm/vc4: crtc: Use local chan variable
  drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
  drm/vc4: kms: Convert to for_each_new_crtc_state
  drm/vc4: crtc: Assign output to channel automatically
  drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
  drm/vc4: crtc: Add function to compute FIFO level bits
  drm/vc4: crtc: Rename HDMI encoder type to HDMI0
  drm/vc4: crtc: Add HDMI1 encoder type
  drm/vc4: crtc: Disable color management for HVS5
  drm/vc4: crtc: Turn pixelvalve reset into a function
  drm/vc4: crtc: Move PV dump to config_pv
  drm/vc4: crtc: Move HVS init and close to a function
  drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
  drm/vc4: hvs: Make sure our channel is reset
  drm/vc4: crtc: Remove mode_set_nofb
  drm/vc4: crtc: Remove redundant pixelvalve reset
  drm/vc4: crtc: Move HVS channel init before the PV initialisation
  drm/vc4: encoder: Add finer-grained encoder callbacks
  drm/vc4: crtc: Add a delay after disabling the PixelValve output
  drm/vc4: crtc: Clear the PixelValve FIFO on disable
  drm/vc4: crtc: Clear the PixelValve FIFO during configuration
  drm/vc4: hvs: Make the stop_channel function public
  drm/vc4: hvs: Introduce a function to get the assigned FIFO
  drm/vc4: crtc: Move the CRTC disable out
  drm/vc4: drv: Disable the CRTC at boot time
  dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
  drm/vc4: crtc: Add BCM2711 pixelvalves
  drm/vc4: hdmi: Use debugfs private field
  drm/vc4: hdmi: Move structure to header
  drm/vc4: hdmi: rework connectors and encoders
  drm/vc4: hdmi: Remove DDC argument to connector_init
  drm/vc4: hdmi: Rename hdmi to vc4_hdmi
  drm/vc4: hdmi: Move accessors to vc4_hdmi
  drm/vc4: hdmi: Use local vc4_hdmi directly
  drm/vc4: hdmi: Add container_of macros for encoders and connectors
  drm/vc4: hdmi: Pass vc4_hdmi to CEC code
  drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
  drm/vc4: hdmi: Remove vc4_dev hdmi pointer
  drm/vc4: hdmi: Remove vc4_hdmi_connector
  drm/vc4: hdmi: Introduce resource init and variant
  drm/vc4: hdmi: Implement a register layout abstraction
  drm/vc4: hdmi: Add reset callback
  drm/vc4: hdmi: Add PHY init and disable function
  drm/vc4: hdmi: Add PHY RNG enable / disable function
  drm/vc4: hdmi: Add a CSC setup callback
  drm/vc4: hdmi: Store the encoder type in the variant structure
  drm/vc4: hdmi: Deal with multiple debugfs files
  drm/vc4: hdmi: Move CEC init to its own function
  drm/vc4: hdmi: Add CEC support flag
  drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
  drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
  drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  drm/vc4: hdmi: Use clk_set_min_rate instead
  drm/vc4: hdmi: Deal with multiple ALSA cards
  drm/vc4: hdmi: Remove register dumps in enable
  drm/vc4: hdmi: Always recenter the HDMI FIFO
  drm/vc4: hdmi: Implement finer-grained hooks
  drm/vc4: hdmi: Do the VID_CTL configuration at once
  drm/vc4: hdmi: Switch to blank pixels when disabled
  drm/vc4: hdmi: Support the BCM2711 HDMI controllers
  dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
  dt-bindings: display: vc4: Document BCM2711 VC5
  drm/vc4: drv: Support BCM2711
  ARM: dts: bcm2711: Enable the display pipeline

 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
 arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
 drivers/gpu/drm/vc4/Makefile                                            |    1 +-
 drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
 drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
 drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
 drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
 drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
 drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
 drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
 19 files changed, 3331 insertions(+), 1008 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h

base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-08 17:41   ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
	Michael Turquette, Kamal Dasu, linux-kernel, dri-devel,
	linux-clk, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Phil Elwell, linux-arm-kernel, Maxime Ripard

Hi everyone,

Here's a (pretty long) series to introduce support in the VC4 DRM driver
for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).

The main differences are that there's two HDMI controllers and that there's
more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
have only 3 FIFOs. Both of those differences are breaking a bunch of
expectations in the driver, so we first need a good bunch of cleanup and
reworks to introduce support for the new controllers.

Similarly, the HDMI controller has all its registers shuffled and split in
multiple controllers now, so we need a bunch of changes to support this as
well.

Only the HDMI support is enabled for now (even though the DPI and DSI
outputs have been tested too).

Let me know if you have any comments
Maxime

Cc: bcm-kernel-feedback-list@broadcom.com
Cc: devicetree@vger.kernel.org
Cc: Kamal Dasu <kdasu.kdev@gmail.com>
Cc: linux-clk@vger.kernel.org
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>

Changes from v3:
  - Rebased on top of next-20200708
  - Added a name to the HDMI audio codec component
  - Only disable the BCM2711 HDMI pixelvalves at boot
  - Fixed an error in the HVS binding
  - Fix a framebuffer size condition that was inverted
  - Changed the channel allocation algorithm using Eric's suggestion
  - Always write the muxing values instead of updating if needed
  - Improved a bit the hvs_available_channels comment in the structure
  - Change atomic_complete_commit code to use for_each_new_crtc_in_state
  - Change the muxing code to take into account disparities between the
    BCM2711 and previous SoCs.
  - Only change the clock rate on BCM2711 during a modeset
  - Fix a crash at atomic_disable
  - Use clk_set_min_rate for the core clock too
  - Add a few defines, and simplify the FIFO level stuff
  - Reordered the patches according to Eric's reviews
  - Fixed a regression with VID_CTL setting on RPI3

Changes from v2:
  - Rebased on top of next-20200526
  - Split the firmware clock series away
  - Removed the stuck pixel (with all the subsequent pixels being shifted
    by one
  - Fixed the writeback issue too.
  - Fix the dual output
  - Fixed the return value of phy_get_cp_current
  - Enhanced the comment on the reset delay
  - Increase the max width and height
  - Made a proper Kconfig option for the DVP clock driver
  - Fixed the alsa card name collision

Changes from v1:
  - Rebased on top of 5.7-rc1
  - Run checkpatch
  - Added audio support
  - Fixed some HDMI timeouts
  - Swiched to clk_hw_register_gate_parent_data
  - Reorder Kconfig symbols in drivers/i2c/busses
  - Make the firmware clocks a child of the firmware node
  - Switch DVP clock driver to clk_hw interface
  - constify raspberrypi_clk_data in raspberrypi_clock_property
  - Don't mark firmware clocks as IGNORE_UNUSED
  - Change from reset_ms to reset_us in reset-simple, and add a bit more
    comments
  - Remove generic clk patch to test if a NULL pointer is returned
  - Removed misleading message in the is_prepared renaming patch commit
    message
  - Constify HDMI controller variants
  - Fix a bug in the allocation size of the clk data array
  - Added a mention in the DT binding conversion patches about the breakage
  - Merged a few fixes from kbuild
  - Fixed a few bisection and CEC build issues
  - Collected Acked-by and Reviewed-by
  - Change Dave email address to raspberrypi.com

Dave Stevenson (7):
  drm/vc4: Add support for the BCM2711 HVS5
  drm/vc4: plane: Change LBM alignment constraint on LBM
  drm/vc4: plane: Optimize the LBM allocation size
  drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
  drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
  drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
  drm/vc4: hdmi: Add audio-related callbacks

Maxime Ripard (71):
  dt-bindings: display: Add support for the BCM2711 HVS
  drm/vc4: hvs: Boost the core clock during modeset
  drm/vc4: plane: Create more planes
  drm/vc4: crtc: Deal with different number of pixel per clock
  drm/vc4: crtc: Use a shared interrupt
  drm/vc4: crtc: Move the cob allocation outside of bind
  drm/vc4: crtc: Rename HVS channel to output
  drm/vc4: crtc: Use local chan variable
  drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
  drm/vc4: kms: Convert to for_each_new_crtc_state
  drm/vc4: crtc: Assign output to channel automatically
  drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
  drm/vc4: crtc: Add function to compute FIFO level bits
  drm/vc4: crtc: Rename HDMI encoder type to HDMI0
  drm/vc4: crtc: Add HDMI1 encoder type
  drm/vc4: crtc: Disable color management for HVS5
  drm/vc4: crtc: Turn pixelvalve reset into a function
  drm/vc4: crtc: Move PV dump to config_pv
  drm/vc4: crtc: Move HVS init and close to a function
  drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
  drm/vc4: hvs: Make sure our channel is reset
  drm/vc4: crtc: Remove mode_set_nofb
  drm/vc4: crtc: Remove redundant pixelvalve reset
  drm/vc4: crtc: Move HVS channel init before the PV initialisation
  drm/vc4: encoder: Add finer-grained encoder callbacks
  drm/vc4: crtc: Add a delay after disabling the PixelValve output
  drm/vc4: crtc: Clear the PixelValve FIFO on disable
  drm/vc4: crtc: Clear the PixelValve FIFO during configuration
  drm/vc4: hvs: Make the stop_channel function public
  drm/vc4: hvs: Introduce a function to get the assigned FIFO
  drm/vc4: crtc: Move the CRTC disable out
  drm/vc4: drv: Disable the CRTC at boot time
  dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
  drm/vc4: crtc: Add BCM2711 pixelvalves
  drm/vc4: hdmi: Use debugfs private field
  drm/vc4: hdmi: Move structure to header
  drm/vc4: hdmi: rework connectors and encoders
  drm/vc4: hdmi: Remove DDC argument to connector_init
  drm/vc4: hdmi: Rename hdmi to vc4_hdmi
  drm/vc4: hdmi: Move accessors to vc4_hdmi
  drm/vc4: hdmi: Use local vc4_hdmi directly
  drm/vc4: hdmi: Add container_of macros for encoders and connectors
  drm/vc4: hdmi: Pass vc4_hdmi to CEC code
  drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
  drm/vc4: hdmi: Remove vc4_dev hdmi pointer
  drm/vc4: hdmi: Remove vc4_hdmi_connector
  drm/vc4: hdmi: Introduce resource init and variant
  drm/vc4: hdmi: Implement a register layout abstraction
  drm/vc4: hdmi: Add reset callback
  drm/vc4: hdmi: Add PHY init and disable function
  drm/vc4: hdmi: Add PHY RNG enable / disable function
  drm/vc4: hdmi: Add a CSC setup callback
  drm/vc4: hdmi: Store the encoder type in the variant structure
  drm/vc4: hdmi: Deal with multiple debugfs files
  drm/vc4: hdmi: Move CEC init to its own function
  drm/vc4: hdmi: Add CEC support flag
  drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
  drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
  drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  drm/vc4: hdmi: Use clk_set_min_rate instead
  drm/vc4: hdmi: Deal with multiple ALSA cards
  drm/vc4: hdmi: Remove register dumps in enable
  drm/vc4: hdmi: Always recenter the HDMI FIFO
  drm/vc4: hdmi: Implement finer-grained hooks
  drm/vc4: hdmi: Do the VID_CTL configuration at once
  drm/vc4: hdmi: Switch to blank pixels when disabled
  drm/vc4: hdmi: Support the BCM2711 HDMI controllers
  dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
  dt-bindings: display: vc4: Document BCM2711 VC5
  drm/vc4: drv: Support BCM2711
  ARM: dts: bcm2711: Enable the display pipeline

 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
 arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
 drivers/gpu/drm/vc4/Makefile                                            |    1 +-
 drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
 drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
 drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
 drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
 drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
 drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
 drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
 19 files changed, 3331 insertions(+), 1008 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h

base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 01/78] dt-bindings: display: Add support for the BCM2711 HVS
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HVS found in the BCM2711 is slightly different from the previous
generations, let's add a compatible for it.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml | 18 ++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
index 02410f8d6d49..e826ab0adb75 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
@@ -11,7 +11,9 @@ maintainers:
 
 properties:
   compatible:
-    const: brcm,bcm2835-hvs
+    enum:
+      - brcm,bcm2711-hvs
+      - brcm,bcm2835-hvs
 
   reg:
     maxItems: 1
@@ -19,6 +21,10 @@ properties:
   interrupts:
     maxItems: 1
 
+  clocks:
+    maxItems: 1
+    description: Core Clock
+
 required:
   - compatible
   - reg
@@ -26,6 +32,16 @@ required:
 
 additionalProperties: false
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: brcm,bcm2711-hvs"
+
+then:
+  required:
+    - clocks
+
 examples:
   - |
     hvs@7e400000 {
-- 
git-series 0.9.1

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

* [PATCH v4 01/78] dt-bindings: display: Add support for the BCM2711 HVS
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HVS found in the BCM2711 is slightly different from the previous
generations, let's add a compatible for it.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml | 18 ++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
index 02410f8d6d49..e826ab0adb75 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
@@ -11,7 +11,9 @@ maintainers:
 
 properties:
   compatible:
-    const: brcm,bcm2835-hvs
+    enum:
+      - brcm,bcm2711-hvs
+      - brcm,bcm2835-hvs
 
   reg:
     maxItems: 1
@@ -19,6 +21,10 @@ properties:
   interrupts:
     maxItems: 1
 
+  clocks:
+    maxItems: 1
+    description: Core Clock
+
 required:
   - compatible
   - reg
@@ -26,6 +32,16 @@ required:
 
 additionalProperties: false
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: brcm,bcm2711-hvs"
+
+then:
+  required:
+    - clocks
+
 examples:
   - |
     hvs@7e400000 {
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 01/78] dt-bindings: display: Add support for the BCM2711 HVS
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HVS found in the BCM2711 is slightly different from the previous
generations, let's add a compatible for it.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml | 18 ++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
index 02410f8d6d49..e826ab0adb75 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
@@ -11,7 +11,9 @@ maintainers:
 
 properties:
   compatible:
-    const: brcm,bcm2835-hvs
+    enum:
+      - brcm,bcm2711-hvs
+      - brcm,bcm2835-hvs
 
   reg:
     maxItems: 1
@@ -19,6 +21,10 @@ properties:
   interrupts:
     maxItems: 1
 
+  clocks:
+    maxItems: 1
+    description: Core Clock
+
 required:
   - compatible
   - reg
@@ -26,6 +32,16 @@ required:
 
 additionalProperties: false
 
+if:
+  properties:
+    compatible:
+      contains:
+        const: brcm,bcm2711-hvs"
+
+then:
+  required:
+    - clocks
+
 examples:
   - |
     hvs@7e400000 {
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 02/78] drm/vc4: Add support for the BCM2711 HVS5
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The HVS found in the BCM2711 is slightly different from the previous
generations.

Most notably, the display list layout changes a bit, the LBM doesn't have
the same size and the formats ordering for some formats is swapped.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h   |   4 +-
 drivers/gpu/drm/vc4/vc4_hvs.c   |  34 ++++--
 drivers/gpu/drm/vc4/vc4_plane.c | 194 ++++++++++++++++++++++++---------
 drivers/gpu/drm/vc4/vc4_regs.h  |  67 +++++++++++-
 4 files changed, 240 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index fa19160c801f..e4cde1f9224b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -329,7 +329,11 @@ struct vc4_hvs {
 	spinlock_t mm_lock;
 
 	struct drm_mm_node mitchell_netravali_filter;
+
 	struct debugfs_regset32 regset;
+
+	/* HVS version 5 flag, therefore requires updated dlist structures */
+	bool hvs5;
 };
 
 struct vc4_plane {
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 2d2bf59c0503..836d8799d79e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -277,11 +277,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 	 * mode.
 	 */
 	dispctrl = SCALER_DISPCTRLX_ENABLE;
-	dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-				  SCALER_DISPCTRLX_WIDTH) |
-		    VC4_SET_FIELD(mode->vdisplay,
-				  SCALER_DISPCTRLX_HEIGHT) |
-		    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+
+	if (!vc4->hvs->hvs5)
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+	else
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER5_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER5_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
 	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
 }
@@ -521,6 +529,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 
 	hvs->pdev = pdev;
 
+	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs"))
+		hvs->hvs5 = true;
+
 	hvs->regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hvs->regs))
 		return PTR_ERR(hvs->regs);
@@ -529,7 +540,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	hvs->regset.regs = hvs_regs;
 	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 
-	hvs->dlist = hvs->regs + SCALER_DLIST_START;
+	if (!hvs->hvs5)
+		hvs->dlist = hvs->regs + SCALER_DLIST_START;
+	else
+		hvs->dlist = hvs->regs + SCALER5_DLIST_START;
 
 	spin_lock_init(&hvs->mm_lock);
 
@@ -547,7 +561,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	 * between planes when they don't overlap on the screen, but
 	 * for now we just allocate globally.
 	 */
-	drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
+	if (!hvs->hvs5)
+		/* 96kB */
+		drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
+	else
+		/* 70k words */
+		drm_mm_init(&hvs->lbm_mm, 0, 70 * 2 * 1024);
 
 	/* Upload filter kernels.  We only have the one for now, so we
 	 * keep it around for the lifetime of the driver.
@@ -632,6 +651,7 @@ static int vc4_hvs_dev_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id vc4_hvs_dt_match[] = {
+	{ .compatible = "brcm,bcm2711-hvs" },
 	{ .compatible = "brcm,bcm2835-hvs" },
 	{}
 };
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index d040d9f12c6d..20c949b57827 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -32,45 +32,60 @@ static const struct hvs_format {
 	u32 drm; /* DRM_FORMAT_* */
 	u32 hvs; /* HVS_FORMAT_* */
 	u32 pixel_order;
+	u32 pixel_order_hvs5;
 } hvs_formats[] = {
 	{
-		.drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_XRGB8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
 	},
 	{
-		.drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_ARGB8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
 	},
 	{
-		.drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_ABGR8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ARGB,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_XBGR8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ARGB,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565,
+		.drm = DRM_FORMAT_RGB565,
+		.hvs = HVS_PIXEL_FORMAT_RGB565,
 		.pixel_order = HVS_PIXEL_ORDER_XRGB,
 	},
 	{
-		.drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565,
+		.drm = DRM_FORMAT_BGR565,
+		.hvs = HVS_PIXEL_FORMAT_RGB565,
 		.pixel_order = HVS_PIXEL_ORDER_XBGR,
 	},
 	{
-		.drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
+		.drm = DRM_FORMAT_ARGB1555,
+		.hvs = HVS_PIXEL_FORMAT_RGBA5551,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
+		.drm = DRM_FORMAT_XRGB1555,
+		.hvs = HVS_PIXEL_FORMAT_RGBA5551,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+		.drm = DRM_FORMAT_RGB888,
+		.hvs = HVS_PIXEL_FORMAT_RGB888,
 		.pixel_order = HVS_PIXEL_ORDER_XRGB,
 	},
 	{
-		.drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+		.drm = DRM_FORMAT_BGR888,
+		.hvs = HVS_PIXEL_FORMAT_RGB888,
 		.pixel_order = HVS_PIXEL_ORDER_XBGR,
 	},
 	{
@@ -776,35 +791,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 		return -EINVAL;
 	}
 
-	/* Control word */
-	vc4_dlist_write(vc4_state,
-			SCALER_CTL0_VALID |
-			(rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
-			(rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
-			VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
-			(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
-			(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
-			VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
-			(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
-			VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
-			VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
-
-	/* Position Word 0: Image Positions and Alpha Value */
-	vc4_state->pos0_offset = vc4_state->dlist_count;
-	vc4_dlist_write(vc4_state,
-			VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) |
-			VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
-			VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
-
-	/* Position Word 1: Scaled Image Dimensions. */
-	if (!vc4_state->is_unity) {
-		vc4_dlist_write(vc4_state,
-				VC4_SET_FIELD(vc4_state->crtc_w,
-					      SCALER_POS1_SCL_WIDTH) |
-				VC4_SET_FIELD(vc4_state->crtc_h,
-					      SCALER_POS1_SCL_HEIGHT));
-	}
-
 	/* Don't waste cycles mixing with plane alpha if the set alpha
 	 * is opaque or there is no per-pixel alpha information.
 	 * In any case we use the alpha property value as the fixed alpha.
@@ -812,20 +798,120 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 	mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE &&
 			  fb->format->has_alpha;
 
-	/* Position Word 2: Source Image Size, Alpha */
-	vc4_state->pos2_offset = vc4_state->dlist_count;
-	vc4_dlist_write(vc4_state,
-			VC4_SET_FIELD(fb->format->has_alpha ?
-				      SCALER_POS2_ALPHA_MODE_PIPELINE :
-				      SCALER_POS2_ALPHA_MODE_FIXED,
-				      SCALER_POS2_ALPHA_MODE) |
-			(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
-			(fb->format->has_alpha ? SCALER_POS2_ALPHA_PREMULT : 0) |
-			VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) |
-			VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT));
+	if (!vc4->hvs->hvs5) {
+	/* Control word */
+		vc4_dlist_write(vc4_state,
+				SCALER_CTL0_VALID |
+				(rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
+				(rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
+				VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
+				(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+				(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+				VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+				(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
+				VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+				VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
+
+		/* Position Word 0: Image Positions and Alpha Value */
+		vc4_state->pos0_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) |
+				VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
+				VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
+
+		/* Position Word 1: Scaled Image Dimensions. */
+		if (!vc4_state->is_unity) {
+			vc4_dlist_write(vc4_state,
+					VC4_SET_FIELD(vc4_state->crtc_w,
+						      SCALER_POS1_SCL_WIDTH) |
+					VC4_SET_FIELD(vc4_state->crtc_h,
+						      SCALER_POS1_SCL_HEIGHT));
+		}
+
+		/* Position Word 2: Source Image Size, Alpha */
+		vc4_state->pos2_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(fb->format->has_alpha ?
+					      SCALER_POS2_ALPHA_MODE_PIPELINE :
+					      SCALER_POS2_ALPHA_MODE_FIXED,
+					      SCALER_POS2_ALPHA_MODE) |
+				(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
+				(fb->format->has_alpha ?
+						SCALER_POS2_ALPHA_PREMULT : 0) |
+				VC4_SET_FIELD(vc4_state->src_w[0],
+					      SCALER_POS2_WIDTH) |
+				VC4_SET_FIELD(vc4_state->src_h[0],
+					      SCALER_POS2_HEIGHT));
+
+		/* Position Word 3: Context.  Written by the HVS. */
+		vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+	} else {
+		u32 hvs_pixel_order = format->pixel_order;
 
-	/* Position Word 3: Context.  Written by the HVS. */
-	vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+		if (format->pixel_order_hvs5)
+			hvs_pixel_order = format->pixel_order_hvs5;
+
+		/* Control word */
+		vc4_dlist_write(vc4_state,
+				SCALER_CTL0_VALID |
+				(hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+				(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+				VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+				(vc4_state->is_unity ?
+						SCALER5_CTL0_UNITY : 0) |
+				VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+				VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) |
+				SCALER5_CTL0_ALPHA_EXPAND |
+				SCALER5_CTL0_RGB_EXPAND);
+
+		/* Position Word 0: Image Positions and Alpha Value */
+		vc4_state->pos0_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				(rotation & DRM_MODE_REFLECT_Y ?
+						SCALER5_POS0_VFLIP : 0) |
+				VC4_SET_FIELD(vc4_state->crtc_x,
+					      SCALER_POS0_START_X) |
+				(rotation & DRM_MODE_REFLECT_X ?
+					      SCALER5_POS0_HFLIP : 0) |
+				VC4_SET_FIELD(vc4_state->crtc_y,
+					      SCALER5_POS0_START_Y)
+			       );
+
+		/* Control Word 2 */
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(state->alpha >> 4,
+					      SCALER5_CTL2_ALPHA) |
+				fb->format->has_alpha ?
+					SCALER5_CTL2_ALPHA_PREMULT : 0 |
+				(mix_plane_alpha ?
+					SCALER5_CTL2_ALPHA_MIX : 0) |
+				VC4_SET_FIELD(fb->format->has_alpha ?
+				      SCALER5_CTL2_ALPHA_MODE_PIPELINE :
+				      SCALER5_CTL2_ALPHA_MODE_FIXED,
+				      SCALER5_CTL2_ALPHA_MODE)
+			       );
+
+		/* Position Word 1: Scaled Image Dimensions. */
+		if (!vc4_state->is_unity) {
+			vc4_dlist_write(vc4_state,
+					VC4_SET_FIELD(vc4_state->crtc_w,
+						      SCALER_POS1_SCL_WIDTH) |
+					VC4_SET_FIELD(vc4_state->crtc_h,
+						      SCALER_POS1_SCL_HEIGHT));
+		}
+
+		/* Position Word 2: Source Image Size */
+		vc4_state->pos2_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(vc4_state->src_w[0],
+					      SCALER5_POS2_WIDTH) |
+				VC4_SET_FIELD(vc4_state->src_h[0],
+					      SCALER5_POS2_HEIGHT));
+
+		/* Position Word 3: Context.  Written by the HVS. */
+		vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+	}
 
 
 	/* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers
@@ -1203,6 +1289,10 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
 		default:
 			return false;
 		}
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
 	case DRM_FORMAT_YUV422:
 	case DRM_FORMAT_YVU422:
 	case DRM_FORMAT_YUV420:
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 324462cc9cd4..91b785725555 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -327,6 +327,20 @@
 # define SCALER_DISPCTRLX_HEIGHT_MASK		VC4_MASK(11, 0)
 # define SCALER_DISPCTRLX_HEIGHT_SHIFT		0
 
+# define SCALER5_DISPCTRLX_WIDTH_MASK		VC4_MASK(28, 16)
+# define SCALER5_DISPCTRLX_WIDTH_SHIFT		16
+/* Generates a single frame when VSTART is seen and stops at the last
+ * pixel read from the FIFO.
+ */
+# define SCALER5_DISPCTRLX_ONESHOT		BIT(15)
+/* Processes a single context in the dlist and then task switch,
+ * instead of an entire line.
+ */
+# define SCALER5_DISPCTRLX_ONECTX_MASK		VC4_MASK(14, 13)
+# define SCALER5_DISPCTRLX_ONECTX_SHIFT		13
+# define SCALER5_DISPCTRLX_HEIGHT_MASK		VC4_MASK(12, 0)
+# define SCALER5_DISPCTRLX_HEIGHT_SHIFT		0
+
 #define SCALER_DISPBKGND0                       0x00000044
 # define SCALER_DISPBKGND_AUTOHS		BIT(31)
 # define SCALER_DISPBKGND_INTERLACE		BIT(30)
@@ -460,6 +474,8 @@
 #define SCALER_DLIST_START                      0x00002000
 #define SCALER_DLIST_SIZE                       0x00004000
 
+#define SCALER5_DLIST_START			0x00004000
+
 #define VC4_HDMI_CORE_REV			0x000
 
 #define VC4_HDMI_SW_RESET_CONTROL		0x004
@@ -825,6 +841,8 @@ enum hvs_pixel_format {
 	HVS_PIXEL_FORMAT_PALETTE = 13,
 	HVS_PIXEL_FORMAT_YUV444_RGB = 14,
 	HVS_PIXEL_FORMAT_AYUV444_RGB = 15,
+	HVS_PIXEL_FORMAT_RGBA1010102 = 16,
+	HVS_PIXEL_FORMAT_YCBCR_10BIT = 17,
 };
 
 /* Note: the LSB is the rightmost character shown.  Only valid for
@@ -879,6 +897,10 @@ enum hvs_pixel_format {
 #define SCALER_CTL0_RGBA_EXPAND_MSB		2
 #define SCALER_CTL0_RGBA_EXPAND_ROUND		3
 
+#define SCALER5_CTL0_ALPHA_EXPAND		BIT(12)
+
+#define SCALER5_CTL0_RGB_EXPAND			BIT(11)
+
 #define SCALER_CTL0_SCL1_MASK			VC4_MASK(10, 8)
 #define SCALER_CTL0_SCL1_SHIFT			8
 
@@ -896,10 +918,13 @@ enum hvs_pixel_format {
 
 /* Set to indicate no scaling. */
 #define SCALER_CTL0_UNITY			BIT(4)
+#define SCALER5_CTL0_UNITY			BIT(15)
 
 #define SCALER_CTL0_PIXEL_FORMAT_MASK		VC4_MASK(3, 0)
 #define SCALER_CTL0_PIXEL_FORMAT_SHIFT		0
 
+#define SCALER5_CTL0_PIXEL_FORMAT_MASK		VC4_MASK(4, 0)
+
 #define SCALER_POS0_FIXED_ALPHA_MASK		VC4_MASK(31, 24)
 #define SCALER_POS0_FIXED_ALPHA_SHIFT		24
 
@@ -909,12 +934,48 @@ enum hvs_pixel_format {
 #define SCALER_POS0_START_X_MASK		VC4_MASK(11, 0)
 #define SCALER_POS0_START_X_SHIFT		0
 
+#define SCALER5_POS0_START_Y_MASK		VC4_MASK(27, 16)
+#define SCALER5_POS0_START_Y_SHIFT		16
+
+#define SCALER5_POS0_START_X_MASK		VC4_MASK(13, 0)
+#define SCALER5_POS0_START_X_SHIFT		0
+
+#define SCALER5_POS0_VFLIP			BIT(31)
+#define SCALER5_POS0_HFLIP			BIT(15)
+
+#define SCALER5_CTL2_ALPHA_MODE_MASK		VC4_MASK(31, 30)
+#define SCALER5_CTL2_ALPHA_MODE_SHIFT		30
+#define SCALER5_CTL2_ALPHA_MODE_PIPELINE		0
+#define SCALER5_CTL2_ALPHA_MODE_FIXED		1
+#define SCALER5_CTL2_ALPHA_MODE_FIXED_NONZERO	2
+#define SCALER5_CTL2_ALPHA_MODE_FIXED_OVER_0x07	3
+
+#define SCALER5_CTL2_ALPHA_PREMULT		BIT(29)
+
+#define SCALER5_CTL2_ALPHA_MIX			BIT(28)
+
+#define SCALER5_CTL2_ALPHA_LOC			BIT(25)
+
+#define SCALER5_CTL2_MAP_SEL_MASK		VC4_MASK(18, 17)
+#define SCALER5_CTL2_MAP_SEL_SHIFT		17
+
+#define SCALER5_CTL2_GAMMA			BIT(16)
+
+#define SCALER5_CTL2_ALPHA_MASK			VC4_MASK(15, 4)
+#define SCALER5_CTL2_ALPHA_SHIFT		4
+
 #define SCALER_POS1_SCL_HEIGHT_MASK		VC4_MASK(27, 16)
 #define SCALER_POS1_SCL_HEIGHT_SHIFT		16
 
 #define SCALER_POS1_SCL_WIDTH_MASK		VC4_MASK(11, 0)
 #define SCALER_POS1_SCL_WIDTH_SHIFT		0
 
+#define SCALER5_POS1_SCL_HEIGHT_MASK		VC4_MASK(28, 16)
+#define SCALER5_POS1_SCL_HEIGHT_SHIFT		16
+
+#define SCALER5_POS1_SCL_WIDTH_MASK		VC4_MASK(12, 0)
+#define SCALER5_POS1_SCL_WIDTH_SHIFT		0
+
 #define SCALER_POS2_ALPHA_MODE_MASK		VC4_MASK(31, 30)
 #define SCALER_POS2_ALPHA_MODE_SHIFT		30
 #define SCALER_POS2_ALPHA_MODE_PIPELINE		0
@@ -930,6 +991,12 @@ enum hvs_pixel_format {
 #define SCALER_POS2_WIDTH_MASK			VC4_MASK(11, 0)
 #define SCALER_POS2_WIDTH_SHIFT			0
 
+#define SCALER5_POS2_HEIGHT_MASK		VC4_MASK(28, 16)
+#define SCALER5_POS2_HEIGHT_SHIFT		16
+
+#define SCALER5_POS2_WIDTH_MASK			VC4_MASK(12, 0)
+#define SCALER5_POS2_WIDTH_SHIFT		0
+
 /* Color Space Conversion words.  Some values are S2.8 signed
  * integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1,
  * 0x2: 2, 0x3: -1}
-- 
git-series 0.9.1

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

* [PATCH v4 02/78] drm/vc4: Add support for the BCM2711 HVS5
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The HVS found in the BCM2711 is slightly different from the previous
generations.

Most notably, the display list layout changes a bit, the LBM doesn't have
the same size and the formats ordering for some formats is swapped.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h   |   4 +-
 drivers/gpu/drm/vc4/vc4_hvs.c   |  34 ++++--
 drivers/gpu/drm/vc4/vc4_plane.c | 194 ++++++++++++++++++++++++---------
 drivers/gpu/drm/vc4/vc4_regs.h  |  67 +++++++++++-
 4 files changed, 240 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index fa19160c801f..e4cde1f9224b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -329,7 +329,11 @@ struct vc4_hvs {
 	spinlock_t mm_lock;
 
 	struct drm_mm_node mitchell_netravali_filter;
+
 	struct debugfs_regset32 regset;
+
+	/* HVS version 5 flag, therefore requires updated dlist structures */
+	bool hvs5;
 };
 
 struct vc4_plane {
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 2d2bf59c0503..836d8799d79e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -277,11 +277,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 	 * mode.
 	 */
 	dispctrl = SCALER_DISPCTRLX_ENABLE;
-	dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-				  SCALER_DISPCTRLX_WIDTH) |
-		    VC4_SET_FIELD(mode->vdisplay,
-				  SCALER_DISPCTRLX_HEIGHT) |
-		    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+
+	if (!vc4->hvs->hvs5)
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+	else
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER5_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER5_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
 	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
 }
@@ -521,6 +529,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 
 	hvs->pdev = pdev;
 
+	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs"))
+		hvs->hvs5 = true;
+
 	hvs->regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hvs->regs))
 		return PTR_ERR(hvs->regs);
@@ -529,7 +540,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	hvs->regset.regs = hvs_regs;
 	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 
-	hvs->dlist = hvs->regs + SCALER_DLIST_START;
+	if (!hvs->hvs5)
+		hvs->dlist = hvs->regs + SCALER_DLIST_START;
+	else
+		hvs->dlist = hvs->regs + SCALER5_DLIST_START;
 
 	spin_lock_init(&hvs->mm_lock);
 
@@ -547,7 +561,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	 * between planes when they don't overlap on the screen, but
 	 * for now we just allocate globally.
 	 */
-	drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
+	if (!hvs->hvs5)
+		/* 96kB */
+		drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
+	else
+		/* 70k words */
+		drm_mm_init(&hvs->lbm_mm, 0, 70 * 2 * 1024);
 
 	/* Upload filter kernels.  We only have the one for now, so we
 	 * keep it around for the lifetime of the driver.
@@ -632,6 +651,7 @@ static int vc4_hvs_dev_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id vc4_hvs_dt_match[] = {
+	{ .compatible = "brcm,bcm2711-hvs" },
 	{ .compatible = "brcm,bcm2835-hvs" },
 	{}
 };
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index d040d9f12c6d..20c949b57827 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -32,45 +32,60 @@ static const struct hvs_format {
 	u32 drm; /* DRM_FORMAT_* */
 	u32 hvs; /* HVS_FORMAT_* */
 	u32 pixel_order;
+	u32 pixel_order_hvs5;
 } hvs_formats[] = {
 	{
-		.drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_XRGB8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
 	},
 	{
-		.drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_ARGB8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
 	},
 	{
-		.drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_ABGR8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ARGB,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_XBGR8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ARGB,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565,
+		.drm = DRM_FORMAT_RGB565,
+		.hvs = HVS_PIXEL_FORMAT_RGB565,
 		.pixel_order = HVS_PIXEL_ORDER_XRGB,
 	},
 	{
-		.drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565,
+		.drm = DRM_FORMAT_BGR565,
+		.hvs = HVS_PIXEL_FORMAT_RGB565,
 		.pixel_order = HVS_PIXEL_ORDER_XBGR,
 	},
 	{
-		.drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
+		.drm = DRM_FORMAT_ARGB1555,
+		.hvs = HVS_PIXEL_FORMAT_RGBA5551,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
+		.drm = DRM_FORMAT_XRGB1555,
+		.hvs = HVS_PIXEL_FORMAT_RGBA5551,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+		.drm = DRM_FORMAT_RGB888,
+		.hvs = HVS_PIXEL_FORMAT_RGB888,
 		.pixel_order = HVS_PIXEL_ORDER_XRGB,
 	},
 	{
-		.drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+		.drm = DRM_FORMAT_BGR888,
+		.hvs = HVS_PIXEL_FORMAT_RGB888,
 		.pixel_order = HVS_PIXEL_ORDER_XBGR,
 	},
 	{
@@ -776,35 +791,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 		return -EINVAL;
 	}
 
-	/* Control word */
-	vc4_dlist_write(vc4_state,
-			SCALER_CTL0_VALID |
-			(rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
-			(rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
-			VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
-			(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
-			(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
-			VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
-			(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
-			VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
-			VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
-
-	/* Position Word 0: Image Positions and Alpha Value */
-	vc4_state->pos0_offset = vc4_state->dlist_count;
-	vc4_dlist_write(vc4_state,
-			VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) |
-			VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
-			VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
-
-	/* Position Word 1: Scaled Image Dimensions. */
-	if (!vc4_state->is_unity) {
-		vc4_dlist_write(vc4_state,
-				VC4_SET_FIELD(vc4_state->crtc_w,
-					      SCALER_POS1_SCL_WIDTH) |
-				VC4_SET_FIELD(vc4_state->crtc_h,
-					      SCALER_POS1_SCL_HEIGHT));
-	}
-
 	/* Don't waste cycles mixing with plane alpha if the set alpha
 	 * is opaque or there is no per-pixel alpha information.
 	 * In any case we use the alpha property value as the fixed alpha.
@@ -812,20 +798,120 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 	mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE &&
 			  fb->format->has_alpha;
 
-	/* Position Word 2: Source Image Size, Alpha */
-	vc4_state->pos2_offset = vc4_state->dlist_count;
-	vc4_dlist_write(vc4_state,
-			VC4_SET_FIELD(fb->format->has_alpha ?
-				      SCALER_POS2_ALPHA_MODE_PIPELINE :
-				      SCALER_POS2_ALPHA_MODE_FIXED,
-				      SCALER_POS2_ALPHA_MODE) |
-			(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
-			(fb->format->has_alpha ? SCALER_POS2_ALPHA_PREMULT : 0) |
-			VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) |
-			VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT));
+	if (!vc4->hvs->hvs5) {
+	/* Control word */
+		vc4_dlist_write(vc4_state,
+				SCALER_CTL0_VALID |
+				(rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
+				(rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
+				VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
+				(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+				(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+				VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+				(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
+				VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+				VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
+
+		/* Position Word 0: Image Positions and Alpha Value */
+		vc4_state->pos0_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) |
+				VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
+				VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
+
+		/* Position Word 1: Scaled Image Dimensions. */
+		if (!vc4_state->is_unity) {
+			vc4_dlist_write(vc4_state,
+					VC4_SET_FIELD(vc4_state->crtc_w,
+						      SCALER_POS1_SCL_WIDTH) |
+					VC4_SET_FIELD(vc4_state->crtc_h,
+						      SCALER_POS1_SCL_HEIGHT));
+		}
+
+		/* Position Word 2: Source Image Size, Alpha */
+		vc4_state->pos2_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(fb->format->has_alpha ?
+					      SCALER_POS2_ALPHA_MODE_PIPELINE :
+					      SCALER_POS2_ALPHA_MODE_FIXED,
+					      SCALER_POS2_ALPHA_MODE) |
+				(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
+				(fb->format->has_alpha ?
+						SCALER_POS2_ALPHA_PREMULT : 0) |
+				VC4_SET_FIELD(vc4_state->src_w[0],
+					      SCALER_POS2_WIDTH) |
+				VC4_SET_FIELD(vc4_state->src_h[0],
+					      SCALER_POS2_HEIGHT));
+
+		/* Position Word 3: Context.  Written by the HVS. */
+		vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+	} else {
+		u32 hvs_pixel_order = format->pixel_order;
 
-	/* Position Word 3: Context.  Written by the HVS. */
-	vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+		if (format->pixel_order_hvs5)
+			hvs_pixel_order = format->pixel_order_hvs5;
+
+		/* Control word */
+		vc4_dlist_write(vc4_state,
+				SCALER_CTL0_VALID |
+				(hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+				(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+				VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+				(vc4_state->is_unity ?
+						SCALER5_CTL0_UNITY : 0) |
+				VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+				VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) |
+				SCALER5_CTL0_ALPHA_EXPAND |
+				SCALER5_CTL0_RGB_EXPAND);
+
+		/* Position Word 0: Image Positions and Alpha Value */
+		vc4_state->pos0_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				(rotation & DRM_MODE_REFLECT_Y ?
+						SCALER5_POS0_VFLIP : 0) |
+				VC4_SET_FIELD(vc4_state->crtc_x,
+					      SCALER_POS0_START_X) |
+				(rotation & DRM_MODE_REFLECT_X ?
+					      SCALER5_POS0_HFLIP : 0) |
+				VC4_SET_FIELD(vc4_state->crtc_y,
+					      SCALER5_POS0_START_Y)
+			       );
+
+		/* Control Word 2 */
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(state->alpha >> 4,
+					      SCALER5_CTL2_ALPHA) |
+				fb->format->has_alpha ?
+					SCALER5_CTL2_ALPHA_PREMULT : 0 |
+				(mix_plane_alpha ?
+					SCALER5_CTL2_ALPHA_MIX : 0) |
+				VC4_SET_FIELD(fb->format->has_alpha ?
+				      SCALER5_CTL2_ALPHA_MODE_PIPELINE :
+				      SCALER5_CTL2_ALPHA_MODE_FIXED,
+				      SCALER5_CTL2_ALPHA_MODE)
+			       );
+
+		/* Position Word 1: Scaled Image Dimensions. */
+		if (!vc4_state->is_unity) {
+			vc4_dlist_write(vc4_state,
+					VC4_SET_FIELD(vc4_state->crtc_w,
+						      SCALER_POS1_SCL_WIDTH) |
+					VC4_SET_FIELD(vc4_state->crtc_h,
+						      SCALER_POS1_SCL_HEIGHT));
+		}
+
+		/* Position Word 2: Source Image Size */
+		vc4_state->pos2_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(vc4_state->src_w[0],
+					      SCALER5_POS2_WIDTH) |
+				VC4_SET_FIELD(vc4_state->src_h[0],
+					      SCALER5_POS2_HEIGHT));
+
+		/* Position Word 3: Context.  Written by the HVS. */
+		vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+	}
 
 
 	/* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers
@@ -1203,6 +1289,10 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
 		default:
 			return false;
 		}
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
 	case DRM_FORMAT_YUV422:
 	case DRM_FORMAT_YVU422:
 	case DRM_FORMAT_YUV420:
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 324462cc9cd4..91b785725555 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -327,6 +327,20 @@
 # define SCALER_DISPCTRLX_HEIGHT_MASK		VC4_MASK(11, 0)
 # define SCALER_DISPCTRLX_HEIGHT_SHIFT		0
 
+# define SCALER5_DISPCTRLX_WIDTH_MASK		VC4_MASK(28, 16)
+# define SCALER5_DISPCTRLX_WIDTH_SHIFT		16
+/* Generates a single frame when VSTART is seen and stops at the last
+ * pixel read from the FIFO.
+ */
+# define SCALER5_DISPCTRLX_ONESHOT		BIT(15)
+/* Processes a single context in the dlist and then task switch,
+ * instead of an entire line.
+ */
+# define SCALER5_DISPCTRLX_ONECTX_MASK		VC4_MASK(14, 13)
+# define SCALER5_DISPCTRLX_ONECTX_SHIFT		13
+# define SCALER5_DISPCTRLX_HEIGHT_MASK		VC4_MASK(12, 0)
+# define SCALER5_DISPCTRLX_HEIGHT_SHIFT		0
+
 #define SCALER_DISPBKGND0                       0x00000044
 # define SCALER_DISPBKGND_AUTOHS		BIT(31)
 # define SCALER_DISPBKGND_INTERLACE		BIT(30)
@@ -460,6 +474,8 @@
 #define SCALER_DLIST_START                      0x00002000
 #define SCALER_DLIST_SIZE                       0x00004000
 
+#define SCALER5_DLIST_START			0x00004000
+
 #define VC4_HDMI_CORE_REV			0x000
 
 #define VC4_HDMI_SW_RESET_CONTROL		0x004
@@ -825,6 +841,8 @@ enum hvs_pixel_format {
 	HVS_PIXEL_FORMAT_PALETTE = 13,
 	HVS_PIXEL_FORMAT_YUV444_RGB = 14,
 	HVS_PIXEL_FORMAT_AYUV444_RGB = 15,
+	HVS_PIXEL_FORMAT_RGBA1010102 = 16,
+	HVS_PIXEL_FORMAT_YCBCR_10BIT = 17,
 };
 
 /* Note: the LSB is the rightmost character shown.  Only valid for
@@ -879,6 +897,10 @@ enum hvs_pixel_format {
 #define SCALER_CTL0_RGBA_EXPAND_MSB		2
 #define SCALER_CTL0_RGBA_EXPAND_ROUND		3
 
+#define SCALER5_CTL0_ALPHA_EXPAND		BIT(12)
+
+#define SCALER5_CTL0_RGB_EXPAND			BIT(11)
+
 #define SCALER_CTL0_SCL1_MASK			VC4_MASK(10, 8)
 #define SCALER_CTL0_SCL1_SHIFT			8
 
@@ -896,10 +918,13 @@ enum hvs_pixel_format {
 
 /* Set to indicate no scaling. */
 #define SCALER_CTL0_UNITY			BIT(4)
+#define SCALER5_CTL0_UNITY			BIT(15)
 
 #define SCALER_CTL0_PIXEL_FORMAT_MASK		VC4_MASK(3, 0)
 #define SCALER_CTL0_PIXEL_FORMAT_SHIFT		0
 
+#define SCALER5_CTL0_PIXEL_FORMAT_MASK		VC4_MASK(4, 0)
+
 #define SCALER_POS0_FIXED_ALPHA_MASK		VC4_MASK(31, 24)
 #define SCALER_POS0_FIXED_ALPHA_SHIFT		24
 
@@ -909,12 +934,48 @@ enum hvs_pixel_format {
 #define SCALER_POS0_START_X_MASK		VC4_MASK(11, 0)
 #define SCALER_POS0_START_X_SHIFT		0
 
+#define SCALER5_POS0_START_Y_MASK		VC4_MASK(27, 16)
+#define SCALER5_POS0_START_Y_SHIFT		16
+
+#define SCALER5_POS0_START_X_MASK		VC4_MASK(13, 0)
+#define SCALER5_POS0_START_X_SHIFT		0
+
+#define SCALER5_POS0_VFLIP			BIT(31)
+#define SCALER5_POS0_HFLIP			BIT(15)
+
+#define SCALER5_CTL2_ALPHA_MODE_MASK		VC4_MASK(31, 30)
+#define SCALER5_CTL2_ALPHA_MODE_SHIFT		30
+#define SCALER5_CTL2_ALPHA_MODE_PIPELINE		0
+#define SCALER5_CTL2_ALPHA_MODE_FIXED		1
+#define SCALER5_CTL2_ALPHA_MODE_FIXED_NONZERO	2
+#define SCALER5_CTL2_ALPHA_MODE_FIXED_OVER_0x07	3
+
+#define SCALER5_CTL2_ALPHA_PREMULT		BIT(29)
+
+#define SCALER5_CTL2_ALPHA_MIX			BIT(28)
+
+#define SCALER5_CTL2_ALPHA_LOC			BIT(25)
+
+#define SCALER5_CTL2_MAP_SEL_MASK		VC4_MASK(18, 17)
+#define SCALER5_CTL2_MAP_SEL_SHIFT		17
+
+#define SCALER5_CTL2_GAMMA			BIT(16)
+
+#define SCALER5_CTL2_ALPHA_MASK			VC4_MASK(15, 4)
+#define SCALER5_CTL2_ALPHA_SHIFT		4
+
 #define SCALER_POS1_SCL_HEIGHT_MASK		VC4_MASK(27, 16)
 #define SCALER_POS1_SCL_HEIGHT_SHIFT		16
 
 #define SCALER_POS1_SCL_WIDTH_MASK		VC4_MASK(11, 0)
 #define SCALER_POS1_SCL_WIDTH_SHIFT		0
 
+#define SCALER5_POS1_SCL_HEIGHT_MASK		VC4_MASK(28, 16)
+#define SCALER5_POS1_SCL_HEIGHT_SHIFT		16
+
+#define SCALER5_POS1_SCL_WIDTH_MASK		VC4_MASK(12, 0)
+#define SCALER5_POS1_SCL_WIDTH_SHIFT		0
+
 #define SCALER_POS2_ALPHA_MODE_MASK		VC4_MASK(31, 30)
 #define SCALER_POS2_ALPHA_MODE_SHIFT		30
 #define SCALER_POS2_ALPHA_MODE_PIPELINE		0
@@ -930,6 +991,12 @@ enum hvs_pixel_format {
 #define SCALER_POS2_WIDTH_MASK			VC4_MASK(11, 0)
 #define SCALER_POS2_WIDTH_SHIFT			0
 
+#define SCALER5_POS2_HEIGHT_MASK		VC4_MASK(28, 16)
+#define SCALER5_POS2_HEIGHT_SHIFT		16
+
+#define SCALER5_POS2_WIDTH_MASK			VC4_MASK(12, 0)
+#define SCALER5_POS2_WIDTH_SHIFT		0
+
 /* Color Space Conversion words.  Some values are S2.8 signed
  * integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1,
  * 0x2: 2, 0x3: -1}
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 02/78] drm/vc4: Add support for the BCM2711 HVS5
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The HVS found in the BCM2711 is slightly different from the previous
generations.

Most notably, the display list layout changes a bit, the LBM doesn't have
the same size and the formats ordering for some formats is swapped.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h   |   4 +-
 drivers/gpu/drm/vc4/vc4_hvs.c   |  34 ++++--
 drivers/gpu/drm/vc4/vc4_plane.c | 194 ++++++++++++++++++++++++---------
 drivers/gpu/drm/vc4/vc4_regs.h  |  67 +++++++++++-
 4 files changed, 240 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index fa19160c801f..e4cde1f9224b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -329,7 +329,11 @@ struct vc4_hvs {
 	spinlock_t mm_lock;
 
 	struct drm_mm_node mitchell_netravali_filter;
+
 	struct debugfs_regset32 regset;
+
+	/* HVS version 5 flag, therefore requires updated dlist structures */
+	bool hvs5;
 };
 
 struct vc4_plane {
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 2d2bf59c0503..836d8799d79e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -277,11 +277,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 	 * mode.
 	 */
 	dispctrl = SCALER_DISPCTRLX_ENABLE;
-	dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-				  SCALER_DISPCTRLX_WIDTH) |
-		    VC4_SET_FIELD(mode->vdisplay,
-				  SCALER_DISPCTRLX_HEIGHT) |
-		    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+
+	if (!vc4->hvs->hvs5)
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+	else
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER5_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER5_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
 	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
 }
@@ -521,6 +529,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 
 	hvs->pdev = pdev;
 
+	if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs"))
+		hvs->hvs5 = true;
+
 	hvs->regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hvs->regs))
 		return PTR_ERR(hvs->regs);
@@ -529,7 +540,10 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	hvs->regset.regs = hvs_regs;
 	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 
-	hvs->dlist = hvs->regs + SCALER_DLIST_START;
+	if (!hvs->hvs5)
+		hvs->dlist = hvs->regs + SCALER_DLIST_START;
+	else
+		hvs->dlist = hvs->regs + SCALER5_DLIST_START;
 
 	spin_lock_init(&hvs->mm_lock);
 
@@ -547,7 +561,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	 * between planes when they don't overlap on the screen, but
 	 * for now we just allocate globally.
 	 */
-	drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
+	if (!hvs->hvs5)
+		/* 96kB */
+		drm_mm_init(&hvs->lbm_mm, 0, 96 * 1024);
+	else
+		/* 70k words */
+		drm_mm_init(&hvs->lbm_mm, 0, 70 * 2 * 1024);
 
 	/* Upload filter kernels.  We only have the one for now, so we
 	 * keep it around for the lifetime of the driver.
@@ -632,6 +651,7 @@ static int vc4_hvs_dev_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id vc4_hvs_dt_match[] = {
+	{ .compatible = "brcm,bcm2711-hvs" },
 	{ .compatible = "brcm,bcm2835-hvs" },
 	{}
 };
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index d040d9f12c6d..20c949b57827 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -32,45 +32,60 @@ static const struct hvs_format {
 	u32 drm; /* DRM_FORMAT_* */
 	u32 hvs; /* HVS_FORMAT_* */
 	u32 pixel_order;
+	u32 pixel_order_hvs5;
 } hvs_formats[] = {
 	{
-		.drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_XRGB8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
 	},
 	{
-		.drm = DRM_FORMAT_ARGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_ARGB8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ARGB,
 	},
 	{
-		.drm = DRM_FORMAT_ABGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_ABGR8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ARGB,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_XBGR8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
+		.drm = DRM_FORMAT_XBGR8888,
+		.hvs = HVS_PIXEL_FORMAT_RGBA8888,
 		.pixel_order = HVS_PIXEL_ORDER_ARGB,
+		.pixel_order_hvs5 = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_RGB565, .hvs = HVS_PIXEL_FORMAT_RGB565,
+		.drm = DRM_FORMAT_RGB565,
+		.hvs = HVS_PIXEL_FORMAT_RGB565,
 		.pixel_order = HVS_PIXEL_ORDER_XRGB,
 	},
 	{
-		.drm = DRM_FORMAT_BGR565, .hvs = HVS_PIXEL_FORMAT_RGB565,
+		.drm = DRM_FORMAT_BGR565,
+		.hvs = HVS_PIXEL_FORMAT_RGB565,
 		.pixel_order = HVS_PIXEL_ORDER_XBGR,
 	},
 	{
-		.drm = DRM_FORMAT_ARGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
+		.drm = DRM_FORMAT_ARGB1555,
+		.hvs = HVS_PIXEL_FORMAT_RGBA5551,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
+		.drm = DRM_FORMAT_XRGB1555,
+		.hvs = HVS_PIXEL_FORMAT_RGBA5551,
 		.pixel_order = HVS_PIXEL_ORDER_ABGR,
 	},
 	{
-		.drm = DRM_FORMAT_RGB888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+		.drm = DRM_FORMAT_RGB888,
+		.hvs = HVS_PIXEL_FORMAT_RGB888,
 		.pixel_order = HVS_PIXEL_ORDER_XRGB,
 	},
 	{
-		.drm = DRM_FORMAT_BGR888, .hvs = HVS_PIXEL_FORMAT_RGB888,
+		.drm = DRM_FORMAT_BGR888,
+		.hvs = HVS_PIXEL_FORMAT_RGB888,
 		.pixel_order = HVS_PIXEL_ORDER_XBGR,
 	},
 	{
@@ -776,35 +791,6 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 		return -EINVAL;
 	}
 
-	/* Control word */
-	vc4_dlist_write(vc4_state,
-			SCALER_CTL0_VALID |
-			(rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
-			(rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
-			VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
-			(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
-			(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
-			VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
-			(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
-			VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
-			VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
-
-	/* Position Word 0: Image Positions and Alpha Value */
-	vc4_state->pos0_offset = vc4_state->dlist_count;
-	vc4_dlist_write(vc4_state,
-			VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) |
-			VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
-			VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
-
-	/* Position Word 1: Scaled Image Dimensions. */
-	if (!vc4_state->is_unity) {
-		vc4_dlist_write(vc4_state,
-				VC4_SET_FIELD(vc4_state->crtc_w,
-					      SCALER_POS1_SCL_WIDTH) |
-				VC4_SET_FIELD(vc4_state->crtc_h,
-					      SCALER_POS1_SCL_HEIGHT));
-	}
-
 	/* Don't waste cycles mixing with plane alpha if the set alpha
 	 * is opaque or there is no per-pixel alpha information.
 	 * In any case we use the alpha property value as the fixed alpha.
@@ -812,20 +798,120 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
 	mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE &&
 			  fb->format->has_alpha;
 
-	/* Position Word 2: Source Image Size, Alpha */
-	vc4_state->pos2_offset = vc4_state->dlist_count;
-	vc4_dlist_write(vc4_state,
-			VC4_SET_FIELD(fb->format->has_alpha ?
-				      SCALER_POS2_ALPHA_MODE_PIPELINE :
-				      SCALER_POS2_ALPHA_MODE_FIXED,
-				      SCALER_POS2_ALPHA_MODE) |
-			(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
-			(fb->format->has_alpha ? SCALER_POS2_ALPHA_PREMULT : 0) |
-			VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) |
-			VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT));
+	if (!vc4->hvs->hvs5) {
+	/* Control word */
+		vc4_dlist_write(vc4_state,
+				SCALER_CTL0_VALID |
+				(rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
+				(rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
+				VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
+				(format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+				(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+				VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+				(vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
+				VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+				VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
+
+		/* Position Word 0: Image Positions and Alpha Value */
+		vc4_state->pos0_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(state->alpha >> 8, SCALER_POS0_FIXED_ALPHA) |
+				VC4_SET_FIELD(vc4_state->crtc_x, SCALER_POS0_START_X) |
+				VC4_SET_FIELD(vc4_state->crtc_y, SCALER_POS0_START_Y));
+
+		/* Position Word 1: Scaled Image Dimensions. */
+		if (!vc4_state->is_unity) {
+			vc4_dlist_write(vc4_state,
+					VC4_SET_FIELD(vc4_state->crtc_w,
+						      SCALER_POS1_SCL_WIDTH) |
+					VC4_SET_FIELD(vc4_state->crtc_h,
+						      SCALER_POS1_SCL_HEIGHT));
+		}
+
+		/* Position Word 2: Source Image Size, Alpha */
+		vc4_state->pos2_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(fb->format->has_alpha ?
+					      SCALER_POS2_ALPHA_MODE_PIPELINE :
+					      SCALER_POS2_ALPHA_MODE_FIXED,
+					      SCALER_POS2_ALPHA_MODE) |
+				(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
+				(fb->format->has_alpha ?
+						SCALER_POS2_ALPHA_PREMULT : 0) |
+				VC4_SET_FIELD(vc4_state->src_w[0],
+					      SCALER_POS2_WIDTH) |
+				VC4_SET_FIELD(vc4_state->src_h[0],
+					      SCALER_POS2_HEIGHT));
+
+		/* Position Word 3: Context.  Written by the HVS. */
+		vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+
+	} else {
+		u32 hvs_pixel_order = format->pixel_order;
 
-	/* Position Word 3: Context.  Written by the HVS. */
-	vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+		if (format->pixel_order_hvs5)
+			hvs_pixel_order = format->pixel_order_hvs5;
+
+		/* Control word */
+		vc4_dlist_write(vc4_state,
+				SCALER_CTL0_VALID |
+				(hvs_pixel_order << SCALER_CTL0_ORDER_SHIFT) |
+				(hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
+				VC4_SET_FIELD(tiling, SCALER_CTL0_TILING) |
+				(vc4_state->is_unity ?
+						SCALER5_CTL0_UNITY : 0) |
+				VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
+				VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1) |
+				SCALER5_CTL0_ALPHA_EXPAND |
+				SCALER5_CTL0_RGB_EXPAND);
+
+		/* Position Word 0: Image Positions and Alpha Value */
+		vc4_state->pos0_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				(rotation & DRM_MODE_REFLECT_Y ?
+						SCALER5_POS0_VFLIP : 0) |
+				VC4_SET_FIELD(vc4_state->crtc_x,
+					      SCALER_POS0_START_X) |
+				(rotation & DRM_MODE_REFLECT_X ?
+					      SCALER5_POS0_HFLIP : 0) |
+				VC4_SET_FIELD(vc4_state->crtc_y,
+					      SCALER5_POS0_START_Y)
+			       );
+
+		/* Control Word 2 */
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(state->alpha >> 4,
+					      SCALER5_CTL2_ALPHA) |
+				fb->format->has_alpha ?
+					SCALER5_CTL2_ALPHA_PREMULT : 0 |
+				(mix_plane_alpha ?
+					SCALER5_CTL2_ALPHA_MIX : 0) |
+				VC4_SET_FIELD(fb->format->has_alpha ?
+				      SCALER5_CTL2_ALPHA_MODE_PIPELINE :
+				      SCALER5_CTL2_ALPHA_MODE_FIXED,
+				      SCALER5_CTL2_ALPHA_MODE)
+			       );
+
+		/* Position Word 1: Scaled Image Dimensions. */
+		if (!vc4_state->is_unity) {
+			vc4_dlist_write(vc4_state,
+					VC4_SET_FIELD(vc4_state->crtc_w,
+						      SCALER_POS1_SCL_WIDTH) |
+					VC4_SET_FIELD(vc4_state->crtc_h,
+						      SCALER_POS1_SCL_HEIGHT));
+		}
+
+		/* Position Word 2: Source Image Size */
+		vc4_state->pos2_offset = vc4_state->dlist_count;
+		vc4_dlist_write(vc4_state,
+				VC4_SET_FIELD(vc4_state->src_w[0],
+					      SCALER5_POS2_WIDTH) |
+				VC4_SET_FIELD(vc4_state->src_h[0],
+					      SCALER5_POS2_HEIGHT));
+
+		/* Position Word 3: Context.  Written by the HVS. */
+		vc4_dlist_write(vc4_state, 0xc0c0c0c0);
+	}
 
 
 	/* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers
@@ -1203,6 +1289,10 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
 		default:
 			return false;
 		}
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
 	case DRM_FORMAT_YUV422:
 	case DRM_FORMAT_YVU422:
 	case DRM_FORMAT_YUV420:
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 324462cc9cd4..91b785725555 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -327,6 +327,20 @@
 # define SCALER_DISPCTRLX_HEIGHT_MASK		VC4_MASK(11, 0)
 # define SCALER_DISPCTRLX_HEIGHT_SHIFT		0
 
+# define SCALER5_DISPCTRLX_WIDTH_MASK		VC4_MASK(28, 16)
+# define SCALER5_DISPCTRLX_WIDTH_SHIFT		16
+/* Generates a single frame when VSTART is seen and stops at the last
+ * pixel read from the FIFO.
+ */
+# define SCALER5_DISPCTRLX_ONESHOT		BIT(15)
+/* Processes a single context in the dlist and then task switch,
+ * instead of an entire line.
+ */
+# define SCALER5_DISPCTRLX_ONECTX_MASK		VC4_MASK(14, 13)
+# define SCALER5_DISPCTRLX_ONECTX_SHIFT		13
+# define SCALER5_DISPCTRLX_HEIGHT_MASK		VC4_MASK(12, 0)
+# define SCALER5_DISPCTRLX_HEIGHT_SHIFT		0
+
 #define SCALER_DISPBKGND0                       0x00000044
 # define SCALER_DISPBKGND_AUTOHS		BIT(31)
 # define SCALER_DISPBKGND_INTERLACE		BIT(30)
@@ -460,6 +474,8 @@
 #define SCALER_DLIST_START                      0x00002000
 #define SCALER_DLIST_SIZE                       0x00004000
 
+#define SCALER5_DLIST_START			0x00004000
+
 #define VC4_HDMI_CORE_REV			0x000
 
 #define VC4_HDMI_SW_RESET_CONTROL		0x004
@@ -825,6 +841,8 @@ enum hvs_pixel_format {
 	HVS_PIXEL_FORMAT_PALETTE = 13,
 	HVS_PIXEL_FORMAT_YUV444_RGB = 14,
 	HVS_PIXEL_FORMAT_AYUV444_RGB = 15,
+	HVS_PIXEL_FORMAT_RGBA1010102 = 16,
+	HVS_PIXEL_FORMAT_YCBCR_10BIT = 17,
 };
 
 /* Note: the LSB is the rightmost character shown.  Only valid for
@@ -879,6 +897,10 @@ enum hvs_pixel_format {
 #define SCALER_CTL0_RGBA_EXPAND_MSB		2
 #define SCALER_CTL0_RGBA_EXPAND_ROUND		3
 
+#define SCALER5_CTL0_ALPHA_EXPAND		BIT(12)
+
+#define SCALER5_CTL0_RGB_EXPAND			BIT(11)
+
 #define SCALER_CTL0_SCL1_MASK			VC4_MASK(10, 8)
 #define SCALER_CTL0_SCL1_SHIFT			8
 
@@ -896,10 +918,13 @@ enum hvs_pixel_format {
 
 /* Set to indicate no scaling. */
 #define SCALER_CTL0_UNITY			BIT(4)
+#define SCALER5_CTL0_UNITY			BIT(15)
 
 #define SCALER_CTL0_PIXEL_FORMAT_MASK		VC4_MASK(3, 0)
 #define SCALER_CTL0_PIXEL_FORMAT_SHIFT		0
 
+#define SCALER5_CTL0_PIXEL_FORMAT_MASK		VC4_MASK(4, 0)
+
 #define SCALER_POS0_FIXED_ALPHA_MASK		VC4_MASK(31, 24)
 #define SCALER_POS0_FIXED_ALPHA_SHIFT		24
 
@@ -909,12 +934,48 @@ enum hvs_pixel_format {
 #define SCALER_POS0_START_X_MASK		VC4_MASK(11, 0)
 #define SCALER_POS0_START_X_SHIFT		0
 
+#define SCALER5_POS0_START_Y_MASK		VC4_MASK(27, 16)
+#define SCALER5_POS0_START_Y_SHIFT		16
+
+#define SCALER5_POS0_START_X_MASK		VC4_MASK(13, 0)
+#define SCALER5_POS0_START_X_SHIFT		0
+
+#define SCALER5_POS0_VFLIP			BIT(31)
+#define SCALER5_POS0_HFLIP			BIT(15)
+
+#define SCALER5_CTL2_ALPHA_MODE_MASK		VC4_MASK(31, 30)
+#define SCALER5_CTL2_ALPHA_MODE_SHIFT		30
+#define SCALER5_CTL2_ALPHA_MODE_PIPELINE		0
+#define SCALER5_CTL2_ALPHA_MODE_FIXED		1
+#define SCALER5_CTL2_ALPHA_MODE_FIXED_NONZERO	2
+#define SCALER5_CTL2_ALPHA_MODE_FIXED_OVER_0x07	3
+
+#define SCALER5_CTL2_ALPHA_PREMULT		BIT(29)
+
+#define SCALER5_CTL2_ALPHA_MIX			BIT(28)
+
+#define SCALER5_CTL2_ALPHA_LOC			BIT(25)
+
+#define SCALER5_CTL2_MAP_SEL_MASK		VC4_MASK(18, 17)
+#define SCALER5_CTL2_MAP_SEL_SHIFT		17
+
+#define SCALER5_CTL2_GAMMA			BIT(16)
+
+#define SCALER5_CTL2_ALPHA_MASK			VC4_MASK(15, 4)
+#define SCALER5_CTL2_ALPHA_SHIFT		4
+
 #define SCALER_POS1_SCL_HEIGHT_MASK		VC4_MASK(27, 16)
 #define SCALER_POS1_SCL_HEIGHT_SHIFT		16
 
 #define SCALER_POS1_SCL_WIDTH_MASK		VC4_MASK(11, 0)
 #define SCALER_POS1_SCL_WIDTH_SHIFT		0
 
+#define SCALER5_POS1_SCL_HEIGHT_MASK		VC4_MASK(28, 16)
+#define SCALER5_POS1_SCL_HEIGHT_SHIFT		16
+
+#define SCALER5_POS1_SCL_WIDTH_MASK		VC4_MASK(12, 0)
+#define SCALER5_POS1_SCL_WIDTH_SHIFT		0
+
 #define SCALER_POS2_ALPHA_MODE_MASK		VC4_MASK(31, 30)
 #define SCALER_POS2_ALPHA_MODE_SHIFT		30
 #define SCALER_POS2_ALPHA_MODE_PIPELINE		0
@@ -930,6 +991,12 @@ enum hvs_pixel_format {
 #define SCALER_POS2_WIDTH_MASK			VC4_MASK(11, 0)
 #define SCALER_POS2_WIDTH_SHIFT			0
 
+#define SCALER5_POS2_HEIGHT_MASK		VC4_MASK(28, 16)
+#define SCALER5_POS2_HEIGHT_SHIFT		16
+
+#define SCALER5_POS2_WIDTH_MASK			VC4_MASK(12, 0)
+#define SCALER5_POS2_WIDTH_SHIFT		0
+
 /* Color Space Conversion words.  Some values are S2.8 signed
  * integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1,
  * 0x2: 2, 0x3: -1}
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to prevent timeouts and stalls in the pipeline, the core clock
needs to be maxed at 500MHz during a modeset on the BCM2711.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
 drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
 drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
 3 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index e4cde1f9224b..6358f6ca8d56 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -320,6 +320,8 @@ struct vc4_hvs {
 	void __iomem *regs;
 	u32 __iomem *dlist;
 
+	struct clk *core_clk;
+
 	/* Memory manager for CRTCs to allocate space in the display
 	 * list.  Units are dwords.
 	 */
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 836d8799d79e..091fdf4908aa 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -19,6 +19,7 @@
  * each CRTC.
  */
 
+#include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/platform_device.h>
 
@@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	hvs->regset.regs = hvs_regs;
 	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 
+	if (hvs->hvs5) {
+		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(hvs->core_clk)) {
+			dev_err(&pdev->dev, "Couldn't get core clock\n");
+			return PTR_ERR(hvs->core_clk);
+		}
+	}
+
 	if (!hvs->hvs5)
 		hvs->dlist = hvs->regs + SCALER_DLIST_START;
 	else
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 08318e69061b..210cc2408087 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -11,6 +11,8 @@
  * crtc, HDMI encoder).
  */
 
+#include <linux/clk.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hvs *hvs = vc4->hvs;
 	struct vc4_crtc *vc4_crtc;
 	int i;
 
@@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
 	}
 
+	if (vc4->hvs->hvs5)
+		clk_set_min_rate(hvs->core_clk, 500000000);
+
 	drm_atomic_helper_wait_for_fences(dev, state, false);
 
 	drm_atomic_helper_wait_for_dependencies(state);
@@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	drm_atomic_helper_commit_cleanup_done(state);
 
+	if (vc4->hvs->hvs5)
+		clk_set_min_rate(hvs->core_clk, 0);
+
 	drm_atomic_state_put(state);
 
 	up(&vc4->async_modeset);
-- 
git-series 0.9.1

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

* [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to prevent timeouts and stalls in the pipeline, the core clock
needs to be maxed at 500MHz during a modeset on the BCM2711.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
 drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
 drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
 3 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index e4cde1f9224b..6358f6ca8d56 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -320,6 +320,8 @@ struct vc4_hvs {
 	void __iomem *regs;
 	u32 __iomem *dlist;
 
+	struct clk *core_clk;
+
 	/* Memory manager for CRTCs to allocate space in the display
 	 * list.  Units are dwords.
 	 */
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 836d8799d79e..091fdf4908aa 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -19,6 +19,7 @@
  * each CRTC.
  */
 
+#include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/platform_device.h>
 
@@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	hvs->regset.regs = hvs_regs;
 	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 
+	if (hvs->hvs5) {
+		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(hvs->core_clk)) {
+			dev_err(&pdev->dev, "Couldn't get core clock\n");
+			return PTR_ERR(hvs->core_clk);
+		}
+	}
+
 	if (!hvs->hvs5)
 		hvs->dlist = hvs->regs + SCALER_DLIST_START;
 	else
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 08318e69061b..210cc2408087 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -11,6 +11,8 @@
  * crtc, HDMI encoder).
  */
 
+#include <linux/clk.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hvs *hvs = vc4->hvs;
 	struct vc4_crtc *vc4_crtc;
 	int i;
 
@@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
 	}
 
+	if (vc4->hvs->hvs5)
+		clk_set_min_rate(hvs->core_clk, 500000000);
+
 	drm_atomic_helper_wait_for_fences(dev, state, false);
 
 	drm_atomic_helper_wait_for_dependencies(state);
@@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	drm_atomic_helper_commit_cleanup_done(state);
 
+	if (vc4->hvs->hvs5)
+		clk_set_min_rate(hvs->core_clk, 0);
+
 	drm_atomic_state_put(state);
 
 	up(&vc4->async_modeset);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to prevent timeouts and stalls in the pipeline, the core clock
needs to be maxed at 500MHz during a modeset on the BCM2711.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
 drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
 drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
 3 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index e4cde1f9224b..6358f6ca8d56 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -320,6 +320,8 @@ struct vc4_hvs {
 	void __iomem *regs;
 	u32 __iomem *dlist;
 
+	struct clk *core_clk;
+
 	/* Memory manager for CRTCs to allocate space in the display
 	 * list.  Units are dwords.
 	 */
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 836d8799d79e..091fdf4908aa 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -19,6 +19,7 @@
  * each CRTC.
  */
 
+#include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/platform_device.h>
 
@@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 	hvs->regset.regs = hvs_regs;
 	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
 
+	if (hvs->hvs5) {
+		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(hvs->core_clk)) {
+			dev_err(&pdev->dev, "Couldn't get core clock\n");
+			return PTR_ERR(hvs->core_clk);
+		}
+	}
+
 	if (!hvs->hvs5)
 		hvs->dlist = hvs->regs + SCALER_DLIST_START;
 	else
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 08318e69061b..210cc2408087 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -11,6 +11,8 @@
  * crtc, HDMI encoder).
  */
 
+#include <linux/clk.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hvs *hvs = vc4->hvs;
 	struct vc4_crtc *vc4_crtc;
 	int i;
 
@@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
 	}
 
+	if (vc4->hvs->hvs5)
+		clk_set_min_rate(hvs->core_clk, 500000000);
+
 	drm_atomic_helper_wait_for_fences(dev, state, false);
 
 	drm_atomic_helper_wait_for_dependencies(state);
@@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	drm_atomic_helper_commit_cleanup_done(state);
 
+	if (vc4->hvs->hvs5)
+		clk_set_min_rate(hvs->core_clk, 0);
+
 	drm_atomic_state_put(state);
 
 	up(&vc4->async_modeset);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 04/78] drm/vc4: plane: Change LBM alignment constraint on LBM
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The HVS5 needs an alignment of 64bytes for its LBM memory, so let's reflect
it.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 20c949b57827..d0771ebd5f75 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -578,7 +578,9 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
 		spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags);
 		ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm,
 						 &vc4_state->lbm,
-						 lbm_size, 32, 0, 0);
+						 lbm_size,
+						 vc4->hvs->hvs5 ? 64 : 32,
+						 0, 0);
 		spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags);
 
 		if (ret)
-- 
git-series 0.9.1

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

* [PATCH v4 04/78] drm/vc4: plane: Change LBM alignment constraint on LBM
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The HVS5 needs an alignment of 64bytes for its LBM memory, so let's reflect
it.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 20c949b57827..d0771ebd5f75 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -578,7 +578,9 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
 		spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags);
 		ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm,
 						 &vc4_state->lbm,
-						 lbm_size, 32, 0, 0);
+						 lbm_size,
+						 vc4->hvs->hvs5 ? 64 : 32,
+						 0, 0);
 		spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags);
 
 		if (ret)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 04/78] drm/vc4: plane: Change LBM alignment constraint on LBM
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The HVS5 needs an alignment of 64bytes for its LBM memory, so let's reflect
it.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 20c949b57827..d0771ebd5f75 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -578,7 +578,9 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
 		spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags);
 		ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm,
 						 &vc4_state->lbm,
-						 lbm_size, 32, 0, 0);
+						 lbm_size,
+						 vc4->hvs->hvs5 ? 64 : 32,
+						 0, 0);
 		spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags);
 
 		if (ret)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 05/78] drm/vc4: plane: Optimize the LBM allocation size
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The current code is using the maximum of the source line size and the
destination line size to compute the size of the LBM to allocate.

While this is simpler, it starts to be an issue with modes such as 4k with
a quite long that will consume all the available memory, so we no longer
have that luxury.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index d0771ebd5f75..23916814b4e3 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -437,10 +437,7 @@ static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst)
 static u32 vc4_lbm_size(struct drm_plane_state *state)
 {
 	struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
-	/* This is the worst case number.  One of the two sizes will
-	 * be used depending on the scaling configuration.
-	 */
-	u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w);
+	u32 pix_per_line;
 	u32 lbm;
 
 	/* LBM is not needed when there's no vertical scaling. */
@@ -448,6 +445,18 @@ static u32 vc4_lbm_size(struct drm_plane_state *state)
 	    vc4_state->y_scaling[1] == VC4_SCALING_NONE)
 		return 0;
 
+	/*
+	 * This can be further optimized in the RGB/YUV444 case if the PPF
+	 * decimation factor is between 0.5 and 1.0 by using crtc_w.
+	 *
+	 * It's not an issue though, since in that case since src_w[0] is going
+	 * to be greater than or equal to crtc_w.
+	 */
+	if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ)
+		pix_per_line = vc4_state->crtc_w;
+	else
+		pix_per_line = vc4_state->src_w[0];
+
 	if (!vc4_state->is_yuv) {
 		if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
 			lbm = pix_per_line * 8;
-- 
git-series 0.9.1

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

* [PATCH v4 05/78] drm/vc4: plane: Optimize the LBM allocation size
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The current code is using the maximum of the source line size and the
destination line size to compute the size of the LBM to allocate.

While this is simpler, it starts to be an issue with modes such as 4k with
a quite long that will consume all the available memory, so we no longer
have that luxury.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index d0771ebd5f75..23916814b4e3 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -437,10 +437,7 @@ static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst)
 static u32 vc4_lbm_size(struct drm_plane_state *state)
 {
 	struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
-	/* This is the worst case number.  One of the two sizes will
-	 * be used depending on the scaling configuration.
-	 */
-	u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w);
+	u32 pix_per_line;
 	u32 lbm;
 
 	/* LBM is not needed when there's no vertical scaling. */
@@ -448,6 +445,18 @@ static u32 vc4_lbm_size(struct drm_plane_state *state)
 	    vc4_state->y_scaling[1] == VC4_SCALING_NONE)
 		return 0;
 
+	/*
+	 * This can be further optimized in the RGB/YUV444 case if the PPF
+	 * decimation factor is between 0.5 and 1.0 by using crtc_w.
+	 *
+	 * It's not an issue though, since in that case since src_w[0] is going
+	 * to be greater than or equal to crtc_w.
+	 */
+	if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ)
+		pix_per_line = vc4_state->crtc_w;
+	else
+		pix_per_line = vc4_state->src_w[0];
+
 	if (!vc4_state->is_yuv) {
 		if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
 			lbm = pix_per_line * 8;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 05/78] drm/vc4: plane: Optimize the LBM allocation size
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The current code is using the maximum of the source line size and the
destination line size to compute the size of the LBM to allocate.

While this is simpler, it starts to be an issue with modes such as 4k with
a quite long that will consume all the available memory, so we no longer
have that luxury.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index d0771ebd5f75..23916814b4e3 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -437,10 +437,7 @@ static void vc4_write_ppf(struct vc4_plane_state *vc4_state, u32 src, u32 dst)
 static u32 vc4_lbm_size(struct drm_plane_state *state)
 {
 	struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
-	/* This is the worst case number.  One of the two sizes will
-	 * be used depending on the scaling configuration.
-	 */
-	u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w);
+	u32 pix_per_line;
 	u32 lbm;
 
 	/* LBM is not needed when there's no vertical scaling. */
@@ -448,6 +445,18 @@ static u32 vc4_lbm_size(struct drm_plane_state *state)
 	    vc4_state->y_scaling[1] == VC4_SCALING_NONE)
 		return 0;
 
+	/*
+	 * This can be further optimized in the RGB/YUV444 case if the PPF
+	 * decimation factor is between 0.5 and 1.0 by using crtc_w.
+	 *
+	 * It's not an issue though, since in that case since src_w[0] is going
+	 * to be greater than or equal to crtc_w.
+	 */
+	if (vc4_state->x_scaling[0] == VC4_SCALING_TPZ)
+		pix_per_line = vc4_state->crtc_w;
+	else
+		pix_per_line = vc4_state->src_w[0];
+
 	if (!vc4_state->is_yuv) {
 		if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
 			lbm = pix_per_line * 8;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 06/78] drm/vc4: plane: Create more planes
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Let's now create more planes that can be affected to all the CRTCs.

vc4 has 3 CRTCs, 1 primary and 1 cursor each, and was having 24 (8
planes per CRTC) overlays.

However, vc5 has 5 CRTCs, so keeping the same logic would put us at 50
planes which is well above the 32 planes limit imposed by DRM.

Using 16 seems like a good tradeoff between staying under 32 and yet
providing enough planes.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 23916814b4e3..1e38e603f83b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -1384,7 +1384,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
 	 * modest number of planes to expose, that should hopefully
 	 * still cover any sane usecase.
 	 */
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 16; i++) {
 		struct drm_plane *plane =
 			vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY);
 
-- 
git-series 0.9.1

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

* [PATCH v4 06/78] drm/vc4: plane: Create more planes
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Let's now create more planes that can be affected to all the CRTCs.

vc4 has 3 CRTCs, 1 primary and 1 cursor each, and was having 24 (8
planes per CRTC) overlays.

However, vc5 has 5 CRTCs, so keeping the same logic would put us at 50
planes which is well above the 32 planes limit imposed by DRM.

Using 16 seems like a good tradeoff between staying under 32 and yet
providing enough planes.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 23916814b4e3..1e38e603f83b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -1384,7 +1384,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
 	 * modest number of planes to expose, that should hopefully
 	 * still cover any sane usecase.
 	 */
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 16; i++) {
 		struct drm_plane *plane =
 			vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY);
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 06/78] drm/vc4: plane: Create more planes
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Let's now create more planes that can be affected to all the CRTCs.

vc4 has 3 CRTCs, 1 primary and 1 cursor each, and was having 24 (8
planes per CRTC) overlays.

However, vc5 has 5 CRTCs, so keeping the same logic would put us at 50
planes which is well above the 32 planes limit imposed by DRM.

Using 16 seems like a good tradeoff between staying under 32 and yet
providing enough planes.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_plane.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 23916814b4e3..1e38e603f83b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -1384,7 +1384,7 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
 	 * modest number of planes to expose, that should hopefully
 	 * still cover any sane usecase.
 	 */
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 16; i++) {
 		struct drm_plane *plane =
 			vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY);
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 07/78] drm/vc4: crtc: Deal with different number of pixel per clock
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Some of the HDMI pixelvalves in vc5 output two pixels per clock cycle.
Let's put the number of pixel output per clock cycle in the CRTC data and
update the various calculations to reflect that.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 18 +++++++++++-------
 drivers/gpu/drm/vc4/vc4_drv.h  |  3 +++
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 6d8fa6118fc1..e55b2208b4b7 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -235,6 +235,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
 	struct drm_crtc_state *state = crtc->state;
 	struct drm_display_mode *mode = &state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -242,6 +243,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
 		       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
+	u8 ppc = pv_data->pixels_per_clock;
 
 	/* Reset the PV fifo. */
 	CRTC_WRITE(PV_CONTROL, 0);
@@ -249,17 +251,16 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	CRTC_WRITE(PV_CONTROL, 0);
 
 	CRTC_WRITE(PV_HORZA,
-		   VC4_SET_FIELD((mode->htotal -
-				  mode->hsync_end) * pixel_rep,
+		   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
 				 PV_HORZA_HBP) |
-		   VC4_SET_FIELD((mode->hsync_end -
-				  mode->hsync_start) * pixel_rep,
+		   VC4_SET_FIELD((mode->hsync_end - mode->hsync_start) * pixel_rep / ppc,
 				 PV_HORZA_HSYNC));
+
 	CRTC_WRITE(PV_HORZB,
-		   VC4_SET_FIELD((mode->hsync_start -
-				  mode->hdisplay) * pixel_rep,
+		   VC4_SET_FIELD((mode->hsync_start - mode->hdisplay) * pixel_rep / ppc,
 				 PV_HORZB_HFP) |
-		   VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE));
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
+				 PV_HORZB_HACTIVE));
 
 	CRTC_WRITE(PV_VERTA,
 		   VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
@@ -761,6 +762,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 		.hvs_channel = 0,
 	},
 	.debugfs_name = "crtc0_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
@@ -772,6 +774,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 		.hvs_channel = 2,
 	},
 	.debugfs_name = "crtc1_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
@@ -783,6 +786,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 		.hvs_channel = 1,
 	},
 	.debugfs_name = "crtc2_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
 		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 6358f6ca8d56..0bc150daafb2 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -454,6 +454,9 @@ struct vc4_crtc_data {
 struct vc4_pv_data {
 	struct vc4_crtc_data	base;
 
+	/* Number of pixels output per clock period */
+	u8 pixels_per_clock;
+
 	enum vc4_encoder_type encoder_types[4];
 	const char *debugfs_name;
 
-- 
git-series 0.9.1

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

* [PATCH v4 07/78] drm/vc4: crtc: Deal with different number of pixel per clock
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Some of the HDMI pixelvalves in vc5 output two pixels per clock cycle.
Let's put the number of pixel output per clock cycle in the CRTC data and
update the various calculations to reflect that.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 18 +++++++++++-------
 drivers/gpu/drm/vc4/vc4_drv.h  |  3 +++
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 6d8fa6118fc1..e55b2208b4b7 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -235,6 +235,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
 	struct drm_crtc_state *state = crtc->state;
 	struct drm_display_mode *mode = &state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -242,6 +243,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
 		       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
+	u8 ppc = pv_data->pixels_per_clock;
 
 	/* Reset the PV fifo. */
 	CRTC_WRITE(PV_CONTROL, 0);
@@ -249,17 +251,16 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	CRTC_WRITE(PV_CONTROL, 0);
 
 	CRTC_WRITE(PV_HORZA,
-		   VC4_SET_FIELD((mode->htotal -
-				  mode->hsync_end) * pixel_rep,
+		   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
 				 PV_HORZA_HBP) |
-		   VC4_SET_FIELD((mode->hsync_end -
-				  mode->hsync_start) * pixel_rep,
+		   VC4_SET_FIELD((mode->hsync_end - mode->hsync_start) * pixel_rep / ppc,
 				 PV_HORZA_HSYNC));
+
 	CRTC_WRITE(PV_HORZB,
-		   VC4_SET_FIELD((mode->hsync_start -
-				  mode->hdisplay) * pixel_rep,
+		   VC4_SET_FIELD((mode->hsync_start - mode->hdisplay) * pixel_rep / ppc,
 				 PV_HORZB_HFP) |
-		   VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE));
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
+				 PV_HORZB_HACTIVE));
 
 	CRTC_WRITE(PV_VERTA,
 		   VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
@@ -761,6 +762,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 		.hvs_channel = 0,
 	},
 	.debugfs_name = "crtc0_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
@@ -772,6 +774,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 		.hvs_channel = 2,
 	},
 	.debugfs_name = "crtc1_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
@@ -783,6 +786,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 		.hvs_channel = 1,
 	},
 	.debugfs_name = "crtc2_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
 		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 6358f6ca8d56..0bc150daafb2 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -454,6 +454,9 @@ struct vc4_crtc_data {
 struct vc4_pv_data {
 	struct vc4_crtc_data	base;
 
+	/* Number of pixels output per clock period */
+	u8 pixels_per_clock;
+
 	enum vc4_encoder_type encoder_types[4];
 	const char *debugfs_name;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 07/78] drm/vc4: crtc: Deal with different number of pixel per clock
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Some of the HDMI pixelvalves in vc5 output two pixels per clock cycle.
Let's put the number of pixel output per clock cycle in the CRTC data and
update the various calculations to reflect that.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 18 +++++++++++-------
 drivers/gpu/drm/vc4/vc4_drv.h  |  3 +++
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 6d8fa6118fc1..e55b2208b4b7 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -235,6 +235,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
 	struct drm_crtc_state *state = crtc->state;
 	struct drm_display_mode *mode = &state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -242,6 +243,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 ||
 		       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
+	u8 ppc = pv_data->pixels_per_clock;
 
 	/* Reset the PV fifo. */
 	CRTC_WRITE(PV_CONTROL, 0);
@@ -249,17 +251,16 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	CRTC_WRITE(PV_CONTROL, 0);
 
 	CRTC_WRITE(PV_HORZA,
-		   VC4_SET_FIELD((mode->htotal -
-				  mode->hsync_end) * pixel_rep,
+		   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
 				 PV_HORZA_HBP) |
-		   VC4_SET_FIELD((mode->hsync_end -
-				  mode->hsync_start) * pixel_rep,
+		   VC4_SET_FIELD((mode->hsync_end - mode->hsync_start) * pixel_rep / ppc,
 				 PV_HORZA_HSYNC));
+
 	CRTC_WRITE(PV_HORZB,
-		   VC4_SET_FIELD((mode->hsync_start -
-				  mode->hdisplay) * pixel_rep,
+		   VC4_SET_FIELD((mode->hsync_start - mode->hdisplay) * pixel_rep / ppc,
 				 PV_HORZB_HFP) |
-		   VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE));
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep / ppc,
+				 PV_HORZB_HACTIVE));
 
 	CRTC_WRITE(PV_VERTA,
 		   VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
@@ -761,6 +762,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 		.hvs_channel = 0,
 	},
 	.debugfs_name = "crtc0_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
@@ -772,6 +774,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 		.hvs_channel = 2,
 	},
 	.debugfs_name = "crtc1_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
@@ -783,6 +786,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 		.hvs_channel = 1,
 	},
 	.debugfs_name = "crtc2_regs",
+	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
 		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 6358f6ca8d56..0bc150daafb2 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -454,6 +454,9 @@ struct vc4_crtc_data {
 struct vc4_pv_data {
 	struct vc4_crtc_data	base;
 
+	/* Number of pixels output per clock period */
+	u8 pixels_per_clock;
+
 	enum vc4_encoder_type encoder_types[4];
 	const char *debugfs_name;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 08/78] drm/vc4: crtc: Use a shared interrupt
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Some pixelvalves in vc5 use the same interrupt line so let's register our
interrupt handler as a shared one.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index e55b2208b4b7..9faae22cb0f8 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -919,7 +919,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
 	CRTC_WRITE(PV_INTEN, 0);
 	CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
 	ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-			       vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc);
+			       vc4_crtc_irq_handler,
+			       IRQF_SHARED,
+			       "vc4 crtc", vc4_crtc);
 	if (ret)
 		goto err_destroy_planes;
 
-- 
git-series 0.9.1

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

* [PATCH v4 08/78] drm/vc4: crtc: Use a shared interrupt
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Some pixelvalves in vc5 use the same interrupt line so let's register our
interrupt handler as a shared one.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index e55b2208b4b7..9faae22cb0f8 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -919,7 +919,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
 	CRTC_WRITE(PV_INTEN, 0);
 	CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
 	ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-			       vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc);
+			       vc4_crtc_irq_handler,
+			       IRQF_SHARED,
+			       "vc4 crtc", vc4_crtc);
 	if (ret)
 		goto err_destroy_planes;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 08/78] drm/vc4: crtc: Use a shared interrupt
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Some pixelvalves in vc5 use the same interrupt line so let's register our
interrupt handler as a shared one.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index e55b2208b4b7..9faae22cb0f8 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -919,7 +919,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
 	CRTC_WRITE(PV_INTEN, 0);
 	CRTC_WRITE(PV_INTSTAT, PV_INT_VFP_START);
 	ret = devm_request_irq(dev, platform_get_irq(pdev, 0),
-			       vc4_crtc_irq_handler, 0, "vc4 crtc", vc4_crtc);
+			       vc4_crtc_irq_handler,
+			       IRQF_SHARED,
+			       "vc4 crtc", vc4_crtc);
 	if (ret)
 		goto err_destroy_planes;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 09/78] drm/vc4: crtc: Move the cob allocation outside of bind
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The COB allocation depends on the HVS channel used for a given
pixelvalve.

While the channel allocation was entirely static in vc4, vc5 changes
that and at bind time, a pixelvalve can be assigned to multiple
HVS channels.

Let's prepare that rework by allocating the COB when it's actually
needed.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 35 +++++++++++++++++------------------
 drivers/gpu/drm/vc4/vc4_drv.h  |  2 +--
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 9faae22cb0f8..fdecaba77836 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -65,6 +65,20 @@ static const struct debugfs_reg32 crtc_regs[] = {
 	VC4_REG32(PV_HACT_ACT),
 };
 
+static unsigned int
+vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel)
+{
+	u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel));
+	/* Top/base are supposed to be 4-pixel aligned, but the
+	 * Raspberry Pi firmware fills the low bits (which are
+	 * presumably ignored).
+	 */
+	u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
+	u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
+
+	return top - base + 4;
+}
+
 static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 					  bool in_vblank_irq,
 					  int *vpos, int *hpos,
@@ -74,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
 	int vblank_lines;
@@ -109,8 +124,9 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
-	fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
+	fifo_lines = cob_size / mode->crtc_hdisplay;
 
 	if (fifo_lines > 0)
 		ret = true;
@@ -823,22 +839,6 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
 	}
 }
 
-static void
-vc4_crtc_get_cob_allocation(struct vc4_crtc *vc4_crtc)
-{
-	struct drm_device *drm = vc4_crtc->base.dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
-	u32 dispbase = HVS_READ(SCALER_DISPBASEX(vc4_crtc->channel));
-	/* Top/base are supposed to be 4-pixel aligned, but the
-	 * Raspberry Pi firmware fills the low bits (which are
-	 * presumably ignored).
-	 */
-	u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
-	u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
-
-	vc4_crtc->cob_size = top - base + 4;
-}
-
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs)
@@ -870,7 +870,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	 * implemented as private driver state in vc4_kms, not here.
 	 */
 	drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
-	vc4_crtc_get_cob_allocation(vc4_crtc);
 
 	for (i = 0; i < crtc->gamma_size; i++) {
 		vc4_crtc->lut_r[i] = i;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 0bc150daafb2..d80fc3bbb450 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -477,8 +477,6 @@ struct vc4_crtc {
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
-	/* Size in pixels of the COB memory allocated to this CRTC. */
-	u32 cob_size;
 
 	struct drm_pending_vblank_event *event;
 
-- 
git-series 0.9.1

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

* [PATCH v4 09/78] drm/vc4: crtc: Move the cob allocation outside of bind
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The COB allocation depends on the HVS channel used for a given
pixelvalve.

While the channel allocation was entirely static in vc4, vc5 changes
that and at bind time, a pixelvalve can be assigned to multiple
HVS channels.

Let's prepare that rework by allocating the COB when it's actually
needed.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 35 +++++++++++++++++------------------
 drivers/gpu/drm/vc4/vc4_drv.h  |  2 +--
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 9faae22cb0f8..fdecaba77836 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -65,6 +65,20 @@ static const struct debugfs_reg32 crtc_regs[] = {
 	VC4_REG32(PV_HACT_ACT),
 };
 
+static unsigned int
+vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel)
+{
+	u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel));
+	/* Top/base are supposed to be 4-pixel aligned, but the
+	 * Raspberry Pi firmware fills the low bits (which are
+	 * presumably ignored).
+	 */
+	u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
+	u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
+
+	return top - base + 4;
+}
+
 static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 					  bool in_vblank_irq,
 					  int *vpos, int *hpos,
@@ -74,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
 	int vblank_lines;
@@ -109,8 +124,9 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
-	fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
+	fifo_lines = cob_size / mode->crtc_hdisplay;
 
 	if (fifo_lines > 0)
 		ret = true;
@@ -823,22 +839,6 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
 	}
 }
 
-static void
-vc4_crtc_get_cob_allocation(struct vc4_crtc *vc4_crtc)
-{
-	struct drm_device *drm = vc4_crtc->base.dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
-	u32 dispbase = HVS_READ(SCALER_DISPBASEX(vc4_crtc->channel));
-	/* Top/base are supposed to be 4-pixel aligned, but the
-	 * Raspberry Pi firmware fills the low bits (which are
-	 * presumably ignored).
-	 */
-	u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
-	u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
-
-	vc4_crtc->cob_size = top - base + 4;
-}
-
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs)
@@ -870,7 +870,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	 * implemented as private driver state in vc4_kms, not here.
 	 */
 	drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
-	vc4_crtc_get_cob_allocation(vc4_crtc);
 
 	for (i = 0; i < crtc->gamma_size; i++) {
 		vc4_crtc->lut_r[i] = i;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 0bc150daafb2..d80fc3bbb450 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -477,8 +477,6 @@ struct vc4_crtc {
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
-	/* Size in pixels of the COB memory allocated to this CRTC. */
-	u32 cob_size;
 
 	struct drm_pending_vblank_event *event;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 09/78] drm/vc4: crtc: Move the cob allocation outside of bind
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The COB allocation depends on the HVS channel used for a given
pixelvalve.

While the channel allocation was entirely static in vc4, vc5 changes
that and at bind time, a pixelvalve can be assigned to multiple
HVS channels.

Let's prepare that rework by allocating the COB when it's actually
needed.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 35 +++++++++++++++++------------------
 drivers/gpu/drm/vc4/vc4_drv.h  |  2 +--
 2 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 9faae22cb0f8..fdecaba77836 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -65,6 +65,20 @@ static const struct debugfs_reg32 crtc_regs[] = {
 	VC4_REG32(PV_HACT_ACT),
 };
 
+static unsigned int
+vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel)
+{
+	u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel));
+	/* Top/base are supposed to be 4-pixel aligned, but the
+	 * Raspberry Pi firmware fills the low bits (which are
+	 * presumably ignored).
+	 */
+	u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
+	u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
+
+	return top - base + 4;
+}
+
 static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 					  bool in_vblank_irq,
 					  int *vpos, int *hpos,
@@ -74,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
 	int vblank_lines;
@@ -109,8 +124,9 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
-	fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
+	fifo_lines = cob_size / mode->crtc_hdisplay;
 
 	if (fifo_lines > 0)
 		ret = true;
@@ -823,22 +839,6 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm,
 	}
 }
 
-static void
-vc4_crtc_get_cob_allocation(struct vc4_crtc *vc4_crtc)
-{
-	struct drm_device *drm = vc4_crtc->base.dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
-	u32 dispbase = HVS_READ(SCALER_DISPBASEX(vc4_crtc->channel));
-	/* Top/base are supposed to be 4-pixel aligned, but the
-	 * Raspberry Pi firmware fills the low bits (which are
-	 * presumably ignored).
-	 */
-	u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
-	u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
-
-	vc4_crtc->cob_size = top - base + 4;
-}
-
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs)
@@ -870,7 +870,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	 * implemented as private driver state in vc4_kms, not here.
 	 */
 	drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
-	vc4_crtc_get_cob_allocation(vc4_crtc);
 
 	for (i = 0; i < crtc->gamma_size; i++) {
 		vc4_crtc->lut_r[i] = i;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 0bc150daafb2..d80fc3bbb450 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -477,8 +477,6 @@ struct vc4_crtc {
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
-	/* Size in pixels of the COB memory allocated to this CRTC. */
-	u32 cob_size;
 
 	struct drm_pending_vblank_event *event;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with
pixelvalves each being assigned to a given output, but each output can
then be muxed to feed from multiple FIFOs.

Since vc4 had that entirely static, both were probably equivalent, but
since that changes, let's rename hvs_channel to hvs_output in the
vc4_crtc_data, since a pixelvalve is really connected to an output, and
not to a FIFO.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
 drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
 drivers/gpu/drm/vc4/vc4_hvs.c  | 2 +-
 drivers/gpu/drm/vc4/vc4_txp.c  | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fdecaba77836..d3126fe04d9a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
-		.hvs_channel = 0,
+		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
 	.pixels_per_clock = 1,
@@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
-		.hvs_channel = 2,
+		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
 	.pixels_per_clock = 1,
@@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
-		.hvs_channel = 1,
+		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
 	.pixels_per_clock = 1,
@@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_channel;
+	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d80fc3bbb450..d1cf4c038180 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
-	/* Which channel of the HVS this pixelvalve sources from. */
-	int hvs_channel;
+	/* Which output of the HVS this pixelvalve sources from. */
+	int hvs_output;
 };
 
 struct vc4_pv_data {
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 091fdf4908aa..6fd9de1dc65a 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_channel == 2) {
+	if (vc4_crtc->data->hvs_output == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index a7c3af0005a0..f39d9900d027 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
-	.hvs_channel = 2,
+	.hvs_output = 2,
 };
 
 static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
-- 
git-series 0.9.1

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

* [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with
pixelvalves each being assigned to a given output, but each output can
then be muxed to feed from multiple FIFOs.

Since vc4 had that entirely static, both were probably equivalent, but
since that changes, let's rename hvs_channel to hvs_output in the
vc4_crtc_data, since a pixelvalve is really connected to an output, and
not to a FIFO.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
 drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
 drivers/gpu/drm/vc4/vc4_hvs.c  | 2 +-
 drivers/gpu/drm/vc4/vc4_txp.c  | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fdecaba77836..d3126fe04d9a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
-		.hvs_channel = 0,
+		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
 	.pixels_per_clock = 1,
@@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
-		.hvs_channel = 2,
+		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
 	.pixels_per_clock = 1,
@@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
-		.hvs_channel = 1,
+		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
 	.pixels_per_clock = 1,
@@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_channel;
+	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d80fc3bbb450..d1cf4c038180 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
-	/* Which channel of the HVS this pixelvalve sources from. */
-	int hvs_channel;
+	/* Which output of the HVS this pixelvalve sources from. */
+	int hvs_output;
 };
 
 struct vc4_pv_data {
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 091fdf4908aa..6fd9de1dc65a 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_channel == 2) {
+	if (vc4_crtc->data->hvs_output == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index a7c3af0005a0..f39d9900d027 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
-	.hvs_channel = 2,
+	.hvs_output = 2,
 };
 
 static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with
pixelvalves each being assigned to a given output, but each output can
then be muxed to feed from multiple FIFOs.

Since vc4 had that entirely static, both were probably equivalent, but
since that changes, let's rename hvs_channel to hvs_output in the
vc4_crtc_data, since a pixelvalve is really connected to an output, and
not to a FIFO.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
 drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
 drivers/gpu/drm/vc4/vc4_hvs.c  | 2 +-
 drivers/gpu/drm/vc4/vc4_txp.c  | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fdecaba77836..d3126fe04d9a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
-		.hvs_channel = 0,
+		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
 	.pixels_per_clock = 1,
@@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
-		.hvs_channel = 2,
+		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
 	.pixels_per_clock = 1,
@@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
-		.hvs_channel = 1,
+		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
 	.pixels_per_clock = 1,
@@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_channel;
+	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d80fc3bbb450..d1cf4c038180 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
-	/* Which channel of the HVS this pixelvalve sources from. */
-	int hvs_channel;
+	/* Which output of the HVS this pixelvalve sources from. */
+	int hvs_output;
 };
 
 struct vc4_pv_data {
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 091fdf4908aa..6fd9de1dc65a 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_channel == 2) {
+	if (vc4_crtc->data->hvs_output == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index a7c3af0005a0..f39d9900d027 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
-	.hvs_channel = 2,
+	.hvs_output = 2,
 };
 
 static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The vc4_crtc_handle_page_flip already has a local variable holding the
value of vc4_crtc->channel, so let's use it instead.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index d3126fe04d9a..cdeaa0cd981f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 		 * the CRTC and encoder already reconfigured, leading to
 		 * underruns. This can be seen when reconfiguring the CRTC.
 		 */
-		vc4_hvs_unmask_underrun(dev, vc4_crtc->channel);
+		vc4_hvs_unmask_underrun(dev, chan);
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
-- 
git-series 0.9.1

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

* [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4_crtc_handle_page_flip already has a local variable holding the
value of vc4_crtc->channel, so let's use it instead.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index d3126fe04d9a..cdeaa0cd981f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 		 * the CRTC and encoder already reconfigured, leading to
 		 * underruns. This can be seen when reconfiguring the CRTC.
 		 */
-		vc4_hvs_unmask_underrun(dev, vc4_crtc->channel);
+		vc4_hvs_unmask_underrun(dev, chan);
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4_crtc_handle_page_flip already has a local variable holding the
value of vc4_crtc->channel, so let's use it instead.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index d3126fe04d9a..cdeaa0cd981f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 		 * the CRTC and encoder already reconfigured, leading to
 		 * underruns. This can be seen when reconfiguring the CRTC.
 		 */
-		vc4_hvs_unmask_underrun(dev, vc4_crtc->channel);
+		vc4_hvs_unmask_underrun(dev, chan);
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The VIDEN bit in the pixelvalve currently being used to enable or disable
the pixelvalve seems to not be enough in some situations, which whill end
up with the pixelvalve stalling.

In such a case, even re-enabling VIDEN doesn't bring it back and we need to
clear the FIFO. This can only be done if the pixelvalve is disabled though.

In order to overcome this, we can configure the pixelvalve during
mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
there, and in atomic_disable disable the pixelvalve again.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index cdeaa0cd981f..fe2e5675aed4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
-				 PV_CONTROL_CLK_SELECT) |
-		   PV_CONTROL_FIFO_CLR |
-		   PV_CONTROL_EN);
+				 PV_CONTROL_CLK_SELECT));
 }
 
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
@@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+
 	vc4_hvs_atomic_disable(crtc, old_state);
 
 	/*
@@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
+	/* Reset the PV fifo. */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
+		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
-- 
git-series 0.9.1

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

* [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The VIDEN bit in the pixelvalve currently being used to enable or disable
the pixelvalve seems to not be enough in some situations, which whill end
up with the pixelvalve stalling.

In such a case, even re-enabling VIDEN doesn't bring it back and we need to
clear the FIFO. This can only be done if the pixelvalve is disabled though.

In order to overcome this, we can configure the pixelvalve during
mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
there, and in atomic_disable disable the pixelvalve again.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index cdeaa0cd981f..fe2e5675aed4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
-				 PV_CONTROL_CLK_SELECT) |
-		   PV_CONTROL_FIFO_CLR |
-		   PV_CONTROL_EN);
+				 PV_CONTROL_CLK_SELECT));
 }
 
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
@@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+
 	vc4_hvs_atomic_disable(crtc, old_state);
 
 	/*
@@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
+	/* Reset the PV fifo. */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
+		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The VIDEN bit in the pixelvalve currently being used to enable or disable
the pixelvalve seems to not be enough in some situations, which whill end
up with the pixelvalve stalling.

In such a case, even re-enabling VIDEN doesn't bring it back and we need to
clear the FIFO. This can only be done if the pixelvalve is disabled though.

In order to overcome this, we can configure the pixelvalve during
mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
there, and in atomic_disable disable the pixelvalve again.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index cdeaa0cd981f..fe2e5675aed4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
-				 PV_CONTROL_CLK_SELECT) |
-		   PV_CONTROL_FIFO_CLR |
-		   PV_CONTROL_EN);
+				 PV_CONTROL_CLK_SELECT));
 }
 
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
@@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+
 	vc4_hvs_atomic_disable(crtc, old_state);
 
 	/*
@@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
+	/* Reset the PV fifo. */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
+		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The vc4 atomic commit loop has an handrolled loop that is basically
identical to for_each_new_crtc_state, let's convert it to that helper.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 210cc2408087..717673b18132 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	struct drm_device *dev = state->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_hvs *hvs = vc4->hvs;
-	struct vc4_crtc *vc4_crtc;
+	struct drm_crtc_state *new_crtc_state;
+	struct drm_crtc *crtc;
 	int i;
 
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
-			continue;
+	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
-		vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
 		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
 	}
 
-- 
git-series 0.9.1

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

* [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4 atomic commit loop has an handrolled loop that is basically
identical to for_each_new_crtc_state, let's convert it to that helper.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 210cc2408087..717673b18132 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	struct drm_device *dev = state->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_hvs *hvs = vc4->hvs;
-	struct vc4_crtc *vc4_crtc;
+	struct drm_crtc_state *new_crtc_state;
+	struct drm_crtc *crtc;
 	int i;
 
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
-			continue;
+	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
-		vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
 		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
 	}
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4 atomic commit loop has an handrolled loop that is basically
identical to for_each_new_crtc_state, let's convert it to that helper.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 210cc2408087..717673b18132 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	struct drm_device *dev = state->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_hvs *hvs = vc4->hvs;
-	struct vc4_crtc *vc4_crtc;
+	struct drm_crtc_state *new_crtc_state;
+	struct drm_crtc *crtc;
 	int i;
 
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
-			continue;
+	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 
-		vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
 		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
 	}
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
being connected to a pixelvalve, and some muxing between the FIFOs and
outputs.

Any output cannot feed from any FIFO though, and they all have a bunch of
constraints.

In order to support this, let's store the possible FIFOs each output can be
assigned to in the vc4_crtc_data, and use that information at atomic_check
time to iterate over all the CRTCs enabled and assign them FIFOs.

The channel assigned is then set in the vc4_crtc_state so that the rest of
the driver can use it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
 drivers/gpu/drm/vc4/vc4_kms.c  | 167 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
 drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
 6 files changed, 199 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fe2e5675aed4..b7e47ce1476c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
@@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	 * Read vertical scanline which is currently composed for our
 	 * pixelvalve by the HVS, and also the scaler status.
 	 */
-	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
+	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
 
 	/* Get optional system timestamp after query. */
 	if (etime)
@@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
-	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
 	fifo_lines = cob_size / mode->crtc_hdisplay;
 
@@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	u32 chan = vc4_crtc->channel;
+	u32 chan = vc4_state->assigned_channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 	old_vc4_state = to_vc4_crtc_state(crtc->state);
 	vc4_state->feed_txp = old_vc4_state->feed_txp;
 	vc4_state->margins = old_vc4_state->margins;
+	vc4_state->assigned_channel = old_vc4_state->assigned_channel;
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
 	return &vc4_state->base;
@@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
+		.hvs_available_channels = BIT(0),
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
@@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
+		.hvs_available_channels = BIT(2),
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
@@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
+		.hvs_available_channels = BIT(1),
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
@@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d1cf4c038180..9e81ad8331f1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+	/* Bitmask of channels (FIFOs) of the HVS that the output can source from */
+	unsigned int hvs_available_channels;
+
 	/* Which output of the HVS this pixelvalve sources from. */
 	int hvs_output;
 };
@@ -471,9 +474,6 @@ struct vc4_crtc {
 	/* Timestamp at start of vblank irq - unaffected by lock delays. */
 	ktime_t t_vblank;
 
-	/* Which HVS channel we're using for our CRTC. */
-	int channel;
-
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
@@ -509,6 +509,7 @@ struct vc4_crtc_state {
 	struct drm_mm_node mm;
 	bool feed_txp;
 	bool txp_armed;
+	unsigned int assigned_channel;
 
 	struct {
 		unsigned int left;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 6fd9de1dc65a..50e88f634799 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	u32 i;
 
 	/* The LUT memory is laid out with each HVS channel in order,
@@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	 */
 	HVS_WRITE(SCALER_GAMADDR,
 		  SCALER_GAMADDR_AUTOINC |
-		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+		  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 
 	for (i = 0; i < crtc->gamma_size; i++)
 		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
@@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 			crtc->state->event = NULL;
 		}
 
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	} else {
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 	}
 }
@@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
@@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 					  SCALER5_DISPCTRLX_HEIGHT) |
 			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
+	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
@@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	u32 chan = vc4_crtc->channel;
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
+	unsigned int chan = vc4_state->assigned_channel;
 
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
@@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_plane *plane;
 	struct vc4_plane_state *vc4_plane_state;
@@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		/* This sets a black background color fill, as is the case
 		 * with other DRM drivers.
 		 */
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
-			  HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
+			  HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 			  SCALER_DISPBKGND_FILL);
 
 	/* Only update DISPLIST if the CRTC was already running and is not
@@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		vc4_hvs_update_dlist(crtc);
 
 	if (crtc->state->color_mgmt_changed) {
-		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
+		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 
 		if (crtc->state->gamma_lut) {
 			vc4_hvs_update_gamma_lut(crtc);
@@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 			 */
 			dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 		}
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 	}
 
 	if (debug_dump_regs) {
@@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_output == 2) {
+	if (vc4_state->assigned_channel == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
@@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
 	}
 
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
+	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
 		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 717673b18132..7c8a87339959 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
 		  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		u32 dispctrl;
+		u32 dsp3_mux;
+
+		if (!crtc_state->active)
+			continue;
+
+		if (vc4_state->assigned_channel != 2)
+			continue;
+
+		/*
+		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
+		 * FIFO X'.
+		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
+		 *
+		 * DSP3 is connected to FIFO2 unless the transposer is
+		 * enabled. In this case, FIFO 2 is directly accessed by the
+		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
+		 * route.
+		 */
+		if (vc4_state->feed_txp)
+			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
+		else
+			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
+
+		dispctrl = HVS_READ(SCALER_DISPCTRL) &
+			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
+		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
+	}
+}
+
+static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned char dsp2_mux = 0;
+	unsigned char dsp3_mux = 3;
+	unsigned char dsp4_mux = 3;
+	unsigned char dsp5_mux = 3;
+	unsigned int i;
+	u32 reg;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+		if (!crtc_state->active)
+			continue;
+
+		switch (vc4_crtc->data->hvs_output) {
+		case 2:
+			dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+			break;
+
+		case 3:
+			dsp3_mux = vc4_state->assigned_channel;
+			break;
+
+		case 4:
+			dsp4_mux = vc4_state->assigned_channel;
+			break;
+
+		case 5:
+			dsp5_mux = vc4_state->assigned_channel;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	reg = HVS_READ(SCALER_DISPECTRL);
+	HVS_WRITE(SCALER_DISPECTRL,
+		  (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+		  VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
+
+	reg = HVS_READ(SCALER_DISPCTRL);
+	HVS_WRITE(SCALER_DISPCTRL,
+		  (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+		  VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
+
+	reg = HVS_READ(SCALER_DISPEOLN);
+	HVS_WRITE(SCALER_DISPEOLN,
+		  (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+		  VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
+
+	reg = HVS_READ(SCALER_DISPDITHER);
+	HVS_WRITE(SCALER_DISPDITHER,
+		  (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+		  VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
+}
+
 static void
 vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
@@ -157,9 +258,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	int i;
 
 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
 
-		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
+		vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
 	}
 
 	if (vc4->hvs->hvs5)
@@ -173,6 +274,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	vc4_ctm_commit(vc4, state);
 
+	if (vc4->hvs->hvs5)
+		vc5_hvs_pv_muxing_commit(vc4, state);
+	else
+		vc4_hvs_pv_muxing_commit(vc4, state);
+
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -382,8 +488,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 
 		/* CTM is being enabled or the matrix changed. */
 		if (new_crtc_state->ctm) {
+			struct vc4_crtc_state *vc4_crtc_state =
+				to_vc4_crtc_state(new_crtc_state);
+
 			/* fifo is 1-based since 0 disables CTM. */
-			int fifo = to_vc4_crtc(crtc)->channel + 1;
+			int fifo = vc4_crtc_state->assigned_channel + 1;
 
 			/* Check userland isn't trying to turn on CTM for more
 			 * than one CRTC at a time.
@@ -493,10 +602,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
 	.atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
+#define NUM_OUTPUTS  6
+#define NUM_CHANNELS 3
+
 static int
 vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	int ret;
+	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_crtc_state =
+			to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		unsigned int matching_channels;
+
+		if (!crtc_state->active)
+			continue;
+
+		/*
+		 * The problem we have to solve here is that we have
+		 * up to 7 encoders, connected to up to 6 CRTCs.
+		 *
+		 * Those CRTCs, depending on the instance, can be
+		 * routed to 1, 2 or 3 HVS FIFOs, and we need to set
+		 * the change the muxing between FIFOs and outputs in
+		 * the HVS accordingly.
+		 *
+		 * It would be pretty hard to come up with an
+		 * algorithm that would generically solve
+		 * this. However, the current routing trees we support
+		 * allow us to simplify a bit the problem.
+		 *
+		 * Indeed, with the current supported layouts, if we
+		 * try to assign in the ascending crtc index order the
+		 * FIFOs, we can't fall into the situation where an
+		 * earlier CRTC that had multiple routes is assigned
+		 * one that was the only option for a later CRTC.
+		 *
+		 * If the layout changes and doesn't give us that in
+		 * the future, we will need to have something smarter,
+		 * but it works so far.
+		 */
+		matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+		if (matching_channels) {
+			unsigned int channel = ffs(matching_channels) - 1;
+
+			vc4_crtc_state->assigned_channel = channel;
+			unassigned_channels &= ~BIT(channel);
+		} else {
+			return -EINVAL;
+		}
+	}
 
 	ret = vc4_ctm_atomic_check(dev, state);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 91b785725555..7fbac68b6fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -286,9 +286,19 @@
 
 #define SCALER_DISPID                           0x00000008
 #define SCALER_DISPECTRL                        0x0000000c
+# define SCALER_DISPECTRL_DSP2_MUX_SHIFT	31
+# define SCALER_DISPECTRL_DSP2_MUX_MASK		VC4_MASK(31, 31)
+
 #define SCALER_DISPPROF                         0x00000010
+
 #define SCALER_DISPDITHER                       0x00000014
+# define SCALER_DISPDITHER_DSP5_MUX_SHIFT	30
+# define SCALER_DISPDITHER_DSP5_MUX_MASK	VC4_MASK(31, 30)
+
 #define SCALER_DISPEOLN                         0x00000018
+# define SCALER_DISPEOLN_DSP4_MUX_SHIFT		30
+# define SCALER_DISPEOLN_DSP4_MUX_MASK		VC4_MASK(31, 30)
+
 #define SCALER_DISPLIST0                        0x00000020
 #define SCALER_DISPLIST1                        0x00000024
 #define SCALER_DISPLIST2                        0x00000028
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index f39d9900d027..a2380d856000 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+	.hvs_available_channels = BIT(2),
 	.hvs_output = 2,
 };
 
-- 
git-series 0.9.1

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

* [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
being connected to a pixelvalve, and some muxing between the FIFOs and
outputs.

Any output cannot feed from any FIFO though, and they all have a bunch of
constraints.

In order to support this, let's store the possible FIFOs each output can be
assigned to in the vc4_crtc_data, and use that information at atomic_check
time to iterate over all the CRTCs enabled and assign them FIFOs.

The channel assigned is then set in the vc4_crtc_state so that the rest of
the driver can use it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
 drivers/gpu/drm/vc4/vc4_kms.c  | 167 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
 drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
 6 files changed, 199 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fe2e5675aed4..b7e47ce1476c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
@@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	 * Read vertical scanline which is currently composed for our
 	 * pixelvalve by the HVS, and also the scaler status.
 	 */
-	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
+	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
 
 	/* Get optional system timestamp after query. */
 	if (etime)
@@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
-	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
 	fifo_lines = cob_size / mode->crtc_hdisplay;
 
@@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	u32 chan = vc4_crtc->channel;
+	u32 chan = vc4_state->assigned_channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 	old_vc4_state = to_vc4_crtc_state(crtc->state);
 	vc4_state->feed_txp = old_vc4_state->feed_txp;
 	vc4_state->margins = old_vc4_state->margins;
+	vc4_state->assigned_channel = old_vc4_state->assigned_channel;
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
 	return &vc4_state->base;
@@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
+		.hvs_available_channels = BIT(0),
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
@@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
+		.hvs_available_channels = BIT(2),
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
@@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
+		.hvs_available_channels = BIT(1),
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
@@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d1cf4c038180..9e81ad8331f1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+	/* Bitmask of channels (FIFOs) of the HVS that the output can source from */
+	unsigned int hvs_available_channels;
+
 	/* Which output of the HVS this pixelvalve sources from. */
 	int hvs_output;
 };
@@ -471,9 +474,6 @@ struct vc4_crtc {
 	/* Timestamp at start of vblank irq - unaffected by lock delays. */
 	ktime_t t_vblank;
 
-	/* Which HVS channel we're using for our CRTC. */
-	int channel;
-
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
@@ -509,6 +509,7 @@ struct vc4_crtc_state {
 	struct drm_mm_node mm;
 	bool feed_txp;
 	bool txp_armed;
+	unsigned int assigned_channel;
 
 	struct {
 		unsigned int left;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 6fd9de1dc65a..50e88f634799 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	u32 i;
 
 	/* The LUT memory is laid out with each HVS channel in order,
@@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	 */
 	HVS_WRITE(SCALER_GAMADDR,
 		  SCALER_GAMADDR_AUTOINC |
-		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+		  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 
 	for (i = 0; i < crtc->gamma_size; i++)
 		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
@@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 			crtc->state->event = NULL;
 		}
 
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	} else {
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 	}
 }
@@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
@@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 					  SCALER5_DISPCTRLX_HEIGHT) |
 			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
+	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
@@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	u32 chan = vc4_crtc->channel;
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
+	unsigned int chan = vc4_state->assigned_channel;
 
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
@@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_plane *plane;
 	struct vc4_plane_state *vc4_plane_state;
@@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		/* This sets a black background color fill, as is the case
 		 * with other DRM drivers.
 		 */
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
-			  HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
+			  HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 			  SCALER_DISPBKGND_FILL);
 
 	/* Only update DISPLIST if the CRTC was already running and is not
@@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		vc4_hvs_update_dlist(crtc);
 
 	if (crtc->state->color_mgmt_changed) {
-		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
+		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 
 		if (crtc->state->gamma_lut) {
 			vc4_hvs_update_gamma_lut(crtc);
@@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 			 */
 			dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 		}
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 	}
 
 	if (debug_dump_regs) {
@@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_output == 2) {
+	if (vc4_state->assigned_channel == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
@@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
 	}
 
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
+	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
 		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 717673b18132..7c8a87339959 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
 		  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		u32 dispctrl;
+		u32 dsp3_mux;
+
+		if (!crtc_state->active)
+			continue;
+
+		if (vc4_state->assigned_channel != 2)
+			continue;
+
+		/*
+		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
+		 * FIFO X'.
+		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
+		 *
+		 * DSP3 is connected to FIFO2 unless the transposer is
+		 * enabled. In this case, FIFO 2 is directly accessed by the
+		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
+		 * route.
+		 */
+		if (vc4_state->feed_txp)
+			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
+		else
+			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
+
+		dispctrl = HVS_READ(SCALER_DISPCTRL) &
+			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
+		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
+	}
+}
+
+static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned char dsp2_mux = 0;
+	unsigned char dsp3_mux = 3;
+	unsigned char dsp4_mux = 3;
+	unsigned char dsp5_mux = 3;
+	unsigned int i;
+	u32 reg;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+		if (!crtc_state->active)
+			continue;
+
+		switch (vc4_crtc->data->hvs_output) {
+		case 2:
+			dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+			break;
+
+		case 3:
+			dsp3_mux = vc4_state->assigned_channel;
+			break;
+
+		case 4:
+			dsp4_mux = vc4_state->assigned_channel;
+			break;
+
+		case 5:
+			dsp5_mux = vc4_state->assigned_channel;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	reg = HVS_READ(SCALER_DISPECTRL);
+	HVS_WRITE(SCALER_DISPECTRL,
+		  (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+		  VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
+
+	reg = HVS_READ(SCALER_DISPCTRL);
+	HVS_WRITE(SCALER_DISPCTRL,
+		  (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+		  VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
+
+	reg = HVS_READ(SCALER_DISPEOLN);
+	HVS_WRITE(SCALER_DISPEOLN,
+		  (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+		  VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
+
+	reg = HVS_READ(SCALER_DISPDITHER);
+	HVS_WRITE(SCALER_DISPDITHER,
+		  (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+		  VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
+}
+
 static void
 vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
@@ -157,9 +258,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	int i;
 
 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
 
-		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
+		vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
 	}
 
 	if (vc4->hvs->hvs5)
@@ -173,6 +274,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	vc4_ctm_commit(vc4, state);
 
+	if (vc4->hvs->hvs5)
+		vc5_hvs_pv_muxing_commit(vc4, state);
+	else
+		vc4_hvs_pv_muxing_commit(vc4, state);
+
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -382,8 +488,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 
 		/* CTM is being enabled or the matrix changed. */
 		if (new_crtc_state->ctm) {
+			struct vc4_crtc_state *vc4_crtc_state =
+				to_vc4_crtc_state(new_crtc_state);
+
 			/* fifo is 1-based since 0 disables CTM. */
-			int fifo = to_vc4_crtc(crtc)->channel + 1;
+			int fifo = vc4_crtc_state->assigned_channel + 1;
 
 			/* Check userland isn't trying to turn on CTM for more
 			 * than one CRTC at a time.
@@ -493,10 +602,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
 	.atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
+#define NUM_OUTPUTS  6
+#define NUM_CHANNELS 3
+
 static int
 vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	int ret;
+	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_crtc_state =
+			to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		unsigned int matching_channels;
+
+		if (!crtc_state->active)
+			continue;
+
+		/*
+		 * The problem we have to solve here is that we have
+		 * up to 7 encoders, connected to up to 6 CRTCs.
+		 *
+		 * Those CRTCs, depending on the instance, can be
+		 * routed to 1, 2 or 3 HVS FIFOs, and we need to set
+		 * the change the muxing between FIFOs and outputs in
+		 * the HVS accordingly.
+		 *
+		 * It would be pretty hard to come up with an
+		 * algorithm that would generically solve
+		 * this. However, the current routing trees we support
+		 * allow us to simplify a bit the problem.
+		 *
+		 * Indeed, with the current supported layouts, if we
+		 * try to assign in the ascending crtc index order the
+		 * FIFOs, we can't fall into the situation where an
+		 * earlier CRTC that had multiple routes is assigned
+		 * one that was the only option for a later CRTC.
+		 *
+		 * If the layout changes and doesn't give us that in
+		 * the future, we will need to have something smarter,
+		 * but it works so far.
+		 */
+		matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+		if (matching_channels) {
+			unsigned int channel = ffs(matching_channels) - 1;
+
+			vc4_crtc_state->assigned_channel = channel;
+			unassigned_channels &= ~BIT(channel);
+		} else {
+			return -EINVAL;
+		}
+	}
 
 	ret = vc4_ctm_atomic_check(dev, state);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 91b785725555..7fbac68b6fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -286,9 +286,19 @@
 
 #define SCALER_DISPID                           0x00000008
 #define SCALER_DISPECTRL                        0x0000000c
+# define SCALER_DISPECTRL_DSP2_MUX_SHIFT	31
+# define SCALER_DISPECTRL_DSP2_MUX_MASK		VC4_MASK(31, 31)
+
 #define SCALER_DISPPROF                         0x00000010
+
 #define SCALER_DISPDITHER                       0x00000014
+# define SCALER_DISPDITHER_DSP5_MUX_SHIFT	30
+# define SCALER_DISPDITHER_DSP5_MUX_MASK	VC4_MASK(31, 30)
+
 #define SCALER_DISPEOLN                         0x00000018
+# define SCALER_DISPEOLN_DSP4_MUX_SHIFT		30
+# define SCALER_DISPEOLN_DSP4_MUX_MASK		VC4_MASK(31, 30)
+
 #define SCALER_DISPLIST0                        0x00000020
 #define SCALER_DISPLIST1                        0x00000024
 #define SCALER_DISPLIST2                        0x00000028
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index f39d9900d027..a2380d856000 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+	.hvs_available_channels = BIT(2),
 	.hvs_output = 2,
 };
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
being connected to a pixelvalve, and some muxing between the FIFOs and
outputs.

Any output cannot feed from any FIFO though, and they all have a bunch of
constraints.

In order to support this, let's store the possible FIFOs each output can be
assigned to in the vc4_crtc_data, and use that information at atomic_check
time to iterate over all the CRTCs enabled and assign them FIFOs.

The channel assigned is then set in the vc4_crtc_state so that the rest of
the driver can use it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
 drivers/gpu/drm/vc4/vc4_kms.c  | 167 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
 drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
 6 files changed, 199 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index fe2e5675aed4..b7e47ce1476c 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int cob_size;
 	u32 val;
 	int fifo_lines;
@@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 	 * Read vertical scanline which is currently composed for our
 	 * pixelvalve by the HVS, and also the scaler status.
 	 */
-	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
+	val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
 
 	/* Get optional system timestamp after query. */
 	if (etime)
@@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
 			*hpos += mode->crtc_htotal / 2;
 	}
 
-	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
+	cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
 	/* This is the offset we need for translating hvs -> pv scanout pos. */
 	fifo_lines = cob_size / mode->crtc_hdisplay;
 
@@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	u32 chan = vc4_crtc->channel;
+	u32 chan = vc4_state->assigned_channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
 	old_vc4_state = to_vc4_crtc_state(crtc->state);
 	vc4_state->feed_txp = old_vc4_state->feed_txp;
 	vc4_state->margins = old_vc4_state->margins;
+	vc4_state->assigned_channel = old_vc4_state->assigned_channel;
 
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
 	return &vc4_state->base;
@@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
 	.base = {
+		.hvs_available_channels = BIT(0),
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
@@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
 	.base = {
+		.hvs_available_channels = BIT(2),
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
@@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
 	.base = {
+		.hvs_available_channels = BIT(1),
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
@@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	vc4_crtc->channel = vc4_crtc->data->hvs_output;
 	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d1cf4c038180..9e81ad8331f1 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+	/* Bitmask of channels (FIFOs) of the HVS that the output can source from */
+	unsigned int hvs_available_channels;
+
 	/* Which output of the HVS this pixelvalve sources from. */
 	int hvs_output;
 };
@@ -471,9 +474,6 @@ struct vc4_crtc {
 	/* Timestamp at start of vblank irq - unaffected by lock delays. */
 	ktime_t t_vblank;
 
-	/* Which HVS channel we're using for our CRTC. */
-	int channel;
-
 	u8 lut_r[256];
 	u8 lut_g[256];
 	u8 lut_b[256];
@@ -509,6 +509,7 @@ struct vc4_crtc_state {
 	struct drm_mm_node mm;
 	bool feed_txp;
 	bool txp_armed;
+	unsigned int assigned_channel;
 
 	struct {
 		unsigned int left;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 6fd9de1dc65a..50e88f634799 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	u32 i;
 
 	/* The LUT memory is laid out with each HVS channel in order,
@@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
 	 */
 	HVS_WRITE(SCALER_GAMADDR,
 		  SCALER_GAMADDR_AUTOINC |
-		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+		  (vc4_state->assigned_channel * 3 * crtc->gamma_size));
 
 	for (i = 0; i < crtc->gamma_size; i++)
 		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
@@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
 			crtc->state->event = NULL;
 		}
 
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	} else {
-		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+		HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
 			  vc4_state->mm.start);
 	}
 }
@@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
@@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 					  SCALER5_DISPCTRLX_HEIGHT) |
 			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
 
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
+	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
@@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	u32 chan = vc4_crtc->channel;
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
+	unsigned int chan = vc4_state->assigned_channel;
 
 	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
 	    SCALER_DISPCTRLX_ENABLE) {
@@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_plane *plane;
 	struct vc4_plane_state *vc4_plane_state;
@@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		/* This sets a black background color fill, as is the case
 		 * with other DRM drivers.
 		 */
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
-			  HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
+			  HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
 			  SCALER_DISPBKGND_FILL);
 
 	/* Only update DISPLIST if the CRTC was already running and is not
@@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 		vc4_hvs_update_dlist(crtc);
 
 	if (crtc->state->color_mgmt_changed) {
-		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
+		u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
 
 		if (crtc->state->gamma_lut) {
 			vc4_hvs_update_gamma_lut(crtc);
@@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 			 */
 			dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
 		}
-		HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
+		HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
 	}
 
 	if (debug_dump_regs) {
@@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
 
-	if (vc4_crtc->data->hvs_output == 2) {
+	if (vc4_state->assigned_channel == 2) {
 		u32 dispctrl;
 		u32 dsp3_mux;
 
@@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
 	}
 
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
+	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
 		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 717673b18132..7c8a87339959 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
 		  VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
 }
 
+static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		u32 dispctrl;
+		u32 dsp3_mux;
+
+		if (!crtc_state->active)
+			continue;
+
+		if (vc4_state->assigned_channel != 2)
+			continue;
+
+		/*
+		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
+		 * FIFO X'.
+		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
+		 *
+		 * DSP3 is connected to FIFO2 unless the transposer is
+		 * enabled. In this case, FIFO 2 is directly accessed by the
+		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
+		 * route.
+		 */
+		if (vc4_state->feed_txp)
+			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
+		else
+			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
+
+		dispctrl = HVS_READ(SCALER_DISPCTRL) &
+			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
+		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
+	}
+}
+
+static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
+				     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	unsigned char dsp2_mux = 0;
+	unsigned char dsp3_mux = 3;
+	unsigned char dsp4_mux = 3;
+	unsigned char dsp5_mux = 3;
+	unsigned int i;
+	u32 reg;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+		if (!crtc_state->active)
+			continue;
+
+		switch (vc4_crtc->data->hvs_output) {
+		case 2:
+			dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
+			break;
+
+		case 3:
+			dsp3_mux = vc4_state->assigned_channel;
+			break;
+
+		case 4:
+			dsp4_mux = vc4_state->assigned_channel;
+			break;
+
+		case 5:
+			dsp5_mux = vc4_state->assigned_channel;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	reg = HVS_READ(SCALER_DISPECTRL);
+	HVS_WRITE(SCALER_DISPECTRL,
+		  (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
+		  VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
+
+	reg = HVS_READ(SCALER_DISPCTRL);
+	HVS_WRITE(SCALER_DISPCTRL,
+		  (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
+		  VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
+
+	reg = HVS_READ(SCALER_DISPEOLN);
+	HVS_WRITE(SCALER_DISPEOLN,
+		  (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
+		  VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
+
+	reg = HVS_READ(SCALER_DISPDITHER);
+	HVS_WRITE(SCALER_DISPDITHER,
+		  (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
+		  VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
+}
+
 static void
 vc4_atomic_complete_commit(struct drm_atomic_state *state)
 {
@@ -157,9 +258,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 	int i;
 
 	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
 
-		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
+		vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
 	}
 
 	if (vc4->hvs->hvs5)
@@ -173,6 +274,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
 
 	vc4_ctm_commit(vc4, state);
 
+	if (vc4->hvs->hvs5)
+		vc5_hvs_pv_muxing_commit(vc4, state);
+	else
+		vc4_hvs_pv_muxing_commit(vc4, state);
+
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
@@ -382,8 +488,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 
 		/* CTM is being enabled or the matrix changed. */
 		if (new_crtc_state->ctm) {
+			struct vc4_crtc_state *vc4_crtc_state =
+				to_vc4_crtc_state(new_crtc_state);
+
 			/* fifo is 1-based since 0 disables CTM. */
-			int fifo = to_vc4_crtc(crtc)->channel + 1;
+			int fifo = vc4_crtc_state->assigned_channel + 1;
 
 			/* Check userland isn't trying to turn on CTM for more
 			 * than one CRTC at a time.
@@ -493,10 +602,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
 	.atomic_destroy_state = vc4_load_tracker_destroy_state,
 };
 
+#define NUM_OUTPUTS  6
+#define NUM_CHANNELS 3
+
 static int
 vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	int ret;
+	unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		struct vc4_crtc_state *vc4_crtc_state =
+			to_vc4_crtc_state(crtc_state);
+		struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+		unsigned int matching_channels;
+
+		if (!crtc_state->active)
+			continue;
+
+		/*
+		 * The problem we have to solve here is that we have
+		 * up to 7 encoders, connected to up to 6 CRTCs.
+		 *
+		 * Those CRTCs, depending on the instance, can be
+		 * routed to 1, 2 or 3 HVS FIFOs, and we need to set
+		 * the change the muxing between FIFOs and outputs in
+		 * the HVS accordingly.
+		 *
+		 * It would be pretty hard to come up with an
+		 * algorithm that would generically solve
+		 * this. However, the current routing trees we support
+		 * allow us to simplify a bit the problem.
+		 *
+		 * Indeed, with the current supported layouts, if we
+		 * try to assign in the ascending crtc index order the
+		 * FIFOs, we can't fall into the situation where an
+		 * earlier CRTC that had multiple routes is assigned
+		 * one that was the only option for a later CRTC.
+		 *
+		 * If the layout changes and doesn't give us that in
+		 * the future, we will need to have something smarter,
+		 * but it works so far.
+		 */
+		matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
+		if (matching_channels) {
+			unsigned int channel = ffs(matching_channels) - 1;
+
+			vc4_crtc_state->assigned_channel = channel;
+			unassigned_channels &= ~BIT(channel);
+		} else {
+			return -EINVAL;
+		}
+	}
 
 	ret = vc4_ctm_atomic_check(dev, state);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 91b785725555..7fbac68b6fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -286,9 +286,19 @@
 
 #define SCALER_DISPID                           0x00000008
 #define SCALER_DISPECTRL                        0x0000000c
+# define SCALER_DISPECTRL_DSP2_MUX_SHIFT	31
+# define SCALER_DISPECTRL_DSP2_MUX_MASK		VC4_MASK(31, 31)
+
 #define SCALER_DISPPROF                         0x00000010
+
 #define SCALER_DISPDITHER                       0x00000014
+# define SCALER_DISPDITHER_DSP5_MUX_SHIFT	30
+# define SCALER_DISPDITHER_DSP5_MUX_MASK	VC4_MASK(31, 30)
+
 #define SCALER_DISPEOLN                         0x00000018
+# define SCALER_DISPEOLN_DSP4_MUX_SHIFT		30
+# define SCALER_DISPEOLN_DSP4_MUX_MASK		VC4_MASK(31, 30)
+
 #define SCALER_DISPLIST0                        0x00000020
 #define SCALER_DISPLIST1                        0x00000024
 #define SCALER_DISPLIST2                        0x00000028
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index f39d9900d027..a2380d856000 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+	.hvs_available_channels = BIT(2),
 	.hvs_output = 2,
 };
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 15/78] drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Not all pixelvalve FIFOs in vc5 have the same depth, so we need to add that
to our vc4_crtc_data structure to be able to compute the fill level
properly later on.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++---
 drivers/gpu/drm/vc4/vc4_drv.h  |  3 +++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b7e47ce1476c..2c64efd2d3d9 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -206,10 +206,21 @@ void vc4_crtc_destroy(struct drm_crtc *crtc)
 	drm_crtc_cleanup(crtc);
 }
 
-static u32 vc4_get_fifo_full_level(u32 format)
+static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
-	static const u32 fifo_len_bytes = 64;
+	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
+	u32 fifo_len_bytes = pv_data->fifo_depth;
 
+	/*
+	 * Pixels are pulled from the HVS if the number of bytes is
+	 * lower than the FIFO full level.
+	 *
+	 * The latency of the pixel fetch mechanism is 6 pixels, so we
+	 * need to convert those 6 pixels in bytes, depending on the
+	 * format, and then subtract that from the length of the FIFO
+	 * to make sure we never end up in a situation where the FIFO
+	 * is full.
+	 */
 	switch (format) {
 	case PV_CONTROL_FORMAT_DSIV_16:
 	case PV_CONTROL_FORMAT_DSIC_16:
@@ -326,7 +337,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 
 	CRTC_WRITE(PV_CONTROL,
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
-		   VC4_SET_FIELD(vc4_get_fifo_full_level(format),
+		   VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format),
 				 PV_CONTROL_FIFO_LEVEL) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
 		   PV_CONTROL_CLR_AT_START |
@@ -785,6 +796,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
@@ -798,6 +810,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
@@ -811,6 +824,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 9e81ad8331f1..179010b9a010 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -457,6 +457,9 @@ struct vc4_crtc_data {
 struct vc4_pv_data {
 	struct vc4_crtc_data	base;
 
+	/* Depth of the PixelValve FIFO in bytes */
+	unsigned int fifo_depth;
+
 	/* Number of pixels output per clock period */
 	u8 pixels_per_clock;
 
-- 
git-series 0.9.1

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

* [PATCH v4 15/78] drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Not all pixelvalve FIFOs in vc5 have the same depth, so we need to add that
to our vc4_crtc_data structure to be able to compute the fill level
properly later on.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++---
 drivers/gpu/drm/vc4/vc4_drv.h  |  3 +++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b7e47ce1476c..2c64efd2d3d9 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -206,10 +206,21 @@ void vc4_crtc_destroy(struct drm_crtc *crtc)
 	drm_crtc_cleanup(crtc);
 }
 
-static u32 vc4_get_fifo_full_level(u32 format)
+static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
-	static const u32 fifo_len_bytes = 64;
+	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
+	u32 fifo_len_bytes = pv_data->fifo_depth;
 
+	/*
+	 * Pixels are pulled from the HVS if the number of bytes is
+	 * lower than the FIFO full level.
+	 *
+	 * The latency of the pixel fetch mechanism is 6 pixels, so we
+	 * need to convert those 6 pixels in bytes, depending on the
+	 * format, and then subtract that from the length of the FIFO
+	 * to make sure we never end up in a situation where the FIFO
+	 * is full.
+	 */
 	switch (format) {
 	case PV_CONTROL_FORMAT_DSIV_16:
 	case PV_CONTROL_FORMAT_DSIC_16:
@@ -326,7 +337,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 
 	CRTC_WRITE(PV_CONTROL,
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
-		   VC4_SET_FIELD(vc4_get_fifo_full_level(format),
+		   VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format),
 				 PV_CONTROL_FIFO_LEVEL) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
 		   PV_CONTROL_CLR_AT_START |
@@ -785,6 +796,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
@@ -798,6 +810,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
@@ -811,6 +824,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 9e81ad8331f1..179010b9a010 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -457,6 +457,9 @@ struct vc4_crtc_data {
 struct vc4_pv_data {
 	struct vc4_crtc_data	base;
 
+	/* Depth of the PixelValve FIFO in bytes */
+	unsigned int fifo_depth;
+
 	/* Number of pixels output per clock period */
 	u8 pixels_per_clock;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 15/78] drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Not all pixelvalve FIFOs in vc5 have the same depth, so we need to add that
to our vc4_crtc_data structure to be able to compute the fill level
properly later on.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++---
 drivers/gpu/drm/vc4/vc4_drv.h  |  3 +++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b7e47ce1476c..2c64efd2d3d9 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -206,10 +206,21 @@ void vc4_crtc_destroy(struct drm_crtc *crtc)
 	drm_crtc_cleanup(crtc);
 }
 
-static u32 vc4_get_fifo_full_level(u32 format)
+static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
-	static const u32 fifo_len_bytes = 64;
+	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
+	u32 fifo_len_bytes = pv_data->fifo_depth;
 
+	/*
+	 * Pixels are pulled from the HVS if the number of bytes is
+	 * lower than the FIFO full level.
+	 *
+	 * The latency of the pixel fetch mechanism is 6 pixels, so we
+	 * need to convert those 6 pixels in bytes, depending on the
+	 * format, and then subtract that from the length of the FIFO
+	 * to make sure we never end up in a situation where the FIFO
+	 * is full.
+	 */
 	switch (format) {
 	case PV_CONTROL_FORMAT_DSIV_16:
 	case PV_CONTROL_FORMAT_DSIC_16:
@@ -326,7 +337,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 
 	CRTC_WRITE(PV_CONTROL,
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
-		   VC4_SET_FIELD(vc4_get_fifo_full_level(format),
+		   VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format),
 				 PV_CONTROL_FIFO_LEVEL) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
 		   PV_CONTROL_CLR_AT_START |
@@ -785,6 +796,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 		.hvs_output = 0,
 	},
 	.debugfs_name = "crtc0_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
@@ -798,6 +810,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 		.hvs_output = 2,
 	},
 	.debugfs_name = "crtc1_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
@@ -811,6 +824,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 		.hvs_output = 1,
 	},
 	.debugfs_name = "crtc2_regs",
+	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
 		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 9e81ad8331f1..179010b9a010 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -457,6 +457,9 @@ struct vc4_crtc_data {
 struct vc4_pv_data {
 	struct vc4_crtc_data	base;
 
+	/* Depth of the PixelValve FIFO in bytes */
+	unsigned int fifo_depth;
+
 	/* Number of pixels output per clock period */
 	u8 pixels_per_clock;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 16/78] drm/vc4: crtc: Add function to compute FIFO level bits
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The longer FIFOs in vc5 pixelvalves means that the FIFO full level
doesn't fit in the original register field and that we also have a
secondary field. In order to prepare for this, let's move the registers
fill part to a helper function.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2c64efd2d3d9..1d9e3658ae59 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -234,6 +234,15 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 	}
 }
 
+static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
+					     u32 format)
+{
+	u32 level = vc4_get_fifo_full_level(vc4_crtc, format);
+
+	return VC4_SET_FIELD(level & 0x3f,
+			     PV_CONTROL_FIFO_LEVEL);
+}
+
 /*
  * Returns the encoder attached to the CRTC.
  *
@@ -336,9 +345,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
 	CRTC_WRITE(PV_CONTROL,
+		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
-		   VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format),
-				 PV_CONTROL_FIFO_LEVEL) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
 		   PV_CONTROL_CLR_AT_START |
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
-- 
git-series 0.9.1

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

* [PATCH v4 16/78] drm/vc4: crtc: Add function to compute FIFO level bits
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The longer FIFOs in vc5 pixelvalves means that the FIFO full level
doesn't fit in the original register field and that we also have a
secondary field. In order to prepare for this, let's move the registers
fill part to a helper function.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2c64efd2d3d9..1d9e3658ae59 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -234,6 +234,15 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 	}
 }
 
+static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
+					     u32 format)
+{
+	u32 level = vc4_get_fifo_full_level(vc4_crtc, format);
+
+	return VC4_SET_FIELD(level & 0x3f,
+			     PV_CONTROL_FIFO_LEVEL);
+}
+
 /*
  * Returns the encoder attached to the CRTC.
  *
@@ -336,9 +345,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
 	CRTC_WRITE(PV_CONTROL,
+		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
-		   VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format),
-				 PV_CONTROL_FIFO_LEVEL) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
 		   PV_CONTROL_CLR_AT_START |
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 16/78] drm/vc4: crtc: Add function to compute FIFO level bits
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The longer FIFOs in vc5 pixelvalves means that the FIFO full level
doesn't fit in the original register field and that we also have a
secondary field. In order to prepare for this, let's move the registers
fill part to a helper function.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2c64efd2d3d9..1d9e3658ae59 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -234,6 +234,15 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 	}
 }
 
+static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
+					     u32 format)
+{
+	u32 level = vc4_get_fifo_full_level(vc4_crtc, format);
+
+	return VC4_SET_FIELD(level & 0x3f,
+			     PV_CONTROL_FIFO_LEVEL);
+}
+
 /*
  * Returns the encoder attached to the CRTC.
  *
@@ -336,9 +345,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
 	CRTC_WRITE(PV_CONTROL,
+		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
-		   VC4_SET_FIELD(vc4_get_fifo_full_level(vc4_crtc, format),
-				 PV_CONTROL_FIFO_LEVEL) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
 		   PV_CONTROL_CLR_AT_START |
 		   PV_CONTROL_TRIGGER_UNDERFLOW |
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 17/78] drm/vc4: crtc: Rename HDMI encoder type to HDMI0
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The previous generations were only supporting a single HDMI controller, but
that's about to change, so put an index as well to differentiate between
the two controllers.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 drivers/gpu/drm/vc4/vc4_drv.h  | 2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 1d9e3658ae59..04744223460a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -835,7 +835,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
-		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
+		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0,
 		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
 	},
 };
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 179010b9a010..5781773aec4b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -426,7 +426,7 @@ to_vc4_plane_state(struct drm_plane_state *state)
 
 enum vc4_encoder_type {
 	VC4_ENCODER_TYPE_NONE,
-	VC4_ENCODER_TYPE_HDMI,
+	VC4_ENCODER_TYPE_HDMI0,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
 	VC4_ENCODER_TYPE_DSI1,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a057db0d9baa..d9e48fbd7519 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1310,7 +1310,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 					GFP_KERNEL);
 	if (!vc4_hdmi_encoder)
 		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI;
+	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->encoder = &vc4_hdmi_encoder->base.base;
 
 	hdmi->pdev = pdev;
-- 
git-series 0.9.1

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

* [PATCH v4 17/78] drm/vc4: crtc: Rename HDMI encoder type to HDMI0
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The previous generations were only supporting a single HDMI controller, but
that's about to change, so put an index as well to differentiate between
the two controllers.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 drivers/gpu/drm/vc4/vc4_drv.h  | 2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 1d9e3658ae59..04744223460a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -835,7 +835,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
-		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
+		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0,
 		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
 	},
 };
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 179010b9a010..5781773aec4b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -426,7 +426,7 @@ to_vc4_plane_state(struct drm_plane_state *state)
 
 enum vc4_encoder_type {
 	VC4_ENCODER_TYPE_NONE,
-	VC4_ENCODER_TYPE_HDMI,
+	VC4_ENCODER_TYPE_HDMI0,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
 	VC4_ENCODER_TYPE_DSI1,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a057db0d9baa..d9e48fbd7519 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1310,7 +1310,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 					GFP_KERNEL);
 	if (!vc4_hdmi_encoder)
 		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI;
+	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->encoder = &vc4_hdmi_encoder->base.base;
 
 	hdmi->pdev = pdev;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 17/78] drm/vc4: crtc: Rename HDMI encoder type to HDMI0
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The previous generations were only supporting a single HDMI controller, but
that's about to change, so put an index as well to differentiate between
the two controllers.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 drivers/gpu/drm/vc4/vc4_drv.h  | 2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 1d9e3658ae59..04744223460a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -835,7 +835,7 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 	.fifo_depth = 64,
 	.pixels_per_clock = 1,
 	.encoder_types = {
-		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
+		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0,
 		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
 	},
 };
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 179010b9a010..5781773aec4b 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -426,7 +426,7 @@ to_vc4_plane_state(struct drm_plane_state *state)
 
 enum vc4_encoder_type {
 	VC4_ENCODER_TYPE_NONE,
-	VC4_ENCODER_TYPE_HDMI,
+	VC4_ENCODER_TYPE_HDMI0,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
 	VC4_ENCODER_TYPE_DSI1,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a057db0d9baa..d9e48fbd7519 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1310,7 +1310,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 					GFP_KERNEL);
 	if (!vc4_hdmi_encoder)
 		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI;
+	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->encoder = &vc4_hdmi_encoder->base.base;
 
 	hdmi->pdev = pdev;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 18/78] drm/vc4: crtc: Add HDMI1 encoder type
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The BCM2711 sports a second HDMI controller, so let's add that second HDMI
encoder type.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 5781773aec4b..4126506b3a69 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -427,6 +427,7 @@ to_vc4_plane_state(struct drm_plane_state *state)
 enum vc4_encoder_type {
 	VC4_ENCODER_TYPE_NONE,
 	VC4_ENCODER_TYPE_HDMI0,
+	VC4_ENCODER_TYPE_HDMI1,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
 	VC4_ENCODER_TYPE_DSI1,
-- 
git-series 0.9.1

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

* [PATCH v4 18/78] drm/vc4: crtc: Add HDMI1 encoder type
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 sports a second HDMI controller, so let's add that second HDMI
encoder type.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 5781773aec4b..4126506b3a69 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -427,6 +427,7 @@ to_vc4_plane_state(struct drm_plane_state *state)
 enum vc4_encoder_type {
 	VC4_ENCODER_TYPE_NONE,
 	VC4_ENCODER_TYPE_HDMI0,
+	VC4_ENCODER_TYPE_HDMI1,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
 	VC4_ENCODER_TYPE_DSI1,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 18/78] drm/vc4: crtc: Add HDMI1 encoder type
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 sports a second HDMI controller, so let's add that second HDMI
encoder type.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 5781773aec4b..4126506b3a69 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -427,6 +427,7 @@ to_vc4_plane_state(struct drm_plane_state *state)
 enum vc4_encoder_type {
 	VC4_ENCODER_TYPE_NONE,
 	VC4_ENCODER_TYPE_HDMI0,
+	VC4_ENCODER_TYPE_HDMI1,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
 	VC4_ENCODER_TYPE_DSI1,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 19/78] drm/vc4: crtc: Disable color management for HVS5
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HVS5 uses different color matrices. Disable color management support
for now.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++------
 drivers/gpu/drm/vc4/vc4_hvs.c  |  2 +-
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 04744223460a..41bc61d5a61f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -874,6 +874,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs)
 {
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct drm_crtc *crtc = &vc4_crtc->base;
 	struct drm_plane *primary_plane;
 	unsigned int i;
@@ -893,13 +894,17 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
-	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
-	/* We support CTM, but only for one CRTC at a time. It's therefore
-	 * implemented as private driver state in vc4_kms, not here.
-	 */
-	drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+	if (!vc4->hvs->hvs5) {
+		drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
+
+		drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+
+		/* We support CTM, but only for one CRTC at a time. It's therefore
+		 * implemented as private driver state in vc4_kms, not here.
+		 */
+		drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+	}
 
 	for (i = 0; i < crtc->gamma_size; i++) {
 		vc4_crtc->lut_r[i] = i;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 50e88f634799..50f9a9674a7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -443,7 +443,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 
 	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
-		  SCALER_DISPBKGND_GAMMA |
+		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
 
 	/* Reload the LUT, since the SRAMs would have been disabled if
-- 
git-series 0.9.1

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

* [PATCH v4 19/78] drm/vc4: crtc: Disable color management for HVS5
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HVS5 uses different color matrices. Disable color management support
for now.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++------
 drivers/gpu/drm/vc4/vc4_hvs.c  |  2 +-
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 04744223460a..41bc61d5a61f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -874,6 +874,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs)
 {
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct drm_crtc *crtc = &vc4_crtc->base;
 	struct drm_plane *primary_plane;
 	unsigned int i;
@@ -893,13 +894,17 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
-	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
-	/* We support CTM, but only for one CRTC at a time. It's therefore
-	 * implemented as private driver state in vc4_kms, not here.
-	 */
-	drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+	if (!vc4->hvs->hvs5) {
+		drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
+
+		drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+
+		/* We support CTM, but only for one CRTC at a time. It's therefore
+		 * implemented as private driver state in vc4_kms, not here.
+		 */
+		drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+	}
 
 	for (i = 0; i < crtc->gamma_size; i++) {
 		vc4_crtc->lut_r[i] = i;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 50e88f634799..50f9a9674a7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -443,7 +443,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 
 	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
-		  SCALER_DISPBKGND_GAMMA |
+		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
 
 	/* Reload the LUT, since the SRAMs would have been disabled if
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 19/78] drm/vc4: crtc: Disable color management for HVS5
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HVS5 uses different color matrices. Disable color management support
for now.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++------
 drivers/gpu/drm/vc4/vc4_hvs.c  |  2 +-
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 04744223460a..41bc61d5a61f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -874,6 +874,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs)
 {
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	struct drm_crtc *crtc = &vc4_crtc->base;
 	struct drm_plane *primary_plane;
 	unsigned int i;
@@ -893,13 +894,17 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 				  crtc_funcs, NULL);
 	drm_crtc_helper_add(crtc, crtc_helper_funcs);
-	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
-	drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
 
-	/* We support CTM, but only for one CRTC at a time. It's therefore
-	 * implemented as private driver state in vc4_kms, not here.
-	 */
-	drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+	if (!vc4->hvs->hvs5) {
+		drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
+
+		drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
+
+		/* We support CTM, but only for one CRTC at a time. It's therefore
+		 * implemented as private driver state in vc4_kms, not here.
+		 */
+		drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);
+	}
 
 	for (i = 0; i < crtc->gamma_size; i++) {
 		vc4_crtc->lut_r[i] = i;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 50e88f634799..50f9a9674a7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -443,7 +443,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
 
 	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
 		  SCALER_DISPBKGND_AUTOHS |
-		  SCALER_DISPBKGND_GAMMA |
+		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
 
 	/* Reload the LUT, since the SRAMs would have been disabled if
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 20/78] drm/vc4: crtc: Turn pixelvalve reset into a function
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The driver resets the pixelvalve FIFO in a number of occurences without
always using the same sequence.

Since this will be critical for BCM2711, let's move that sequence to a
function so that we are consistent.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 41bc61d5a61f..c2ab907611e3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -267,6 +267,15 @@ static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc)
 	return NULL;
 }
 
+static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
+{
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+	/* The PV needs to be disabled before it can be flushed */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR);
+}
+
 static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 {
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
@@ -282,10 +291,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
 	u8 ppc = pv_data->pixels_per_clock;
 
-	/* Reset the PV fifo. */
-	CRTC_WRITE(PV_CONTROL, 0);
-	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
-	CRTC_WRITE(PV_CONTROL, 0);
+	vc4_crtc_pixelvalve_reset(crtc);
 
 	CRTC_WRITE(PV_HORZA,
 		   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
@@ -430,9 +436,9 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	/* Reset the PV fifo. */
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
-		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+	vc4_crtc_pixelvalve_reset(crtc);
+
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
-- 
git-series 0.9.1

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

* [PATCH v4 20/78] drm/vc4: crtc: Turn pixelvalve reset into a function
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The driver resets the pixelvalve FIFO in a number of occurences without
always using the same sequence.

Since this will be critical for BCM2711, let's move that sequence to a
function so that we are consistent.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 41bc61d5a61f..c2ab907611e3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -267,6 +267,15 @@ static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc)
 	return NULL;
 }
 
+static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
+{
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+	/* The PV needs to be disabled before it can be flushed */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR);
+}
+
 static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 {
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
@@ -282,10 +291,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
 	u8 ppc = pv_data->pixels_per_clock;
 
-	/* Reset the PV fifo. */
-	CRTC_WRITE(PV_CONTROL, 0);
-	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
-	CRTC_WRITE(PV_CONTROL, 0);
+	vc4_crtc_pixelvalve_reset(crtc);
 
 	CRTC_WRITE(PV_HORZA,
 		   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
@@ -430,9 +436,9 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	/* Reset the PV fifo. */
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
-		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+	vc4_crtc_pixelvalve_reset(crtc);
+
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 20/78] drm/vc4: crtc: Turn pixelvalve reset into a function
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The driver resets the pixelvalve FIFO in a number of occurences without
always using the same sequence.

Since this will be critical for BCM2711, let's move that sequence to a
function so that we are consistent.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 41bc61d5a61f..c2ab907611e3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -267,6 +267,15 @@ static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc)
 	return NULL;
 }
 
+static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
+{
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+	/* The PV needs to be disabled before it can be flushed */
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_FIFO_CLR);
+}
+
 static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 {
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
@@ -282,10 +291,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
 	u8 ppc = pv_data->pixels_per_clock;
 
-	/* Reset the PV fifo. */
-	CRTC_WRITE(PV_CONTROL, 0);
-	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
-	CRTC_WRITE(PV_CONTROL, 0);
+	vc4_crtc_pixelvalve_reset(crtc);
 
 	CRTC_WRITE(PV_HORZA,
 		   VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
@@ -430,9 +436,9 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	/* Reset the PV fifo. */
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
-		   PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
+	vc4_crtc_pixelvalve_reset(crtc);
+
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't
really make much sense to dump its register content in its caller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index c2ab907611e3..181d3fd57bc7 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
 	u8 ppc = pv_data->pixels_per_clock;
+	bool debug_dump_regs = false;
+
+	if (debug_dump_regs) {
+		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
+		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
+			 drm_crtc_index(crtc));
+		drm_print_regset32(&p, &vc4_crtc->regset);
+	}
 
 	vc4_crtc_pixelvalve_reset(crtc);
 
@@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
 				 PV_CONTROL_CLK_SELECT));
-}
-
-static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	bool debug_dump_regs = false;
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
-		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
+		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
 			 drm_crtc_index(crtc));
 		drm_print_regset32(&p, &vc4_crtc->regset);
 	}
+}
 
+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
 	vc4_crtc_config_pv(crtc);
 
 	vc4_hvs_mode_set_nofb(crtc);
-
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
-		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
-			 drm_crtc_index(crtc));
-		drm_print_regset32(&p, &vc4_crtc->regset);
-	}
 }
 
 static void require_hvs_enabled(struct drm_device *dev)
-- 
git-series 0.9.1

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

* [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't
really make much sense to dump its register content in its caller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index c2ab907611e3..181d3fd57bc7 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
 	u8 ppc = pv_data->pixels_per_clock;
+	bool debug_dump_regs = false;
+
+	if (debug_dump_regs) {
+		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
+		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
+			 drm_crtc_index(crtc));
+		drm_print_regset32(&p, &vc4_crtc->regset);
+	}
 
 	vc4_crtc_pixelvalve_reset(crtc);
 
@@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
 				 PV_CONTROL_CLK_SELECT));
-}
-
-static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	bool debug_dump_regs = false;
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
-		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
+		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
 			 drm_crtc_index(crtc));
 		drm_print_regset32(&p, &vc4_crtc->regset);
 	}
+}
 
+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
 	vc4_crtc_config_pv(crtc);
 
 	vc4_hvs_mode_set_nofb(crtc);
-
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
-		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
-			 drm_crtc_index(crtc));
-		drm_print_regset32(&p, &vc4_crtc->regset);
-	}
 }
 
 static void require_hvs_enabled(struct drm_device *dev)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't
really make much sense to dump its register content in its caller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index c2ab907611e3..181d3fd57bc7 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		       vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
 	u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
 	u8 ppc = pv_data->pixels_per_clock;
+	bool debug_dump_regs = false;
+
+	if (debug_dump_regs) {
+		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
+		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
+			 drm_crtc_index(crtc));
+		drm_print_regset32(&p, &vc4_crtc->regset);
+	}
 
 	vc4_crtc_pixelvalve_reset(crtc);
 
@@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 		   PV_CONTROL_WAIT_HSTART |
 		   VC4_SET_FIELD(vc4_encoder->clock_select,
 				 PV_CONTROL_CLK_SELECT));
-}
-
-static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
-	bool debug_dump_regs = false;
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
-		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
+		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
 			 drm_crtc_index(crtc));
 		drm_print_regset32(&p, &vc4_crtc->regset);
 	}
+}
 
+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
 	vc4_crtc_config_pv(crtc);
 
 	vc4_hvs_mode_set_nofb(crtc);
-
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
-		dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
-			 drm_crtc_index(crtc));
-		drm_print_regset32(&p, &vc4_crtc->regset);
-	}
 }
 
 static void require_hvs_enabled(struct drm_device *dev)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to make further refactoring easier, let's move the HVS channel
setup / teardown to their own function.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++----------------
 1 file changed, 58 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 50f9a9674a7e..78bb1c0b0b76 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 	vc4_hvs_lut_load(crtc);
 }
 
+static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
+				struct drm_display_mode *mode, bool oneshot)
+{
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
+	unsigned int chan = vc4_crtc_state->assigned_channel;
+	u32 dispctrl;
+
+	/* Turn on the scaler, which will wait for vstart to start
+	 * compositing.
+	 * When feeding the transposer, we should operate in oneshot
+	 * mode.
+	 */
+	dispctrl = SCALER_DISPCTRLX_ENABLE;
+
+	if (!vc4->hvs->hvs5)
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+	else
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER5_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER5_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
+
+	HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
+
+	return 0;
+}
+
+static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
+{
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+	if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
+		return;
+
+	HVS_WRITE(SCALER_DISPCTRLX(chan),
+		  HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
+	HVS_WRITE(SCALER_DISPCTRLX(chan),
+		  HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
+
+	/* Once we leave, the scaler should be disabled and its fifo empty. */
+	WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
+
+	WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
+				   SCALER_DISPSTATX_MODE) !=
+		     SCALER_DISPSTATX_MODE_DISABLED);
+
+	WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
+		      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
+		     SCALER_DISPSTATX_EMPTY);
+}
+
 int vc4_hvs_atomic_check(struct drm_crtc *crtc,
 			 struct drm_crtc_state *state)
 {
@@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
-	u32 dispctrl;
 
 	vc4_hvs_update_dlist(crtc);
-
-	/* Turn on the scaler, which will wait for vstart to start
-	 * compositing.
-	 * When feeding the transposer, we should operate in oneshot
-	 * mode.
-	 */
-	dispctrl = SCALER_DISPCTRLX_ENABLE;
-
-	if (!vc4->hvs->hvs5)
-		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-					  SCALER_DISPCTRLX_WIDTH) |
-			    VC4_SET_FIELD(mode->vdisplay,
-					  SCALER_DISPCTRLX_HEIGHT) |
-			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
-	else
-		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-					  SCALER5_DISPCTRLX_WIDTH) |
-			    VC4_SET_FIELD(mode->vdisplay,
-					  SCALER5_DISPCTRLX_HEIGHT) |
-			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
-
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
+	vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 			    struct drm_crtc_state *old_state)
 {
 	struct drm_device *dev = crtc->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
 	unsigned int chan = vc4_state->assigned_channel;
 
-	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
-	    SCALER_DISPCTRLX_ENABLE) {
-		HVS_WRITE(SCALER_DISPCTRLX(chan),
-			  SCALER_DISPCTRLX_RESET);
-
-		/* While the docs say that reset is self-clearing, it
-		 * seems it doesn't actually.
-		 */
-		HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
-	}
-
-	/* Once we leave, the scaler should be disabled and its fifo empty. */
-
-	WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
-
-	WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
-				   SCALER_DISPSTATX_MODE) !=
-		     SCALER_DISPSTATX_MODE_DISABLED);
-
-	WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
-		      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
-		     SCALER_DISPSTATX_EMPTY);
+	vc4_hvs_stop_channel(dev, chan);
 }
 
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
-- 
git-series 0.9.1

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

* [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to make further refactoring easier, let's move the HVS channel
setup / teardown to their own function.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++----------------
 1 file changed, 58 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 50f9a9674a7e..78bb1c0b0b76 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 	vc4_hvs_lut_load(crtc);
 }
 
+static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
+				struct drm_display_mode *mode, bool oneshot)
+{
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
+	unsigned int chan = vc4_crtc_state->assigned_channel;
+	u32 dispctrl;
+
+	/* Turn on the scaler, which will wait for vstart to start
+	 * compositing.
+	 * When feeding the transposer, we should operate in oneshot
+	 * mode.
+	 */
+	dispctrl = SCALER_DISPCTRLX_ENABLE;
+
+	if (!vc4->hvs->hvs5)
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+	else
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER5_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER5_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
+
+	HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
+
+	return 0;
+}
+
+static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
+{
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+	if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
+		return;
+
+	HVS_WRITE(SCALER_DISPCTRLX(chan),
+		  HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
+	HVS_WRITE(SCALER_DISPCTRLX(chan),
+		  HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
+
+	/* Once we leave, the scaler should be disabled and its fifo empty. */
+	WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
+
+	WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
+				   SCALER_DISPSTATX_MODE) !=
+		     SCALER_DISPSTATX_MODE_DISABLED);
+
+	WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
+		      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
+		     SCALER_DISPSTATX_EMPTY);
+}
+
 int vc4_hvs_atomic_check(struct drm_crtc *crtc,
 			 struct drm_crtc_state *state)
 {
@@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
-	u32 dispctrl;
 
 	vc4_hvs_update_dlist(crtc);
-
-	/* Turn on the scaler, which will wait for vstart to start
-	 * compositing.
-	 * When feeding the transposer, we should operate in oneshot
-	 * mode.
-	 */
-	dispctrl = SCALER_DISPCTRLX_ENABLE;
-
-	if (!vc4->hvs->hvs5)
-		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-					  SCALER_DISPCTRLX_WIDTH) |
-			    VC4_SET_FIELD(mode->vdisplay,
-					  SCALER_DISPCTRLX_HEIGHT) |
-			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
-	else
-		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-					  SCALER5_DISPCTRLX_WIDTH) |
-			    VC4_SET_FIELD(mode->vdisplay,
-					  SCALER5_DISPCTRLX_HEIGHT) |
-			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
-
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
+	vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 			    struct drm_crtc_state *old_state)
 {
 	struct drm_device *dev = crtc->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
 	unsigned int chan = vc4_state->assigned_channel;
 
-	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
-	    SCALER_DISPCTRLX_ENABLE) {
-		HVS_WRITE(SCALER_DISPCTRLX(chan),
-			  SCALER_DISPCTRLX_RESET);
-
-		/* While the docs say that reset is self-clearing, it
-		 * seems it doesn't actually.
-		 */
-		HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
-	}
-
-	/* Once we leave, the scaler should be disabled and its fifo empty. */
-
-	WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
-
-	WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
-				   SCALER_DISPSTATX_MODE) !=
-		     SCALER_DISPSTATX_MODE_DISABLED);
-
-	WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
-		      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
-		     SCALER_DISPSTATX_EMPTY);
+	vc4_hvs_stop_channel(dev, chan);
 }
 
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to make further refactoring easier, let's move the HVS channel
setup / teardown to their own function.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++----------------
 1 file changed, 58 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 50f9a9674a7e..78bb1c0b0b76 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 	vc4_hvs_lut_load(crtc);
 }
 
+static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
+				struct drm_display_mode *mode, bool oneshot)
+{
+	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
+	unsigned int chan = vc4_crtc_state->assigned_channel;
+	u32 dispctrl;
+
+	/* Turn on the scaler, which will wait for vstart to start
+	 * compositing.
+	 * When feeding the transposer, we should operate in oneshot
+	 * mode.
+	 */
+	dispctrl = SCALER_DISPCTRLX_ENABLE;
+
+	if (!vc4->hvs->hvs5)
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
+	else
+		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+					  SCALER5_DISPCTRLX_WIDTH) |
+			    VC4_SET_FIELD(mode->vdisplay,
+					  SCALER5_DISPCTRLX_HEIGHT) |
+			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
+
+	HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
+
+	return 0;
+}
+
+static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
+{
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+
+	if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
+		return;
+
+	HVS_WRITE(SCALER_DISPCTRLX(chan),
+		  HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
+	HVS_WRITE(SCALER_DISPCTRLX(chan),
+		  HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
+
+	/* Once we leave, the scaler should be disabled and its fifo empty. */
+	WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
+
+	WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
+				   SCALER_DISPSTATX_MODE) !=
+		     SCALER_DISPSTATX_MODE_DISABLED);
+
+	WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
+		      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
+		     SCALER_DISPSTATX_EMPTY);
+}
+
 int vc4_hvs_atomic_check(struct drm_crtc *crtc,
 			 struct drm_crtc_state *state)
 {
@@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	bool oneshot = vc4_state->feed_txp;
-	u32 dispctrl;
 
 	vc4_hvs_update_dlist(crtc);
-
-	/* Turn on the scaler, which will wait for vstart to start
-	 * compositing.
-	 * When feeding the transposer, we should operate in oneshot
-	 * mode.
-	 */
-	dispctrl = SCALER_DISPCTRLX_ENABLE;
-
-	if (!vc4->hvs->hvs5)
-		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-					  SCALER_DISPCTRLX_WIDTH) |
-			    VC4_SET_FIELD(mode->vdisplay,
-					  SCALER_DISPCTRLX_HEIGHT) |
-			    (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
-	else
-		dispctrl |= VC4_SET_FIELD(mode->hdisplay,
-					  SCALER5_DISPCTRLX_WIDTH) |
-			    VC4_SET_FIELD(mode->vdisplay,
-					  SCALER5_DISPCTRLX_HEIGHT) |
-			    (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
-
-	HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
+	vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
 }
 
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
 			    struct drm_crtc_state *old_state)
 {
 	struct drm_device *dev = crtc->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
 	unsigned int chan = vc4_state->assigned_channel;
 
-	if (HVS_READ(SCALER_DISPCTRLX(chan)) &
-	    SCALER_DISPCTRLX_ENABLE) {
-		HVS_WRITE(SCALER_DISPCTRLX(chan),
-			  SCALER_DISPCTRLX_RESET);
-
-		/* While the docs say that reset is self-clearing, it
-		 * seems it doesn't actually.
-		 */
-		HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
-	}
-
-	/* Once we leave, the scaler should be disabled and its fifo empty. */
-
-	WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
-
-	WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
-				   SCALER_DISPSTATX_MODE) !=
-		     SCALER_DISPSTATX_MODE_DISABLED);
-
-	WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
-		      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
-		     SCALER_DISPSTATX_EMPTY);
+	vc4_hvs_stop_channel(dev, chan);
 }
 
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Since most of the HVS channel is setup in the init function, let's move the
gamma setup there too. As this makes the HVS mode_set function empty, let's
remove it in the process.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  2 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |  1 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  | 59 +++++++++--------------------------
 drivers/gpu/drm/vc4/vc4_txp.c  |  1 +-
 4 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 181d3fd57bc7..284a85b9d7d4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
 	vc4_crtc_config_pv(crtc);
-
-	vc4_hvs_mode_set_nofb(crtc);
 }
 
 static void require_hvs_enabled(struct drm_device *dev)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 4126506b3a69..dfcc684f5d28 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
-void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc);
 void vc4_hvs_dump_state(struct drm_device *dev);
 void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
 void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 78bb1c0b0b76..c7de77afbf0a 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 {
 	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int chan = vc4_crtc_state->assigned_channel;
+	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 dispbkgndx;
 	u32 dispctrl;
 
 	/* Turn on the scaler, which will wait for vstart to start
@@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 
 	HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
 
+	dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
+	dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
+	dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
+
+	HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
+		  SCALER_DISPBKGND_AUTOHS |
+		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
+		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
+
+	/* Reload the LUT, since the SRAMs would have been disabled if
+	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
+	 */
+	vc4_hvs_lut_load(crtc);
+
 	return 0;
 }
 
@@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 	}
 }
 
-void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
-
-	if (vc4_state->assigned_channel == 2) {
-		u32 dispctrl;
-		u32 dsp3_mux;
-
-		/*
-		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
-		 * FIFO X'.
-		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
-		 *
-		 * DSP3 is connected to FIFO2 unless the transposer is
-		 * enabled. In this case, FIFO 2 is directly accessed by the
-		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
-		 * route.
-		 */
-		if (vc4_state->feed_txp)
-			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
-		else
-			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
-
-		dispctrl = HVS_READ(SCALER_DISPCTRL) &
-			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
-		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
-	}
-
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
-		  SCALER_DISPBKGND_AUTOHS |
-		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
-		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
-
-	/* Reload the LUT, since the SRAMs would have been disabled if
-	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
-	 */
-	vc4_hvs_lut_load(crtc);
-}
-
 void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index a2380d856000..849dcafbfff1 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
 	.atomic_flush	= vc4_hvs_atomic_flush,
 	.atomic_enable	= vc4_txp_atomic_enable,
 	.atomic_disable	= vc4_txp_atomic_disable,
-	.mode_set_nofb	= vc4_hvs_mode_set_nofb,
 };
 
 static irqreturn_t vc4_txp_interrupt(int irq, void *data)
-- 
git-series 0.9.1

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

* [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Since most of the HVS channel is setup in the init function, let's move the
gamma setup there too. As this makes the HVS mode_set function empty, let's
remove it in the process.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  2 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |  1 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  | 59 +++++++++--------------------------
 drivers/gpu/drm/vc4/vc4_txp.c  |  1 +-
 4 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 181d3fd57bc7..284a85b9d7d4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
 	vc4_crtc_config_pv(crtc);
-
-	vc4_hvs_mode_set_nofb(crtc);
 }
 
 static void require_hvs_enabled(struct drm_device *dev)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 4126506b3a69..dfcc684f5d28 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
-void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc);
 void vc4_hvs_dump_state(struct drm_device *dev);
 void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
 void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 78bb1c0b0b76..c7de77afbf0a 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 {
 	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int chan = vc4_crtc_state->assigned_channel;
+	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 dispbkgndx;
 	u32 dispctrl;
 
 	/* Turn on the scaler, which will wait for vstart to start
@@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 
 	HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
 
+	dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
+	dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
+	dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
+
+	HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
+		  SCALER_DISPBKGND_AUTOHS |
+		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
+		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
+
+	/* Reload the LUT, since the SRAMs would have been disabled if
+	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
+	 */
+	vc4_hvs_lut_load(crtc);
+
 	return 0;
 }
 
@@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 	}
 }
 
-void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
-
-	if (vc4_state->assigned_channel == 2) {
-		u32 dispctrl;
-		u32 dsp3_mux;
-
-		/*
-		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
-		 * FIFO X'.
-		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
-		 *
-		 * DSP3 is connected to FIFO2 unless the transposer is
-		 * enabled. In this case, FIFO 2 is directly accessed by the
-		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
-		 * route.
-		 */
-		if (vc4_state->feed_txp)
-			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
-		else
-			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
-
-		dispctrl = HVS_READ(SCALER_DISPCTRL) &
-			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
-		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
-	}
-
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
-		  SCALER_DISPBKGND_AUTOHS |
-		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
-		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
-
-	/* Reload the LUT, since the SRAMs would have been disabled if
-	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
-	 */
-	vc4_hvs_lut_load(crtc);
-}
-
 void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index a2380d856000..849dcafbfff1 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
 	.atomic_flush	= vc4_hvs_atomic_flush,
 	.atomic_enable	= vc4_txp_atomic_enable,
 	.atomic_disable	= vc4_txp_atomic_disable,
-	.mode_set_nofb	= vc4_hvs_mode_set_nofb,
 };
 
 static irqreturn_t vc4_txp_interrupt(int irq, void *data)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Since most of the HVS channel is setup in the init function, let's move the
gamma setup there too. As this makes the HVS mode_set function empty, let's
remove it in the process.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c |  2 +-
 drivers/gpu/drm/vc4/vc4_drv.h  |  1 +-
 drivers/gpu/drm/vc4/vc4_hvs.c  | 59 +++++++++--------------------------
 drivers/gpu/drm/vc4/vc4_txp.c  |  1 +-
 4 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 181d3fd57bc7..284a85b9d7d4 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
 	vc4_crtc_config_pv(crtc);
-
-	vc4_hvs_mode_set_nofb(crtc);
 }
 
 static void require_hvs_enabled(struct drm_device *dev)
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 4126506b3a69..dfcc684f5d28 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
-void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc);
 void vc4_hvs_dump_state(struct drm_device *dev);
 void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
 void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 78bb1c0b0b76..c7de77afbf0a 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 {
 	struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
 	unsigned int chan = vc4_crtc_state->assigned_channel;
+	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 dispbkgndx;
 	u32 dispctrl;
 
 	/* Turn on the scaler, which will wait for vstart to start
@@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 
 	HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
 
+	dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
+	dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
+	dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
+
+	HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
+		  SCALER_DISPBKGND_AUTOHS |
+		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
+		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
+
+	/* Reload the LUT, since the SRAMs would have been disabled if
+	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
+	 */
+	vc4_hvs_lut_load(crtc);
+
 	return 0;
 }
 
@@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
 	}
 }
 
-void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
-	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-	bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
-
-	if (vc4_state->assigned_channel == 2) {
-		u32 dispctrl;
-		u32 dsp3_mux;
-
-		/*
-		 * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
-		 * FIFO X'.
-		 * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
-		 *
-		 * DSP3 is connected to FIFO2 unless the transposer is
-		 * enabled. In this case, FIFO 2 is directly accessed by the
-		 * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
-		 * route.
-		 */
-		if (vc4_state->feed_txp)
-			dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
-		else
-			dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
-
-		dispctrl = HVS_READ(SCALER_DISPCTRL) &
-			   ~SCALER_DISPCTRL_DSP3_MUX_MASK;
-		HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
-	}
-
-	HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
-		  SCALER_DISPBKGND_AUTOHS |
-		  ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
-		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
-
-	/* Reload the LUT, since the SRAMs would have been disabled if
-	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
-	 */
-	vc4_hvs_lut_load(crtc);
-}
-
 void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index a2380d856000..849dcafbfff1 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
 	.atomic_flush	= vc4_hvs_atomic_flush,
 	.atomic_enable	= vc4_txp_atomic_enable,
 	.atomic_disable	= vc4_txp_atomic_disable,
-	.mode_set_nofb	= vc4_hvs_mode_set_nofb,
 };
 
 static irqreturn_t vc4_txp_interrupt(int irq, void *data)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to clear our intermediate FIFOs that might end up with a stale
pixel, let's make sure our FIFO channel is reset everytime our channel is
setup.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index c7de77afbf0a..64b9d72471ef 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 	u32 dispbkgndx;
 	u32 dispctrl;
 
+	HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+	HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
+	HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+
 	/* Turn on the scaler, which will wait for vstart to start
 	 * compositing.
 	 * When feeding the transposer, we should operate in oneshot
-- 
git-series 0.9.1

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

* [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to clear our intermediate FIFOs that might end up with a stale
pixel, let's make sure our FIFO channel is reset everytime our channel is
setup.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index c7de77afbf0a..64b9d72471ef 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 	u32 dispbkgndx;
 	u32 dispctrl;
 
+	HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+	HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
+	HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+
 	/* Turn on the scaler, which will wait for vstart to start
 	 * compositing.
 	 * When feeding the transposer, we should operate in oneshot
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to clear our intermediate FIFOs that might end up with a stale
pixel, let's make sure our FIFO channel is reset everytime our channel is
setup.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index c7de77afbf0a..64b9d72471ef 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 	u32 dispbkgndx;
 	u32 dispctrl;
 
+	HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+	HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
+	HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
+
 	/* Turn on the scaler, which will wait for vstart to start
 	 * compositing.
 	 * When feeding the transposer, we should operate in oneshot
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the
pixelvalve needs to be setup each time there's a mode change or enable /
disable sequence.

Therefore, we can't really use mode_set_nofb anymore to configure it, but
we need to move it to atomic_enable.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 284a85b9d7d4..2eda2e6429ec 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	}
 }
 
-static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	vc4_crtc_config_pv(crtc);
-}
-
 static void require_hvs_enabled(struct drm_device *dev)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	require_hvs_enabled(dev);
 
 	vc4_crtc_pixelvalve_reset(crtc);
+	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
@@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
 };
 
 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
-	.mode_set_nofb = vc4_crtc_mode_set_nofb,
 	.mode_valid = vc4_crtc_mode_valid,
 	.atomic_check = vc4_crtc_atomic_check,
 	.atomic_flush = vc4_hvs_atomic_flush,
-- 
git-series 0.9.1

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

* [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the
pixelvalve needs to be setup each time there's a mode change or enable /
disable sequence.

Therefore, we can't really use mode_set_nofb anymore to configure it, but
we need to move it to atomic_enable.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 284a85b9d7d4..2eda2e6429ec 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	}
 }
 
-static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	vc4_crtc_config_pv(crtc);
-}
-
 static void require_hvs_enabled(struct drm_device *dev)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	require_hvs_enabled(dev);
 
 	vc4_crtc_pixelvalve_reset(crtc);
+	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
@@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
 };
 
 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
-	.mode_set_nofb = vc4_crtc_mode_set_nofb,
 	.mode_valid = vc4_crtc_mode_valid,
 	.atomic_check = vc4_crtc_atomic_check,
 	.atomic_flush = vc4_hvs_atomic_flush,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the
pixelvalve needs to be setup each time there's a mode change or enable /
disable sequence.

Therefore, we can't really use mode_set_nofb anymore to configure it, but
we need to move it to atomic_enable.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 284a85b9d7d4..2eda2e6429ec 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	}
 }
 
-static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
-{
-	vc4_crtc_config_pv(crtc);
-}
-
 static void require_hvs_enabled(struct drm_device *dev)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
@@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 	require_hvs_enabled(dev);
 
 	vc4_crtc_pixelvalve_reset(crtc);
+	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
@@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
 };
 
 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
-	.mode_set_nofb = vc4_crtc_mode_set_nofb,
 	.mode_valid = vc4_crtc_mode_valid,
 	.atomic_check = vc4_crtc_atomic_check,
 	.atomic_flush = vc4_hvs_atomic_flush,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Since we moved the pixelvalve configuration to atomic_enable, we're now
first calling the function that resets the pixelvalve and then the one that
configures it.

However, the first thing the latter is doing is calling the reset function,
meaning that we reset twice our pixelvalve. Let's remove the first call.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2eda2e6429ec..2c5ff45dc315 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
-- 
git-series 0.9.1

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

* [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Since we moved the pixelvalve configuration to atomic_enable, we're now
first calling the function that resets the pixelvalve and then the one that
configures it.

However, the first thing the latter is doing is calling the reset function,
meaning that we reset twice our pixelvalve. Let's remove the first call.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2eda2e6429ec..2c5ff45dc315 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Since we moved the pixelvalve configuration to atomic_enable, we're now
first calling the function that resets the pixelvalve and then the one that
configures it.

However, the first thing the latter is doing is calling the reset function,
meaning that we reset twice our pixelvalve. Let's remove the first call.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2eda2e6429ec..2c5ff45dc315 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to avoid stale pixels getting stuck in an intermediate FIFO
between the HVS and the pixelvalve on BCM2711, we need to configure the HVS
channel before the pixelvalve is reset and configured.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2c5ff45dc315..b7b0e19e2fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	vc4_crtc_config_pv(crtc);
-
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
-
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
@@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	vc4_hvs_atomic_enable(crtc, old_state);
 
+	vc4_crtc_config_pv(crtc);
+
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
+
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
 	 */
-- 
git-series 0.9.1

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

* [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid stale pixels getting stuck in an intermediate FIFO
between the HVS and the pixelvalve on BCM2711, we need to configure the HVS
channel before the pixelvalve is reset and configured.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2c5ff45dc315..b7b0e19e2fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	vc4_crtc_config_pv(crtc);
-
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
-
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
@@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	vc4_hvs_atomic_enable(crtc, old_state);
 
+	vc4_crtc_config_pv(crtc);
+
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
+
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
 	 */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid stale pixels getting stuck in an intermediate FIFO
between the HVS and the pixelvalve on BCM2711, we need to configure the HVS
channel before the pixelvalve is reset and configured.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2c5ff45dc315..b7b0e19e2fe1 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	require_hvs_enabled(dev);
 
-	vc4_crtc_config_pv(crtc);
-
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
-
 	/* Enable vblank irq handling before crtc is started otherwise
 	 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
 	 */
@@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	vc4_hvs_atomic_enable(crtc, old_state);
 
+	vc4_crtc_config_pv(crtc);
+
+	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
+
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
 	 */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
requires very precise ordering and timing that the regular atomic callbacks
don't provide. Let's add new callbacks on top of the regular ones to be
able to split the configuration as needed.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++
 drivers/gpu/drm/vc4/vc4_drv.h  |  7 +++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b7b0e19e2fe1..d0b326e1df0a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	int ret;
 
 	require_hvs_enabled(dev);
@@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	if (vc4_encoder->post_crtc_disable)
+		vc4_encoder->post_crtc_disable(encoder);
+
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
 
 	vc4_hvs_atomic_disable(crtc, old_state);
 
+	if (vc4_encoder->post_crtc_powerdown)
+		vc4_encoder->post_crtc_powerdown(encoder);
+
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
 	 * someone was waiting it.
@@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 
 	require_hvs_enabled(dev);
 
@@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	vc4_hvs_atomic_enable(crtc, old_state);
 
+	if (vc4_encoder->pre_crtc_configure)
+		vc4_encoder->pre_crtc_configure(encoder);
+
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
+	if (vc4_encoder->pre_crtc_enable)
+		vc4_encoder->pre_crtc_enable(encoder);
+
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
 	 */
 	CRTC_WRITE(PV_V_CONTROL,
 		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+
+	if (vc4_encoder->post_crtc_enable)
+		vc4_encoder->post_crtc_enable(encoder);
 }
 
 static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index dfcc684f5d28..251fcc35530c 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -439,6 +439,13 @@ struct vc4_encoder {
 	struct drm_encoder base;
 	enum vc4_encoder_type type;
 	u32 clock_select;
+
+	void (*pre_crtc_configure)(struct drm_encoder *encoder);
+	void (*pre_crtc_enable)(struct drm_encoder *encoder);
+	void (*post_crtc_enable)(struct drm_encoder *encoder);
+
+	void (*post_crtc_disable)(struct drm_encoder *encoder);
+	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
 };
 
 static inline struct vc4_encoder *
-- 
git-series 0.9.1

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

* [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
requires very precise ordering and timing that the regular atomic callbacks
don't provide. Let's add new callbacks on top of the regular ones to be
able to split the configuration as needed.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++
 drivers/gpu/drm/vc4/vc4_drv.h  |  7 +++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b7b0e19e2fe1..d0b326e1df0a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	int ret;
 
 	require_hvs_enabled(dev);
@@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	if (vc4_encoder->post_crtc_disable)
+		vc4_encoder->post_crtc_disable(encoder);
+
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
 
 	vc4_hvs_atomic_disable(crtc, old_state);
 
+	if (vc4_encoder->post_crtc_powerdown)
+		vc4_encoder->post_crtc_powerdown(encoder);
+
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
 	 * someone was waiting it.
@@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 
 	require_hvs_enabled(dev);
 
@@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	vc4_hvs_atomic_enable(crtc, old_state);
 
+	if (vc4_encoder->pre_crtc_configure)
+		vc4_encoder->pre_crtc_configure(encoder);
+
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
+	if (vc4_encoder->pre_crtc_enable)
+		vc4_encoder->pre_crtc_enable(encoder);
+
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
 	 */
 	CRTC_WRITE(PV_V_CONTROL,
 		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+
+	if (vc4_encoder->post_crtc_enable)
+		vc4_encoder->post_crtc_enable(encoder);
 }
 
 static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index dfcc684f5d28..251fcc35530c 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -439,6 +439,13 @@ struct vc4_encoder {
 	struct drm_encoder base;
 	enum vc4_encoder_type type;
 	u32 clock_select;
+
+	void (*pre_crtc_configure)(struct drm_encoder *encoder);
+	void (*pre_crtc_enable)(struct drm_encoder *encoder);
+	void (*post_crtc_enable)(struct drm_encoder *encoder);
+
+	void (*post_crtc_disable)(struct drm_encoder *encoder);
+	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
 };
 
 static inline struct vc4_encoder *
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
requires very precise ordering and timing that the regular atomic callbacks
don't provide. Let's add new callbacks on top of the regular ones to be
able to split the configuration as needed.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++
 drivers/gpu/drm/vc4/vc4_drv.h  |  7 +++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b7b0e19e2fe1..d0b326e1df0a 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	int ret;
 
 	require_hvs_enabled(dev);
@@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	if (vc4_encoder->post_crtc_disable)
+		vc4_encoder->post_crtc_disable(encoder);
+
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
 
 	vc4_hvs_atomic_disable(crtc, old_state);
 
+	if (vc4_encoder->post_crtc_powerdown)
+		vc4_encoder->post_crtc_powerdown(encoder);
+
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
 	 * someone was waiting it.
@@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
+	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 
 	require_hvs_enabled(dev);
 
@@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
 
 	vc4_hvs_atomic_enable(crtc, old_state);
 
+	if (vc4_encoder->pre_crtc_configure)
+		vc4_encoder->pre_crtc_configure(encoder);
+
 	vc4_crtc_config_pv(crtc);
 
 	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
 
+	if (vc4_encoder->pre_crtc_enable)
+		vc4_encoder->pre_crtc_enable(encoder);
+
 	/* When feeding the transposer block the pixelvalve is unneeded and
 	 * should not be enabled.
 	 */
 	CRTC_WRITE(PV_V_CONTROL,
 		   CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
+
+	if (vc4_encoder->post_crtc_enable)
+		vc4_encoder->post_crtc_enable(encoder);
 }
 
 static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index dfcc684f5d28..251fcc35530c 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -439,6 +439,13 @@ struct vc4_encoder {
 	struct drm_encoder base;
 	enum vc4_encoder_type type;
 	u32 clock_select;
+
+	void (*pre_crtc_configure)(struct drm_encoder *encoder);
+	void (*pre_crtc_enable)(struct drm_encoder *encoder);
+	void (*post_crtc_enable)(struct drm_encoder *encoder);
+
+	void (*post_crtc_disable)(struct drm_encoder *encoder);
+	void (*post_crtc_powerdown)(struct drm_encoder *encoder);
 };
 
 static inline struct vc4_encoder *
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to avoid pixels getting stuck in the (unflushable) FIFO between
the HVS and the PV, we need to add some delay after disabling the PV output
and before disabling the HDMI controller. 20ms seems to be good enough so
let's use that.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index d0b326e1df0a..7b178d67187f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	mdelay(20);
+
 	if (vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
-- 
git-series 0.9.1

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

* [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid pixels getting stuck in the (unflushable) FIFO between
the HVS and the PV, we need to add some delay after disabling the PV output
and before disabling the HDMI controller. 20ms seems to be good enough so
let's use that.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index d0b326e1df0a..7b178d67187f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	mdelay(20);
+
 	if (vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid pixels getting stuck in the (unflushable) FIFO between
the HVS and the PV, we need to add some delay after disabling the PV output
and before disabling the HDMI controller. 20ms seems to be good enough so
let's use that.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index d0b326e1df0a..7b178d67187f 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
 	WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
 
+	mdelay(20);
+
 	if (vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to avoid a stale pixel getting stuck on mode change or a disable
/ enable cycle, we need to make sure to flush the PV FIFO on disable.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7b178d67187f..13fe0e370fb3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -408,8 +408,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	if (vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
-
+	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_hvs_atomic_disable(crtc, old_state);
 
 	if (vc4_encoder->post_crtc_powerdown)
-- 
git-series 0.9.1

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

* [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid a stale pixel getting stuck on mode change or a disable
/ enable cycle, we need to make sure to flush the PV FIFO on disable.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7b178d67187f..13fe0e370fb3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -408,8 +408,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	if (vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
-
+	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_hvs_atomic_disable(crtc, old_state);
 
 	if (vc4_encoder->post_crtc_powerdown)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid a stale pixel getting stuck on mode change or a disable
/ enable cycle, we need to make sure to flush the PV FIFO on disable.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7b178d67187f..13fe0e370fb3 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -408,8 +408,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 	if (vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
-	CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
-
+	vc4_crtc_pixelvalve_reset(crtc);
 	vc4_hvs_atomic_disable(crtc, old_state);
 
 	if (vc4_encoder->post_crtc_powerdown)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Even though it's not really clear why we need to flush the PV FIFO during
the configuration even though we started by flushing it, experience shows
that without it we get a stale pixel stuck in the FIFO between the HVS and
the PV.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 13fe0e370fb3..25a77cd46b28 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	if (is_dsi)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
-	CRTC_WRITE(PV_CONTROL,
+	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
 		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
-- 
git-series 0.9.1

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

* [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Even though it's not really clear why we need to flush the PV FIFO during
the configuration even though we started by flushing it, experience shows
that without it we get a stale pixel stuck in the FIFO between the HVS and
the PV.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 13fe0e370fb3..25a77cd46b28 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	if (is_dsi)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
-	CRTC_WRITE(PV_CONTROL,
+	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
 		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Even though it's not really clear why we need to flush the PV FIFO during
the configuration even though we started by flushing it, experience shows
that without it we get a stale pixel stuck in the FIFO between the HVS and
the PV.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 13fe0e370fb3..25a77cd46b28 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	if (is_dsi)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
-	CRTC_WRITE(PV_CONTROL,
+	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
 		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
 		   VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 32/78] drm/vc4: hvs: Make the stop_channel function public
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

During the transition from the firmware to the KMS driver, we need to pay
particular attention to how we deal with the pixelvalves that have already
been enabled, otherwise either timeouts or stuck pixels can occur. We'll
thus need to call the function to stop an HVS channel at boot.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
 drivers/gpu/drm/vc4/vc4_hvs.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 251fcc35530c..554c2e29b23d 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -907,6 +907,7 @@ void vc4_irq_reset(struct drm_device *dev);
 
 /* vc4_hvs.c */
 extern struct platform_driver vc4_hvs_driver;
+void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 64b9d72471ef..2966dc05c7bb 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -248,7 +248,7 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 	return 0;
 }
 
-static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
+void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 
-- 
git-series 0.9.1

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

* [PATCH v4 32/78] drm/vc4: hvs: Make the stop_channel function public
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

During the transition from the firmware to the KMS driver, we need to pay
particular attention to how we deal with the pixelvalves that have already
been enabled, otherwise either timeouts or stuck pixels can occur. We'll
thus need to call the function to stop an HVS channel at boot.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
 drivers/gpu/drm/vc4/vc4_hvs.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 251fcc35530c..554c2e29b23d 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -907,6 +907,7 @@ void vc4_irq_reset(struct drm_device *dev);
 
 /* vc4_hvs.c */
 extern struct platform_driver vc4_hvs_driver;
+void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 64b9d72471ef..2966dc05c7bb 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -248,7 +248,7 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 	return 0;
 }
 
-static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
+void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 32/78] drm/vc4: hvs: Make the stop_channel function public
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

During the transition from the firmware to the KMS driver, we need to pay
particular attention to how we deal with the pixelvalves that have already
been enabled, otherwise either timeouts or stuck pixels can occur. We'll
thus need to call the function to stop an HVS channel at boot.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h | 1 +
 drivers/gpu/drm/vc4/vc4_hvs.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 251fcc35530c..554c2e29b23d 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -907,6 +907,7 @@ void vc4_irq_reset(struct drm_device *dev);
 
 /* vc4_hvs.c */
 extern struct platform_driver vc4_hvs_driver;
+void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 64b9d72471ef..2966dc05c7bb 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -248,7 +248,7 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 	return 0;
 }
 
-static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
+void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 33/78] drm/vc4: hvs: Introduce a function to get the assigned FIFO
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

At boot time, if we detect that a pixelvalve has been enabled, we need to
be able to retrieve the HVS channel it has been assigned to so that we can
disable that channel too. Let's create that function that returns the FIFO
or an error from a given output.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h |  1 +-
 drivers/gpu/drm/vc4/vc4_hvs.c | 54 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 554c2e29b23d..860be019d8e3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -908,6 +908,7 @@ void vc4_irq_reset(struct drm_device *dev);
 /* vc4_hvs.c */
 extern struct platform_driver vc4_hvs_driver;
 void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
+int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 2966dc05c7bb..4ef88c0b51ab 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -19,6 +19,7 @@
  * each CRTC.
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/platform_device.h>
@@ -196,6 +197,59 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 	vc4_hvs_lut_load(crtc);
 }
 
+int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output)
+{
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	u32 reg;
+	int ret;
+
+	if (!vc4->hvs->hvs5)
+		return output;
+
+	switch (output) {
+	case 0:
+		return 0;
+
+	case 1:
+		return 1;
+
+	case 2:
+		reg = HVS_READ(SCALER_DISPECTRL);
+		ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg);
+		if (ret == 0)
+			return 2;
+
+		return 0;
+
+	case 3:
+		reg = HVS_READ(SCALER_DISPCTRL);
+		ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	case 4:
+		reg = HVS_READ(SCALER_DISPEOLN);
+		ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	case 5:
+		reg = HVS_READ(SCALER_DISPDITHER);
+		ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	default:
+		return -EPIPE;
+	}
+}
+
 static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 				struct drm_display_mode *mode, bool oneshot)
 {
-- 
git-series 0.9.1

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

* [PATCH v4 33/78] drm/vc4: hvs: Introduce a function to get the assigned FIFO
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

At boot time, if we detect that a pixelvalve has been enabled, we need to
be able to retrieve the HVS channel it has been assigned to so that we can
disable that channel too. Let's create that function that returns the FIFO
or an error from a given output.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h |  1 +-
 drivers/gpu/drm/vc4/vc4_hvs.c | 54 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 554c2e29b23d..860be019d8e3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -908,6 +908,7 @@ void vc4_irq_reset(struct drm_device *dev);
 /* vc4_hvs.c */
 extern struct platform_driver vc4_hvs_driver;
 void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
+int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 2966dc05c7bb..4ef88c0b51ab 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -19,6 +19,7 @@
  * each CRTC.
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/platform_device.h>
@@ -196,6 +197,59 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 	vc4_hvs_lut_load(crtc);
 }
 
+int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output)
+{
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	u32 reg;
+	int ret;
+
+	if (!vc4->hvs->hvs5)
+		return output;
+
+	switch (output) {
+	case 0:
+		return 0;
+
+	case 1:
+		return 1;
+
+	case 2:
+		reg = HVS_READ(SCALER_DISPECTRL);
+		ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg);
+		if (ret == 0)
+			return 2;
+
+		return 0;
+
+	case 3:
+		reg = HVS_READ(SCALER_DISPCTRL);
+		ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	case 4:
+		reg = HVS_READ(SCALER_DISPEOLN);
+		ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	case 5:
+		reg = HVS_READ(SCALER_DISPDITHER);
+		ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	default:
+		return -EPIPE;
+	}
+}
+
 static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 				struct drm_display_mode *mode, bool oneshot)
 {
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 33/78] drm/vc4: hvs: Introduce a function to get the assigned FIFO
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

At boot time, if we detect that a pixelvalve has been enabled, we need to
be able to retrieve the HVS channel it has been assigned to so that we can
disable that channel too. Let's create that function that returns the FIFO
or an error from a given output.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h |  1 +-
 drivers/gpu/drm/vc4/vc4_hvs.c | 54 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 554c2e29b23d..860be019d8e3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -908,6 +908,7 @@ void vc4_irq_reset(struct drm_device *dev);
 /* vc4_hvs.c */
 extern struct platform_driver vc4_hvs_driver;
 void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int output);
+int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output);
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
 void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
 void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 2966dc05c7bb..4ef88c0b51ab 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -19,6 +19,7 @@
  * each CRTC.
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/platform_device.h>
@@ -196,6 +197,59 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
 	vc4_hvs_lut_load(crtc);
 }
 
+int vc4_hvs_get_fifo_from_output(struct drm_device *dev, unsigned int output)
+{
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	u32 reg;
+	int ret;
+
+	if (!vc4->hvs->hvs5)
+		return output;
+
+	switch (output) {
+	case 0:
+		return 0;
+
+	case 1:
+		return 1;
+
+	case 2:
+		reg = HVS_READ(SCALER_DISPECTRL);
+		ret = FIELD_GET(SCALER_DISPECTRL_DSP2_MUX_MASK, reg);
+		if (ret == 0)
+			return 2;
+
+		return 0;
+
+	case 3:
+		reg = HVS_READ(SCALER_DISPCTRL);
+		ret = FIELD_GET(SCALER_DISPCTRL_DSP3_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	case 4:
+		reg = HVS_READ(SCALER_DISPEOLN);
+		ret = FIELD_GET(SCALER_DISPEOLN_DSP4_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	case 5:
+		reg = HVS_READ(SCALER_DISPDITHER);
+		ret = FIELD_GET(SCALER_DISPDITHER_DSP5_MUX_MASK, reg);
+		if (ret == 3)
+			return -EPIPE;
+
+		return ret;
+
+	default:
+		return -EPIPE;
+	}
+}
+
 static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
 				struct drm_display_mode *mode, bool oneshot)
 {
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 34/78] drm/vc4: crtc: Move the CRTC disable out
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

We'll need to reuse the part that disables the HVS and PixelValve during
boot too, so let's create a separate function.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 25a77cd46b28..69851e19e2ab 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -384,20 +384,14 @@ static void require_hvs_enabled(struct drm_device *dev)
 		     SCALER_DISPCTRL_ENABLE);
 }
 
-static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
-				    struct drm_crtc_state *old_state)
+static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 {
-	struct drm_device *dev = crtc->dev;
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
 	int ret;
 
-	require_hvs_enabled(dev);
-
-	/* Disable vblank irq handling before crtc is disabled. */
-	drm_crtc_vblank_off(crtc);
-
 	CRTC_WRITE(PV_V_CONTROL,
 		   CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
@@ -405,15 +399,31 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 
 	mdelay(20);
 
-	if (vc4_encoder->post_crtc_disable)
+	if (vc4_encoder && vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
 	vc4_crtc_pixelvalve_reset(crtc);
-	vc4_hvs_atomic_disable(crtc, old_state);
+	vc4_hvs_stop_channel(dev, channel);
 
-	if (vc4_encoder->post_crtc_powerdown)
+	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
 		vc4_encoder->post_crtc_powerdown(encoder);
 
+	return 0;
+}
+
+static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state);
+	struct drm_device *dev = crtc->dev;
+
+	require_hvs_enabled(dev);
+
+	/* Disable vblank irq handling before crtc is disabled. */
+	drm_crtc_vblank_off(crtc);
+
+	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
+
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
 	 * someone was waiting it.
-- 
git-series 0.9.1

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

* [PATCH v4 34/78] drm/vc4: crtc: Move the CRTC disable out
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

We'll need to reuse the part that disables the HVS and PixelValve during
boot too, so let's create a separate function.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 25a77cd46b28..69851e19e2ab 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -384,20 +384,14 @@ static void require_hvs_enabled(struct drm_device *dev)
 		     SCALER_DISPCTRL_ENABLE);
 }
 
-static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
-				    struct drm_crtc_state *old_state)
+static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 {
-	struct drm_device *dev = crtc->dev;
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
 	int ret;
 
-	require_hvs_enabled(dev);
-
-	/* Disable vblank irq handling before crtc is disabled. */
-	drm_crtc_vblank_off(crtc);
-
 	CRTC_WRITE(PV_V_CONTROL,
 		   CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
@@ -405,15 +399,31 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 
 	mdelay(20);
 
-	if (vc4_encoder->post_crtc_disable)
+	if (vc4_encoder && vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
 	vc4_crtc_pixelvalve_reset(crtc);
-	vc4_hvs_atomic_disable(crtc, old_state);
+	vc4_hvs_stop_channel(dev, channel);
 
-	if (vc4_encoder->post_crtc_powerdown)
+	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
 		vc4_encoder->post_crtc_powerdown(encoder);
 
+	return 0;
+}
+
+static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state);
+	struct drm_device *dev = crtc->dev;
+
+	require_hvs_enabled(dev);
+
+	/* Disable vblank irq handling before crtc is disabled. */
+	drm_crtc_vblank_off(crtc);
+
+	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
+
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
 	 * someone was waiting it.
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 34/78] drm/vc4: crtc: Move the CRTC disable out
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

We'll need to reuse the part that disables the HVS and PixelValve during
boot too, so let's create a separate function.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 25a77cd46b28..69851e19e2ab 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -384,20 +384,14 @@ static void require_hvs_enabled(struct drm_device *dev)
 		     SCALER_DISPCTRL_ENABLE);
 }
 
-static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
-				    struct drm_crtc_state *old_state)
+static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 {
-	struct drm_device *dev = crtc->dev;
-	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
 	int ret;
 
-	require_hvs_enabled(dev);
-
-	/* Disable vblank irq handling before crtc is disabled. */
-	drm_crtc_vblank_off(crtc);
-
 	CRTC_WRITE(PV_V_CONTROL,
 		   CRTC_READ(PV_V_CONTROL) & ~PV_VCONTROL_VIDEN);
 	ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
@@ -405,15 +399,31 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 
 	mdelay(20);
 
-	if (vc4_encoder->post_crtc_disable)
+	if (vc4_encoder && vc4_encoder->post_crtc_disable)
 		vc4_encoder->post_crtc_disable(encoder);
 
 	vc4_crtc_pixelvalve_reset(crtc);
-	vc4_hvs_atomic_disable(crtc, old_state);
+	vc4_hvs_stop_channel(dev, channel);
 
-	if (vc4_encoder->post_crtc_powerdown)
+	if (vc4_encoder && vc4_encoder->post_crtc_powerdown)
 		vc4_encoder->post_crtc_powerdown(encoder);
 
+	return 0;
+}
+
+static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	struct vc4_crtc_state *old_vc4_state = to_vc4_crtc_state(old_state);
+	struct drm_device *dev = crtc->dev;
+
+	require_hvs_enabled(dev);
+
+	/* Disable vblank irq handling before crtc is disabled. */
+	drm_crtc_vblank_off(crtc);
+
+	vc4_crtc_disable(crtc, old_vc4_state->assigned_channel);
+
 	/*
 	 * Make sure we issue a vblank event after disabling the CRTC if
 	 * someone was waiting it.
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 35/78] drm/vc4: drv: Disable the CRTC at boot time
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to prevent issues during the firmware to KMS transition, we need
to make sure the pixelvalve are disabled at boot time so that the DRM state
matches the hardware state.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/vc4/vc4_drv.c  |  4 ++++
 drivers/gpu/drm/vc4/vc4_drv.h  |  1 +
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 69851e19e2ab..a8bc3b26a0fb 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -411,6 +411,31 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 	return 0;
 }
 
+int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
+{
+	struct drm_device *drm = crtc->dev;
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	int channel;
+
+	if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+				      "brcm,bcm2711-pixelvalve2") ||
+	      of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+				      "brcm,bcm2711-pixelvalve4")))
+		return 0;
+
+	if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN))
+		return 0;
+
+	if (!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN))
+		return 0;
+
+	channel = vc4_hvs_get_fifo_from_output(drm, vc4_crtc->data->hvs_output);
+	if (channel < 0)
+		return 0;
+
+	return vc4_crtc_disable(crtc, channel);
+}
+
 static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 38343d2fb4fb..9567d1019212 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -252,6 +252,7 @@ static int vc4_drm_bind(struct device *dev)
 	struct drm_device *drm;
 	struct vc4_dev *vc4;
 	struct device_node *node;
+	struct drm_crtc *crtc;
 	int ret = 0;
 
 	dev->coherent_dma_mask = DMA_BIT_MASK(32);
@@ -298,6 +299,9 @@ static int vc4_drm_bind(struct device *dev)
 	if (ret < 0)
 		goto unbind_all;
 
+	drm_for_each_crtc(crtc, drm)
+		vc4_crtc_disable_at_boot(crtc);
+
 	ret = drm_dev_register(drm, 0);
 	if (ret < 0)
 		goto unbind_all;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 860be019d8e3..1a97545b9244 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -813,6 +813,7 @@ void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo);
 
 /* vc4_crtc.c */
 extern struct platform_driver vc4_crtc_driver;
+int vc4_crtc_disable_at_boot(struct drm_crtc *crtc);
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs);
-- 
git-series 0.9.1

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

* [PATCH v4 35/78] drm/vc4: drv: Disable the CRTC at boot time
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to prevent issues during the firmware to KMS transition, we need
to make sure the pixelvalve are disabled at boot time so that the DRM state
matches the hardware state.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/vc4/vc4_drv.c  |  4 ++++
 drivers/gpu/drm/vc4/vc4_drv.h  |  1 +
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 69851e19e2ab..a8bc3b26a0fb 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -411,6 +411,31 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 	return 0;
 }
 
+int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
+{
+	struct drm_device *drm = crtc->dev;
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	int channel;
+
+	if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+				      "brcm,bcm2711-pixelvalve2") ||
+	      of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+				      "brcm,bcm2711-pixelvalve4")))
+		return 0;
+
+	if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN))
+		return 0;
+
+	if (!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN))
+		return 0;
+
+	channel = vc4_hvs_get_fifo_from_output(drm, vc4_crtc->data->hvs_output);
+	if (channel < 0)
+		return 0;
+
+	return vc4_crtc_disable(crtc, channel);
+}
+
 static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 38343d2fb4fb..9567d1019212 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -252,6 +252,7 @@ static int vc4_drm_bind(struct device *dev)
 	struct drm_device *drm;
 	struct vc4_dev *vc4;
 	struct device_node *node;
+	struct drm_crtc *crtc;
 	int ret = 0;
 
 	dev->coherent_dma_mask = DMA_BIT_MASK(32);
@@ -298,6 +299,9 @@ static int vc4_drm_bind(struct device *dev)
 	if (ret < 0)
 		goto unbind_all;
 
+	drm_for_each_crtc(crtc, drm)
+		vc4_crtc_disable_at_boot(crtc);
+
 	ret = drm_dev_register(drm, 0);
 	if (ret < 0)
 		goto unbind_all;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 860be019d8e3..1a97545b9244 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -813,6 +813,7 @@ void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo);
 
 /* vc4_crtc.c */
 extern struct platform_driver vc4_crtc_driver;
+int vc4_crtc_disable_at_boot(struct drm_crtc *crtc);
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 35/78] drm/vc4: drv: Disable the CRTC at boot time
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to prevent issues during the firmware to KMS transition, we need
to make sure the pixelvalve are disabled at boot time so that the DRM state
matches the hardware state.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 25 +++++++++++++++++++++++++
 drivers/gpu/drm/vc4/vc4_drv.c  |  4 ++++
 drivers/gpu/drm/vc4/vc4_drv.h  |  1 +
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 69851e19e2ab..a8bc3b26a0fb 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -411,6 +411,31 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, unsigned int channel)
 	return 0;
 }
 
+int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
+{
+	struct drm_device *drm = crtc->dev;
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	int channel;
+
+	if (!(of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+				      "brcm,bcm2711-pixelvalve2") ||
+	      of_device_is_compatible(vc4_crtc->pdev->dev.of_node,
+				      "brcm,bcm2711-pixelvalve4")))
+		return 0;
+
+	if (!(CRTC_READ(PV_CONTROL) & PV_CONTROL_EN))
+		return 0;
+
+	if (!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN))
+		return 0;
+
+	channel = vc4_hvs_get_fifo_from_output(drm, vc4_crtc->data->hvs_output);
+	if (channel < 0)
+		return 0;
+
+	return vc4_crtc_disable(crtc, channel);
+}
+
 static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 38343d2fb4fb..9567d1019212 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -252,6 +252,7 @@ static int vc4_drm_bind(struct device *dev)
 	struct drm_device *drm;
 	struct vc4_dev *vc4;
 	struct device_node *node;
+	struct drm_crtc *crtc;
 	int ret = 0;
 
 	dev->coherent_dma_mask = DMA_BIT_MASK(32);
@@ -298,6 +299,9 @@ static int vc4_drm_bind(struct device *dev)
 	if (ret < 0)
 		goto unbind_all;
 
+	drm_for_each_crtc(crtc, drm)
+		vc4_crtc_disable_at_boot(crtc);
+
 	ret = drm_dev_register(drm, 0);
 	if (ret < 0)
 		goto unbind_all;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 860be019d8e3..1a97545b9244 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -813,6 +813,7 @@ void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo);
 
 /* vc4_crtc.c */
 extern struct platform_driver vc4_crtc_driver;
+int vc4_crtc_disable_at_boot(struct drm_crtc *crtc);
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
 		  const struct drm_crtc_funcs *crtc_funcs,
 		  const struct drm_crtc_helper_funcs *crtc_helper_funcs);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 36/78] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard, Rob Herring

The BCM2711 comes with other pixelvalves that have different requirements
and capabilities. Let's document their compatible.

Reviewed-by: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
index e60791db1fa1..4e1ba03f6477 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
@@ -15,6 +15,11 @@ properties:
       - brcm,bcm2835-pixelvalve0
       - brcm,bcm2835-pixelvalve1
       - brcm,bcm2835-pixelvalve2
+      - brcm,bcm2711-pixelvalve0
+      - brcm,bcm2711-pixelvalve1
+      - brcm,bcm2711-pixelvalve2
+      - brcm,bcm2711-pixelvalve3
+      - brcm,bcm2711-pixelvalve4
 
   reg:
     maxItems: 1
-- 
git-series 0.9.1

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

* [PATCH v4 36/78] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 comes with other pixelvalves that have different requirements
and capabilities. Let's document their compatible.

Reviewed-by: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
index e60791db1fa1..4e1ba03f6477 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
@@ -15,6 +15,11 @@ properties:
       - brcm,bcm2835-pixelvalve0
       - brcm,bcm2835-pixelvalve1
       - brcm,bcm2835-pixelvalve2
+      - brcm,bcm2711-pixelvalve0
+      - brcm,bcm2711-pixelvalve1
+      - brcm,bcm2711-pixelvalve2
+      - brcm,bcm2711-pixelvalve3
+      - brcm,bcm2711-pixelvalve4
 
   reg:
     maxItems: 1
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 36/78] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 comes with other pixelvalves that have different requirements
and capabilities. Let's document their compatible.

Reviewed-by: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
index e60791db1fa1..4e1ba03f6477 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
@@ -15,6 +15,11 @@ properties:
       - brcm,bcm2835-pixelvalve0
       - brcm,bcm2835-pixelvalve1
       - brcm,bcm2835-pixelvalve2
+      - brcm,bcm2711-pixelvalve0
+      - brcm,bcm2711-pixelvalve1
+      - brcm,bcm2711-pixelvalve2
+      - brcm,bcm2711-pixelvalve3
+      - brcm,bcm2711-pixelvalve4
 
   reg:
     maxItems: 1
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 37/78] drm/vc4: crtc: Add BCM2711 pixelvalves
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The BCM2711 has 5 pixelvalves, so now that our driver is ready, let's add
support for them.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 95 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  7 +++-
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index a8bc3b26a0fb..c19687eabaf6 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -208,6 +208,7 @@ void vc4_crtc_destroy(struct drm_crtc *crtc)
 
 static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
+	const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
 	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
 	u32 fifo_len_bytes = pv_data->fifo_depth;
 
@@ -230,6 +231,13 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 	case PV_CONTROL_FORMAT_24:
 	case PV_CONTROL_FORMAT_DSIV_24:
 	default:
+		/*
+		 * For some reason, the pixelvalve4 doesn't work with
+		 * the usual formula and will only work with 32.
+		 */
+		if (crtc_data->hvs_output == 5)
+			return 32;
+
 		return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX;
 	}
 }
@@ -238,9 +246,13 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
 					     u32 format)
 {
 	u32 level = vc4_get_fifo_full_level(vc4_crtc, format);
+	u32 ret = 0;
+
+	ret |= VC4_SET_FIELD((level >> 6),
+			     PV5_CONTROL_FIFO_LEVEL_HIGH);
 
-	return VC4_SET_FIELD(level & 0x3f,
-			     PV_CONTROL_FIFO_LEVEL);
+	return ret | VC4_SET_FIELD(level & 0x3f,
+				   PV_CONTROL_FIFO_LEVEL);
 }
 
 /*
@@ -278,6 +290,8 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
 
 static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
@@ -358,6 +372,11 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	if (is_dsi)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
+	if (vc4->hvs->hvs5)
+		CRTC_WRITE(PV_MUX_CFG,
+			   VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP,
+					 PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
+
 	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
 		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
@@ -891,10 +910,82 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 	},
 };
 
+static const struct vc4_pv_data bcm2711_pv0_data = {
+	.base = {
+		.hvs_available_channels = BIT(0),
+		.hvs_output = 0,
+	},
+	.debugfs_name = "crtc0_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_DSI0,
+		[1] = VC4_ENCODER_TYPE_DPI,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv1_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 3,
+	},
+	.debugfs_name = "crtc1_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_DSI1,
+		[1] = VC4_ENCODER_TYPE_SMI,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv2_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 4,
+	},
+	.debugfs_name = "crtc2_regs",
+	.fifo_depth = 256,
+	.pixels_per_clock = 2,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_HDMI0,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv3_data = {
+	.base = {
+		.hvs_available_channels = BIT(1),
+		.hvs_output = 1,
+	},
+	.debugfs_name = "crtc3_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_VEC,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv4_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 5,
+	},
+	.debugfs_name = "crtc4_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 2,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_HDMI1,
+	},
+};
+
 static const struct of_device_id vc4_crtc_dt_match[] = {
 	{ .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data },
 	{ .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data },
 	{ .compatible = "brcm,bcm2835-pixelvalve2", .data = &bcm2835_pv2_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve0", .data = &bcm2711_pv0_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve1", .data = &bcm2711_pv1_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 7fbac68b6fe1..c0031ab19689 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -129,6 +129,8 @@
 #define V3D_ERRSTAT  0x00f20
 
 #define PV_CONTROL				0x00
+# define PV5_CONTROL_FIFO_LEVEL_HIGH_MASK	VC4_MASK(26, 25)
+# define PV5_CONTROL_FIFO_LEVEL_HIGH_SHIFT	25
 # define PV_CONTROL_FORMAT_MASK			VC4_MASK(23, 21)
 # define PV_CONTROL_FORMAT_SHIFT		21
 # define PV_CONTROL_FORMAT_24			0
@@ -208,6 +210,11 @@
 
 #define PV_HACT_ACT				0x30
 
+#define PV_MUX_CFG				0x34
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_MASK	VC4_MASK(5, 2)
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT	2
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP	8
+
 #define SCALER_CHANNELS_COUNT			3
 
 #define SCALER_DISPCTRL                         0x00000000
-- 
git-series 0.9.1

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

* [PATCH v4 37/78] drm/vc4: crtc: Add BCM2711 pixelvalves
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 has 5 pixelvalves, so now that our driver is ready, let's add
support for them.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 95 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  7 +++-
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index a8bc3b26a0fb..c19687eabaf6 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -208,6 +208,7 @@ void vc4_crtc_destroy(struct drm_crtc *crtc)
 
 static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
+	const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
 	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
 	u32 fifo_len_bytes = pv_data->fifo_depth;
 
@@ -230,6 +231,13 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 	case PV_CONTROL_FORMAT_24:
 	case PV_CONTROL_FORMAT_DSIV_24:
 	default:
+		/*
+		 * For some reason, the pixelvalve4 doesn't work with
+		 * the usual formula and will only work with 32.
+		 */
+		if (crtc_data->hvs_output == 5)
+			return 32;
+
 		return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX;
 	}
 }
@@ -238,9 +246,13 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
 					     u32 format)
 {
 	u32 level = vc4_get_fifo_full_level(vc4_crtc, format);
+	u32 ret = 0;
+
+	ret |= VC4_SET_FIELD((level >> 6),
+			     PV5_CONTROL_FIFO_LEVEL_HIGH);
 
-	return VC4_SET_FIELD(level & 0x3f,
-			     PV_CONTROL_FIFO_LEVEL);
+	return ret | VC4_SET_FIELD(level & 0x3f,
+				   PV_CONTROL_FIFO_LEVEL);
 }
 
 /*
@@ -278,6 +290,8 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
 
 static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
@@ -358,6 +372,11 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	if (is_dsi)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
+	if (vc4->hvs->hvs5)
+		CRTC_WRITE(PV_MUX_CFG,
+			   VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP,
+					 PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
+
 	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
 		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
@@ -891,10 +910,82 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 	},
 };
 
+static const struct vc4_pv_data bcm2711_pv0_data = {
+	.base = {
+		.hvs_available_channels = BIT(0),
+		.hvs_output = 0,
+	},
+	.debugfs_name = "crtc0_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_DSI0,
+		[1] = VC4_ENCODER_TYPE_DPI,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv1_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 3,
+	},
+	.debugfs_name = "crtc1_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_DSI1,
+		[1] = VC4_ENCODER_TYPE_SMI,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv2_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 4,
+	},
+	.debugfs_name = "crtc2_regs",
+	.fifo_depth = 256,
+	.pixels_per_clock = 2,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_HDMI0,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv3_data = {
+	.base = {
+		.hvs_available_channels = BIT(1),
+		.hvs_output = 1,
+	},
+	.debugfs_name = "crtc3_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_VEC,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv4_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 5,
+	},
+	.debugfs_name = "crtc4_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 2,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_HDMI1,
+	},
+};
+
 static const struct of_device_id vc4_crtc_dt_match[] = {
 	{ .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data },
 	{ .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data },
 	{ .compatible = "brcm,bcm2835-pixelvalve2", .data = &bcm2835_pv2_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve0", .data = &bcm2711_pv0_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve1", .data = &bcm2711_pv1_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 7fbac68b6fe1..c0031ab19689 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -129,6 +129,8 @@
 #define V3D_ERRSTAT  0x00f20
 
 #define PV_CONTROL				0x00
+# define PV5_CONTROL_FIFO_LEVEL_HIGH_MASK	VC4_MASK(26, 25)
+# define PV5_CONTROL_FIFO_LEVEL_HIGH_SHIFT	25
 # define PV_CONTROL_FORMAT_MASK			VC4_MASK(23, 21)
 # define PV_CONTROL_FORMAT_SHIFT		21
 # define PV_CONTROL_FORMAT_24			0
@@ -208,6 +210,11 @@
 
 #define PV_HACT_ACT				0x30
 
+#define PV_MUX_CFG				0x34
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_MASK	VC4_MASK(5, 2)
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT	2
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP	8
+
 #define SCALER_CHANNELS_COUNT			3
 
 #define SCALER_DISPCTRL                         0x00000000
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 37/78] drm/vc4: crtc: Add BCM2711 pixelvalves
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 has 5 pixelvalves, so now that our driver is ready, let's add
support for them.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_crtc.c | 95 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h |  7 +++-
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index a8bc3b26a0fb..c19687eabaf6 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -208,6 +208,7 @@ void vc4_crtc_destroy(struct drm_crtc *crtc)
 
 static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
+	const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
 	const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
 	u32 fifo_len_bytes = pv_data->fifo_depth;
 
@@ -230,6 +231,13 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 	case PV_CONTROL_FORMAT_24:
 	case PV_CONTROL_FORMAT_DSIV_24:
 	default:
+		/*
+		 * For some reason, the pixelvalve4 doesn't work with
+		 * the usual formula and will only work with 32.
+		 */
+		if (crtc_data->hvs_output == 5)
+			return 32;
+
 		return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX;
 	}
 }
@@ -238,9 +246,13 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
 					     u32 format)
 {
 	u32 level = vc4_get_fifo_full_level(vc4_crtc, format);
+	u32 ret = 0;
+
+	ret |= VC4_SET_FIELD((level >> 6),
+			     PV5_CONTROL_FIFO_LEVEL_HIGH);
 
-	return VC4_SET_FIELD(level & 0x3f,
-			     PV_CONTROL_FIFO_LEVEL);
+	return ret | VC4_SET_FIELD(level & 0x3f,
+				   PV_CONTROL_FIFO_LEVEL);
 }
 
 /*
@@ -278,6 +290,8 @@ static void vc4_crtc_pixelvalve_reset(struct drm_crtc *crtc)
 
 static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
 	struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
@@ -358,6 +372,11 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
 	if (is_dsi)
 		CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
 
+	if (vc4->hvs->hvs5)
+		CRTC_WRITE(PV_MUX_CFG,
+			   VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP,
+					 PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
+
 	CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
 		   vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
 		   VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
@@ -891,10 +910,82 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 	},
 };
 
+static const struct vc4_pv_data bcm2711_pv0_data = {
+	.base = {
+		.hvs_available_channels = BIT(0),
+		.hvs_output = 0,
+	},
+	.debugfs_name = "crtc0_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_DSI0,
+		[1] = VC4_ENCODER_TYPE_DPI,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv1_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 3,
+	},
+	.debugfs_name = "crtc1_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_DSI1,
+		[1] = VC4_ENCODER_TYPE_SMI,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv2_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 4,
+	},
+	.debugfs_name = "crtc2_regs",
+	.fifo_depth = 256,
+	.pixels_per_clock = 2,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_HDMI0,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv3_data = {
+	.base = {
+		.hvs_available_channels = BIT(1),
+		.hvs_output = 1,
+	},
+	.debugfs_name = "crtc3_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 1,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_VEC,
+	},
+};
+
+static const struct vc4_pv_data bcm2711_pv4_data = {
+	.base = {
+		.hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+		.hvs_output = 5,
+	},
+	.debugfs_name = "crtc4_regs",
+	.fifo_depth = 64,
+	.pixels_per_clock = 2,
+	.encoder_types = {
+		[0] = VC4_ENCODER_TYPE_HDMI1,
+	},
+};
+
 static const struct of_device_id vc4_crtc_dt_match[] = {
 	{ .compatible = "brcm,bcm2835-pixelvalve0", .data = &bcm2835_pv0_data },
 	{ .compatible = "brcm,bcm2835-pixelvalve1", .data = &bcm2835_pv1_data },
 	{ .compatible = "brcm,bcm2835-pixelvalve2", .data = &bcm2835_pv2_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve0", .data = &bcm2711_pv0_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve1", .data = &bcm2711_pv1_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve2", .data = &bcm2711_pv2_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve3", .data = &bcm2711_pv3_data },
+	{ .compatible = "brcm,bcm2711-pixelvalve4", .data = &bcm2711_pv4_data },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 7fbac68b6fe1..c0031ab19689 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -129,6 +129,8 @@
 #define V3D_ERRSTAT  0x00f20
 
 #define PV_CONTROL				0x00
+# define PV5_CONTROL_FIFO_LEVEL_HIGH_MASK	VC4_MASK(26, 25)
+# define PV5_CONTROL_FIFO_LEVEL_HIGH_SHIFT	25
 # define PV_CONTROL_FORMAT_MASK			VC4_MASK(23, 21)
 # define PV_CONTROL_FORMAT_SHIFT		21
 # define PV_CONTROL_FORMAT_24			0
@@ -208,6 +210,11 @@
 
 #define PV_HACT_ACT				0x30
 
+#define PV_MUX_CFG				0x34
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_MASK	VC4_MASK(5, 2)
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_SHIFT	2
+# define PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP	8
+
 #define SCALER_CHANNELS_COUNT			3
 
 #define SCALER_DISPCTRL                         0x00000000
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 38/78] drm/vc4: hdmi: Use debugfs private field
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

We're calling vc4_debugfs_add_file with our struct vc4_hdmi pointer set
in the private field, but we don't use that field and go through the
main struct vc4_dev to get it.

Let's use the private field directly, that will save us some trouble
later on.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d9e48fbd7519..f6b4a05a7d96 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -183,9 +183,7 @@ static const struct debugfs_reg32 hd_regs[] = {
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *hdmi = node->info_ent->data;
 	struct drm_printer p = drm_seq_file_printer(m);
 
 	drm_print_regset32(&p, &hdmi->hdmi_regset);
-- 
git-series 0.9.1

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

* [PATCH v4 38/78] drm/vc4: hdmi: Use debugfs private field
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

We're calling vc4_debugfs_add_file with our struct vc4_hdmi pointer set
in the private field, but we don't use that field and go through the
main struct vc4_dev to get it.

Let's use the private field directly, that will save us some trouble
later on.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d9e48fbd7519..f6b4a05a7d96 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -183,9 +183,7 @@ static const struct debugfs_reg32 hd_regs[] = {
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *hdmi = node->info_ent->data;
 	struct drm_printer p = drm_seq_file_printer(m);
 
 	drm_print_regset32(&p, &hdmi->hdmi_regset);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 38/78] drm/vc4: hdmi: Use debugfs private field
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

We're calling vc4_debugfs_add_file with our struct vc4_hdmi pointer set
in the private field, but we don't use that field and go through the
main struct vc4_dev to get it.

Let's use the private field directly, that will save us some trouble
later on.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d9e48fbd7519..f6b4a05a7d96 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -183,9 +183,7 @@ static const struct debugfs_reg32 hd_regs[] = {
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
-	struct drm_device *dev = node->minor->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *hdmi = node->info_ent->data;
 	struct drm_printer p = drm_seq_file_printer(m);
 
 	drm_print_regset32(&p, &hdmi->hdmi_regset);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 39/78] drm/vc4: hdmi: Move structure to header
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

We will need to share the vc4_hdmi and related structures with multiple
files, so let's create a header for it.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 76 +-------------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 86 +++++++++++++++++++++++++++++++++++-
 2 files changed, 87 insertions(+), 75 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f6b4a05a7d96..db79e0d88625 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -49,87 +49,13 @@
 #include <sound/soc.h>
 #include "media/cec.h"
 #include "vc4_drv.h"
+#include "vc4_hdmi.h"
 #include "vc4_regs.h"
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
-/* HDMI audio information */
-struct vc4_hdmi_audio {
-	struct snd_soc_card card;
-	struct snd_soc_dai_link link;
-	struct snd_soc_dai_link_component cpu;
-	struct snd_soc_dai_link_component codec;
-	struct snd_soc_dai_link_component platform;
-	int samplerate;
-	int channels;
-	struct snd_dmaengine_dai_dma_data dma_data;
-	struct snd_pcm_substream *substream;
-};
-
-/* General HDMI hardware state. */
-struct vc4_hdmi {
-	struct platform_device *pdev;
-
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	struct vc4_hdmi_audio audio;
-
-	struct i2c_adapter *ddc;
-	void __iomem *hdmicore_regs;
-	void __iomem *hd_regs;
-	int hpd_gpio;
-	bool hpd_active_low;
-
-	struct cec_adapter *cec_adap;
-	struct cec_msg cec_rx_msg;
-	bool cec_tx_ok;
-	bool cec_irq_was_rx;
-
-	struct clk *pixel_clock;
-	struct clk *hsm_clock;
-
-	struct debugfs_regset32 hdmi_regset;
-	struct debugfs_regset32 hd_regset;
-};
-
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
-
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 static const struct debugfs_reg32 hdmi_regs[] = {
 	VC4_REG32(VC4_HDMI_CORE_REV),
 	VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
new file mode 100644
index 000000000000..5ec5d1f6b1e6
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -0,0 +1,86 @@
+#ifndef _VC4_HDMI_H_
+#define _VC4_HDMI_H_
+
+#include <drm/drm_connector.h>
+#include <media/cec.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
+
+#include "vc4_drv.h"
+
+/* HDMI audio information */
+struct vc4_hdmi_audio {
+	struct snd_soc_card card;
+	struct snd_soc_dai_link link;
+	struct snd_soc_dai_link_component cpu;
+	struct snd_soc_dai_link_component codec;
+	struct snd_soc_dai_link_component platform;
+	int samplerate;
+	int channels;
+	struct snd_dmaengine_dai_dma_data dma_data;
+	struct snd_pcm_substream *substream;
+};
+
+/* General HDMI hardware state. */
+struct vc4_hdmi {
+	struct platform_device *pdev;
+
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	struct vc4_hdmi_audio audio;
+
+	struct i2c_adapter *ddc;
+	void __iomem *hdmicore_regs;
+	void __iomem *hd_regs;
+	int hpd_gpio;
+	bool hpd_active_low;
+
+	struct cec_adapter *cec_adap;
+	struct cec_msg cec_rx_msg;
+	bool cec_tx_ok;
+	bool cec_irq_was_rx;
+
+	struct clk *pixel_clock;
+	struct clk *hsm_clock;
+
+	struct debugfs_regset32 hdmi_regset;
+	struct debugfs_regset32 hd_regset;
+};
+
+#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
+#endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1

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

* [PATCH v4 39/78] drm/vc4: hdmi: Move structure to header
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

We will need to share the vc4_hdmi and related structures with multiple
files, so let's create a header for it.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 76 +-------------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 86 +++++++++++++++++++++++++++++++++++-
 2 files changed, 87 insertions(+), 75 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f6b4a05a7d96..db79e0d88625 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -49,87 +49,13 @@
 #include <sound/soc.h>
 #include "media/cec.h"
 #include "vc4_drv.h"
+#include "vc4_hdmi.h"
 #include "vc4_regs.h"
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
-/* HDMI audio information */
-struct vc4_hdmi_audio {
-	struct snd_soc_card card;
-	struct snd_soc_dai_link link;
-	struct snd_soc_dai_link_component cpu;
-	struct snd_soc_dai_link_component codec;
-	struct snd_soc_dai_link_component platform;
-	int samplerate;
-	int channels;
-	struct snd_dmaengine_dai_dma_data dma_data;
-	struct snd_pcm_substream *substream;
-};
-
-/* General HDMI hardware state. */
-struct vc4_hdmi {
-	struct platform_device *pdev;
-
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	struct vc4_hdmi_audio audio;
-
-	struct i2c_adapter *ddc;
-	void __iomem *hdmicore_regs;
-	void __iomem *hd_regs;
-	int hpd_gpio;
-	bool hpd_active_low;
-
-	struct cec_adapter *cec_adap;
-	struct cec_msg cec_rx_msg;
-	bool cec_tx_ok;
-	bool cec_irq_was_rx;
-
-	struct clk *pixel_clock;
-	struct clk *hsm_clock;
-
-	struct debugfs_regset32 hdmi_regset;
-	struct debugfs_regset32 hd_regset;
-};
-
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
-
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 static const struct debugfs_reg32 hdmi_regs[] = {
 	VC4_REG32(VC4_HDMI_CORE_REV),
 	VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
new file mode 100644
index 000000000000..5ec5d1f6b1e6
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -0,0 +1,86 @@
+#ifndef _VC4_HDMI_H_
+#define _VC4_HDMI_H_
+
+#include <drm/drm_connector.h>
+#include <media/cec.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
+
+#include "vc4_drv.h"
+
+/* HDMI audio information */
+struct vc4_hdmi_audio {
+	struct snd_soc_card card;
+	struct snd_soc_dai_link link;
+	struct snd_soc_dai_link_component cpu;
+	struct snd_soc_dai_link_component codec;
+	struct snd_soc_dai_link_component platform;
+	int samplerate;
+	int channels;
+	struct snd_dmaengine_dai_dma_data dma_data;
+	struct snd_pcm_substream *substream;
+};
+
+/* General HDMI hardware state. */
+struct vc4_hdmi {
+	struct platform_device *pdev;
+
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	struct vc4_hdmi_audio audio;
+
+	struct i2c_adapter *ddc;
+	void __iomem *hdmicore_regs;
+	void __iomem *hd_regs;
+	int hpd_gpio;
+	bool hpd_active_low;
+
+	struct cec_adapter *cec_adap;
+	struct cec_msg cec_rx_msg;
+	bool cec_tx_ok;
+	bool cec_irq_was_rx;
+
+	struct clk *pixel_clock;
+	struct clk *hsm_clock;
+
+	struct debugfs_regset32 hdmi_regset;
+	struct debugfs_regset32 hd_regset;
+};
+
+#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
+#endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 39/78] drm/vc4: hdmi: Move structure to header
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

We will need to share the vc4_hdmi and related structures with multiple
files, so let's create a header for it.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 76 +-------------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 86 +++++++++++++++++++++++++++++++++++-
 2 files changed, 87 insertions(+), 75 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f6b4a05a7d96..db79e0d88625 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -49,87 +49,13 @@
 #include <sound/soc.h>
 #include "media/cec.h"
 #include "vc4_drv.h"
+#include "vc4_hdmi.h"
 #include "vc4_regs.h"
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
-/* HDMI audio information */
-struct vc4_hdmi_audio {
-	struct snd_soc_card card;
-	struct snd_soc_dai_link link;
-	struct snd_soc_dai_link_component cpu;
-	struct snd_soc_dai_link_component codec;
-	struct snd_soc_dai_link_component platform;
-	int samplerate;
-	int channels;
-	struct snd_dmaengine_dai_dma_data dma_data;
-	struct snd_pcm_substream *substream;
-};
-
-/* General HDMI hardware state. */
-struct vc4_hdmi {
-	struct platform_device *pdev;
-
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	struct vc4_hdmi_audio audio;
-
-	struct i2c_adapter *ddc;
-	void __iomem *hdmicore_regs;
-	void __iomem *hd_regs;
-	int hpd_gpio;
-	bool hpd_active_low;
-
-	struct cec_adapter *cec_adap;
-	struct cec_msg cec_rx_msg;
-	bool cec_tx_ok;
-	bool cec_irq_was_rx;
-
-	struct clk *pixel_clock;
-	struct clk *hsm_clock;
-
-	struct debugfs_regset32 hdmi_regset;
-	struct debugfs_regset32 hd_regset;
-};
-
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
-
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 static const struct debugfs_reg32 hdmi_regs[] = {
 	VC4_REG32(VC4_HDMI_CORE_REV),
 	VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
new file mode 100644
index 000000000000..5ec5d1f6b1e6
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -0,0 +1,86 @@
+#ifndef _VC4_HDMI_H_
+#define _VC4_HDMI_H_
+
+#include <drm/drm_connector.h>
+#include <media/cec.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/soc.h>
+
+#include "vc4_drv.h"
+
+/* HDMI audio information */
+struct vc4_hdmi_audio {
+	struct snd_soc_card card;
+	struct snd_soc_dai_link link;
+	struct snd_soc_dai_link_component cpu;
+	struct snd_soc_dai_link_component codec;
+	struct snd_soc_dai_link_component platform;
+	int samplerate;
+	int channels;
+	struct snd_dmaengine_dai_dma_data dma_data;
+	struct snd_pcm_substream *substream;
+};
+
+/* General HDMI hardware state. */
+struct vc4_hdmi {
+	struct platform_device *pdev;
+
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	struct vc4_hdmi_audio audio;
+
+	struct i2c_adapter *ddc;
+	void __iomem *hdmicore_regs;
+	void __iomem *hd_regs;
+	int hpd_gpio;
+	bool hpd_active_low;
+
+	struct cec_adapter *cec_adap;
+	struct cec_msg cec_rx_msg;
+	bool cec_tx_ok;
+	bool cec_irq_was_rx;
+
+	struct clk *pixel_clock;
+	struct clk *hsm_clock;
+
+	struct debugfs_regset32 hdmi_regset;
+	struct debugfs_regset32 hd_regset;
+};
+
+#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
+#endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

the vc4_hdmi driver has some custom structures to hold the data it needs to
associate with the drm_encoder and drm_connector structures.

However, it allocates them separately from the vc4_hdmi structure which
makes it more complicated than it needs to be.

Move those structures to be contained by vc4_hdmi and update the code
accordingly.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
 2 files changed, 72 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index db79e0d88625..1e2214f24ed7 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 	.get_modes = vc4_hdmi_connector_get_modes,
 };
 
-static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
-						     struct drm_encoder *encoder,
-						     struct i2c_adapter *ddc)
+static int vc4_hdmi_connector_init(struct drm_device *dev,
+				   struct vc4_hdmi *vc4_hdmi,
+				   struct i2c_adapter *ddc)
 {
-	struct drm_connector *connector;
-	struct vc4_hdmi_connector *hdmi_connector;
+	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
+	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
-				      GFP_KERNEL);
-	if (!hdmi_connector)
-		return ERR_PTR(-ENOMEM);
-	connector = &hdmi_connector->base;
-
 	hdmi_connector->encoder = encoder;
 
 	drm_connector_init_with_ddc(dev, connector,
@@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 	/* Create and attach TV margin props to this connector. */
 	ret = drm_mode_create_tv_margin_properties(dev);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
 	drm_connector_attach_tv_margin_properties(connector);
 
@@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 
 	drm_connector_attach_encoder(connector, encoder);
 
-	return connector;
+	return 0;
 }
 
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
@@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
 	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector_state *cstate = hdmi->connector->state;
+	struct drm_connector *connector = &hdmi->connector.base;
+	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	union hdmi_infoframe frame;
 	int ret;
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       hdmi->connector, mode);
+						       connector, mode);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
 	}
 
 	drm_hdmi_avi_infoframe_quant_range(&frame.avi,
-					   hdmi->connector, mode,
+					   connector, mode,
 					   vc4_encoder->limited_rgb_range ?
 					   HDMI_QUANTIZATION_RANGE_LIMITED :
 					   HDMI_QUANTIZATION_RANGE_FULL);
@@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 {
-	struct drm_device *drm = hdmi->encoder->dev;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
 	unsigned long n, m;
@@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_connector *connector = &hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
@@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
-	ret = snd_pcm_hw_constraint_eld(substream->runtime,
-					hdmi->connector->eld);
+	ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
 	if (ret)
 		return ret;
 
@@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-	uinfo->count = sizeof(hdmi->connector->eld);
+	uinfo->count = sizeof(connector->eld);
 
 	return 0;
 }
@@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
-	memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
-	       sizeof(hdmi->connector->eld));
+	memcpy(ucontrol->value.bytes.data, connector->eld,
+	       sizeof(connector->eld));
 
 	return 0;
 }
@@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *hdmi;
-	struct vc4_hdmi_encoder *vc4_hdmi_encoder;
+	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
@@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!hdmi)
 		return -ENOMEM;
 
-	vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
-					GFP_KERNEL);
-	if (!vc4_hdmi_encoder)
-		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->encoder = &vc4_hdmi_encoder->base.base;
-
+	encoder = &hdmi->encoder.base.base;
+	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->pdev = pdev;
+
 	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hdmi->hdmicore_regs))
 		return PTR_ERR(hdmi->hdmicore_regs);
@@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 	pm_runtime_enable(dev);
 
-	drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
+	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	hdmi->connector =
-		vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
-	if (IS_ERR(hdmi->connector)) {
-		ret = PTR_ERR(hdmi->connector);
+	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	if (ret)
 		goto err_destroy_encoder;
-	}
+
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 					      vc4, "vc4",
@@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
+	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
 	cec_s_conn_info(hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(hdmi->connector);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
 #endif
 err_destroy_encoder:
-	drm_encoder_cleanup(hdmi->encoder);
+	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
@@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	struct vc4_hdmi *hdmi = vc4->hdmi;
 
 	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(hdmi->connector);
-	drm_encoder_cleanup(hdmi->encoder);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	drm_encoder_cleanup(&hdmi->encoder.base.base);
 
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 5ec5d1f6b1e6..17079a39f1b1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -8,6 +8,36 @@
 
 #include "vc4_drv.h"
 
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
 struct vc4_hdmi {
 	struct platform_device *pdev;
 
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
+	struct vc4_hdmi_encoder encoder;
+	struct vc4_hdmi_connector connector;
 
 	struct vc4_hdmi_audio audio;
 
@@ -53,34 +83,4 @@ struct vc4_hdmi {
 #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
 #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
 
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 #endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1

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

* [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

the vc4_hdmi driver has some custom structures to hold the data it needs to
associate with the drm_encoder and drm_connector structures.

However, it allocates them separately from the vc4_hdmi structure which
makes it more complicated than it needs to be.

Move those structures to be contained by vc4_hdmi and update the code
accordingly.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
 2 files changed, 72 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index db79e0d88625..1e2214f24ed7 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 	.get_modes = vc4_hdmi_connector_get_modes,
 };
 
-static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
-						     struct drm_encoder *encoder,
-						     struct i2c_adapter *ddc)
+static int vc4_hdmi_connector_init(struct drm_device *dev,
+				   struct vc4_hdmi *vc4_hdmi,
+				   struct i2c_adapter *ddc)
 {
-	struct drm_connector *connector;
-	struct vc4_hdmi_connector *hdmi_connector;
+	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
+	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
-				      GFP_KERNEL);
-	if (!hdmi_connector)
-		return ERR_PTR(-ENOMEM);
-	connector = &hdmi_connector->base;
-
 	hdmi_connector->encoder = encoder;
 
 	drm_connector_init_with_ddc(dev, connector,
@@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 	/* Create and attach TV margin props to this connector. */
 	ret = drm_mode_create_tv_margin_properties(dev);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
 	drm_connector_attach_tv_margin_properties(connector);
 
@@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 
 	drm_connector_attach_encoder(connector, encoder);
 
-	return connector;
+	return 0;
 }
 
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
@@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
 	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector_state *cstate = hdmi->connector->state;
+	struct drm_connector *connector = &hdmi->connector.base;
+	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	union hdmi_infoframe frame;
 	int ret;
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       hdmi->connector, mode);
+						       connector, mode);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
 	}
 
 	drm_hdmi_avi_infoframe_quant_range(&frame.avi,
-					   hdmi->connector, mode,
+					   connector, mode,
 					   vc4_encoder->limited_rgb_range ?
 					   HDMI_QUANTIZATION_RANGE_LIMITED :
 					   HDMI_QUANTIZATION_RANGE_FULL);
@@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 {
-	struct drm_device *drm = hdmi->encoder->dev;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
 	unsigned long n, m;
@@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_connector *connector = &hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
@@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
-	ret = snd_pcm_hw_constraint_eld(substream->runtime,
-					hdmi->connector->eld);
+	ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
 	if (ret)
 		return ret;
 
@@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-	uinfo->count = sizeof(hdmi->connector->eld);
+	uinfo->count = sizeof(connector->eld);
 
 	return 0;
 }
@@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
-	memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
-	       sizeof(hdmi->connector->eld));
+	memcpy(ucontrol->value.bytes.data, connector->eld,
+	       sizeof(connector->eld));
 
 	return 0;
 }
@@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *hdmi;
-	struct vc4_hdmi_encoder *vc4_hdmi_encoder;
+	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
@@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!hdmi)
 		return -ENOMEM;
 
-	vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
-					GFP_KERNEL);
-	if (!vc4_hdmi_encoder)
-		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->encoder = &vc4_hdmi_encoder->base.base;
-
+	encoder = &hdmi->encoder.base.base;
+	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->pdev = pdev;
+
 	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hdmi->hdmicore_regs))
 		return PTR_ERR(hdmi->hdmicore_regs);
@@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 	pm_runtime_enable(dev);
 
-	drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
+	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	hdmi->connector =
-		vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
-	if (IS_ERR(hdmi->connector)) {
-		ret = PTR_ERR(hdmi->connector);
+	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	if (ret)
 		goto err_destroy_encoder;
-	}
+
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 					      vc4, "vc4",
@@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
+	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
 	cec_s_conn_info(hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(hdmi->connector);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
 #endif
 err_destroy_encoder:
-	drm_encoder_cleanup(hdmi->encoder);
+	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
@@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	struct vc4_hdmi *hdmi = vc4->hdmi;
 
 	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(hdmi->connector);
-	drm_encoder_cleanup(hdmi->encoder);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	drm_encoder_cleanup(&hdmi->encoder.base.base);
 
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 5ec5d1f6b1e6..17079a39f1b1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -8,6 +8,36 @@
 
 #include "vc4_drv.h"
 
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
 struct vc4_hdmi {
 	struct platform_device *pdev;
 
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
+	struct vc4_hdmi_encoder encoder;
+	struct vc4_hdmi_connector connector;
 
 	struct vc4_hdmi_audio audio;
 
@@ -53,34 +83,4 @@ struct vc4_hdmi {
 #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
 #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
 
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 #endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

the vc4_hdmi driver has some custom structures to hold the data it needs to
associate with the drm_encoder and drm_connector structures.

However, it allocates them separately from the vc4_hdmi structure which
makes it more complicated than it needs to be.

Move those structures to be contained by vc4_hdmi and update the code
accordingly.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
 2 files changed, 72 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index db79e0d88625..1e2214f24ed7 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 	.get_modes = vc4_hdmi_connector_get_modes,
 };
 
-static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
-						     struct drm_encoder *encoder,
-						     struct i2c_adapter *ddc)
+static int vc4_hdmi_connector_init(struct drm_device *dev,
+				   struct vc4_hdmi *vc4_hdmi,
+				   struct i2c_adapter *ddc)
 {
-	struct drm_connector *connector;
-	struct vc4_hdmi_connector *hdmi_connector;
+	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
+	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
-				      GFP_KERNEL);
-	if (!hdmi_connector)
-		return ERR_PTR(-ENOMEM);
-	connector = &hdmi_connector->base;
-
 	hdmi_connector->encoder = encoder;
 
 	drm_connector_init_with_ddc(dev, connector,
@@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 	/* Create and attach TV margin props to this connector. */
 	ret = drm_mode_create_tv_margin_properties(dev);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
 	drm_connector_attach_tv_margin_properties(connector);
 
@@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
 
 	drm_connector_attach_encoder(connector, encoder);
 
-	return connector;
+	return 0;
 }
 
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
@@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
 	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector_state *cstate = hdmi->connector->state;
+	struct drm_connector *connector = &hdmi->connector.base;
+	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	union hdmi_infoframe frame;
 	int ret;
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       hdmi->connector, mode);
+						       connector, mode);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
 	}
 
 	drm_hdmi_avi_infoframe_quant_range(&frame.avi,
-					   hdmi->connector, mode,
+					   connector, mode,
 					   vc4_encoder->limited_rgb_range ?
 					   HDMI_QUANTIZATION_RANGE_LIMITED :
 					   HDMI_QUANTIZATION_RANGE_FULL);
@@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 {
-	struct drm_device *drm = hdmi->encoder->dev;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
 	unsigned long n, m;
@@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_connector *connector = &hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
@@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
-	ret = snd_pcm_hw_constraint_eld(substream->runtime,
-					hdmi->connector->eld);
+	ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
 	if (ret)
 		return ret;
 
@@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 {
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct device *dev = &hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
@@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = hdmi->encoder;
+	struct drm_encoder *encoder = &hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-	uinfo->count = sizeof(hdmi->connector->eld);
+	uinfo->count = sizeof(connector->eld);
 
 	return 0;
 }
@@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &hdmi->connector.base;
 
-	memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
-	       sizeof(hdmi->connector->eld));
+	memcpy(ucontrol->value.bytes.data, connector->eld,
+	       sizeof(connector->eld));
 
 	return 0;
 }
@@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *hdmi;
-	struct vc4_hdmi_encoder *vc4_hdmi_encoder;
+	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
@@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!hdmi)
 		return -ENOMEM;
 
-	vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
-					GFP_KERNEL);
-	if (!vc4_hdmi_encoder)
-		return -ENOMEM;
-	vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->encoder = &vc4_hdmi_encoder->base.base;
-
+	encoder = &hdmi->encoder.base.base;
+	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	hdmi->pdev = pdev;
+
 	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(hdmi->hdmicore_regs))
 		return PTR_ERR(hdmi->hdmicore_regs);
@@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 	pm_runtime_enable(dev);
 
-	drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
-	drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
+	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	hdmi->connector =
-		vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
-	if (IS_ERR(hdmi->connector)) {
-		ret = PTR_ERR(hdmi->connector);
+	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	if (ret)
 		goto err_destroy_encoder;
-	}
+
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 					      vc4, "vc4",
@@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
+	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
 	cec_s_conn_info(hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(hdmi->connector);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
 #endif
 err_destroy_encoder:
-	drm_encoder_cleanup(hdmi->encoder);
+	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
@@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	struct vc4_hdmi *hdmi = vc4->hdmi;
 
 	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(hdmi->connector);
-	drm_encoder_cleanup(hdmi->encoder);
+	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	drm_encoder_cleanup(&hdmi->encoder.base.base);
 
 	clk_disable_unprepare(hdmi->hsm_clock);
 	pm_runtime_disable(dev);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 5ec5d1f6b1e6..17079a39f1b1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -8,6 +8,36 @@
 
 #include "vc4_drv.h"
 
+/* VC4 HDMI encoder KMS struct */
+struct vc4_hdmi_encoder {
+	struct vc4_encoder base;
+	bool hdmi_monitor;
+	bool limited_rgb_range;
+};
+
+static inline struct vc4_hdmi_encoder *
+to_vc4_hdmi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
+}
+
+/* VC4 HDMI connector KMS struct */
+struct vc4_hdmi_connector {
+	struct drm_connector base;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_hdmi_connector *
+to_vc4_hdmi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_hdmi_connector, base);
+}
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
 struct vc4_hdmi {
 	struct platform_device *pdev;
 
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
+	struct vc4_hdmi_encoder encoder;
+	struct vc4_hdmi_connector connector;
 
 	struct vc4_hdmi_audio audio;
 
@@ -53,34 +83,4 @@ struct vc4_hdmi {
 #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
 #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
 
-/* VC4 HDMI encoder KMS struct */
-struct vc4_hdmi_encoder {
-	struct vc4_encoder base;
-	bool hdmi_monitor;
-	bool limited_rgb_range;
-};
-
-static inline struct vc4_hdmi_encoder *
-to_vc4_hdmi_encoder(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
-}
-
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 #endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 41/78] drm/vc4: hdmi: Remove DDC argument to connector_init
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Now that we are passing the vc4_hdmi structure to the connector init
function, we can simply use the pointer in that structure instead of
having the pointer as an argument.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1e2214f24ed7..f0fed167149c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -192,8 +192,7 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 };
 
 static int vc4_hdmi_connector_init(struct drm_device *dev,
-				   struct vc4_hdmi *vc4_hdmi,
-				   struct i2c_adapter *ddc)
+				   struct vc4_hdmi *vc4_hdmi)
 {
 	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
 	struct drm_connector *connector = &hdmi_connector->base;
@@ -205,7 +204,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 	drm_connector_init_with_ddc(dev, connector,
 				    &vc4_hdmi_connector_funcs,
 				    DRM_MODE_CONNECTOR_HDMIA,
-				    ddc);
+				    vc4_hdmi->ddc);
 	drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
 	/* Create and attach TV margin props to this connector. */
@@ -1323,7 +1322,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	ret = vc4_hdmi_connector_init(drm, hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
-- 
git-series 0.9.1

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

* [PATCH v4 41/78] drm/vc4: hdmi: Remove DDC argument to connector_init
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that we are passing the vc4_hdmi structure to the connector init
function, we can simply use the pointer in that structure instead of
having the pointer as an argument.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1e2214f24ed7..f0fed167149c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -192,8 +192,7 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 };
 
 static int vc4_hdmi_connector_init(struct drm_device *dev,
-				   struct vc4_hdmi *vc4_hdmi,
-				   struct i2c_adapter *ddc)
+				   struct vc4_hdmi *vc4_hdmi)
 {
 	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
 	struct drm_connector *connector = &hdmi_connector->base;
@@ -205,7 +204,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 	drm_connector_init_with_ddc(dev, connector,
 				    &vc4_hdmi_connector_funcs,
 				    DRM_MODE_CONNECTOR_HDMIA,
-				    ddc);
+				    vc4_hdmi->ddc);
 	drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
 	/* Create and attach TV margin props to this connector. */
@@ -1323,7 +1322,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	ret = vc4_hdmi_connector_init(drm, hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 41/78] drm/vc4: hdmi: Remove DDC argument to connector_init
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that we are passing the vc4_hdmi structure to the connector init
function, we can simply use the pointer in that structure instead of
having the pointer as an argument.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1e2214f24ed7..f0fed167149c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -192,8 +192,7 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 };
 
 static int vc4_hdmi_connector_init(struct drm_device *dev,
-				   struct vc4_hdmi *vc4_hdmi,
-				   struct i2c_adapter *ddc)
+				   struct vc4_hdmi *vc4_hdmi)
 {
 	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
 	struct drm_connector *connector = &hdmi_connector->base;
@@ -205,7 +204,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 	drm_connector_init_with_ddc(dev, connector,
 				    &vc4_hdmi_connector_funcs,
 				    DRM_MODE_CONNECTOR_HDMIA,
-				    ddc);
+				    vc4_hdmi->ddc);
 	drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
 	/* Create and attach TV margin props to this connector. */
@@ -1323,7 +1322,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
+	ret = vc4_hdmi_connector_init(drm, hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 42/78] drm/vc4: hdmi: Rename hdmi to vc4_hdmi
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The driver isn't consistent with the name given to the vc4_hdmi
structure pointer in its functions. Make sure to use a consistent name.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 283 +++++++++++++++++-----------------
 1 file changed, 142 insertions(+), 141 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f0fed167149c..5b7202f97883 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -109,11 +109,11 @@ static const struct debugfs_reg32 hd_regs[] = {
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
-	struct vc4_hdmi *hdmi = node->info_ent->data;
+	struct vc4_hdmi *vc4_hdmi = node->info_ent->data;
 	struct drm_printer p = drm_seq_file_printer(m);
 
-	drm_print_regset32(&p, &hdmi->hdmi_regset);
-	drm_print_regset32(&p, &hdmi->hd_regset);
+	drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+	drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 
 	return 0;
 }
@@ -291,8 +291,8 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
@@ -337,7 +337,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 {
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -346,7 +346,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 	frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
 	frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
 	frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
-	frame.audio.channels = hdmi->audio.channels;
+	frame.audio.channels = vc4_hdmi->audio.channels;
 
 	vc4_hdmi_write_infoframe(encoder, &frame);
 }
@@ -361,7 +361,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	int ret;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
@@ -370,9 +370,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	HD_WRITE(VC4_HD_VID_CTL,
 		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
-	clk_disable_unprepare(hdmi->pixel_clock);
+	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
-	ret = pm_runtime_put(&hdmi->pdev->dev);
+	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
 	if (ret < 0)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
@@ -383,7 +383,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
@@ -405,13 +405,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	u32 csc_ctl;
 	int ret;
 
-	ret = pm_runtime_get_sync(&hdmi->pdev->dev);
+	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
 	if (ret < 0) {
 		DRM_ERROR("Failed to retain power domain: %d\n", ret);
 		return;
 	}
 
-	ret = clk_set_rate(hdmi->pixel_clock,
+	ret = clk_set_rate(vc4_hdmi->pixel_clock,
 			   mode->clock * 1000 *
 			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
 	if (ret) {
@@ -419,7 +419,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	ret = clk_prepare_enable(hdmi->pixel_clock);
+	ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
 	if (ret) {
 		DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
 		return;
@@ -439,11 +439,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
 
 	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
+		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
 
-		dev_info(&hdmi->pdev->dev, "HDMI regs before:\n");
-		drm_print_regset32(&p, &hdmi->hdmi_regset);
-		drm_print_regset32(&p, &hdmi->hd_regset);
+		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
+		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
 	HD_WRITE(VC4_HD_VID_CTL, 0);
@@ -518,11 +518,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
+		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
 
-		dev_info(&hdmi->pdev->dev, "HDMI regs after:\n");
-		drm_print_regset32(&p, &hdmi->hdmi_regset);
-		drm_print_regset32(&p, &hdmi->hd_regset);
+		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
+		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
 	HD_WRITE(VC4_HD_VID_CTL,
@@ -621,15 +621,15 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 };
 
 /* HDMI audio codec callbacks */
-static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
-	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
+	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
 	unsigned long n, m;
 
-	rational_best_approximation(hsm_clock, hdmi->audio.samplerate,
+	rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
 				    VC4_HD_MAI_SMP_N_MASK >>
 				    VC4_HD_MAI_SMP_N_SHIFT,
 				    (VC4_HD_MAI_SMP_M_MASK >>
@@ -641,14 +641,14 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 		 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
 }
 
-static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-	u32 samplerate = hdmi->audio.samplerate;
+	u32 samplerate = vc4_hdmi->audio.samplerate;
 	u32 n, cts;
 	u64 tmp;
 
@@ -680,16 +680,16 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
 static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
-	if (hdmi->audio.substream && hdmi->audio.substream != substream)
+	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
 		return -EINVAL;
 
-	hdmi->audio.substream = substream;
+	vc4_hdmi->audio.substream = substream;
 
 	/*
 	 * If the HDMI encoder hasn't probed, or the encoder is
@@ -711,11 +711,11 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
-static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
-	struct device *dev = &hdmi->pdev->dev;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	int ret;
 
@@ -731,14 +731,14 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 
-	if (substream != hdmi->audio.substream)
+	if (substream != vc4_hdmi->audio.substream)
 		return;
 
-	vc4_hdmi_audio_reset(hdmi);
+	vc4_hdmi_audio_reset(vc4_hdmi);
 
-	hdmi->audio.substream = NULL;
+	vc4_hdmi->audio.substream = NULL;
 }
 
 /* HDMI audio codec callbacks */
@@ -746,23 +746,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
-	struct device *dev = &hdmi->pdev->dev;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 audio_packet_config, channel_mask;
 	u32 channel_map, i;
 
-	if (substream != hdmi->audio.substream)
+	if (substream != vc4_hdmi->audio.substream)
 		return -EINVAL;
 
 	dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
 		params_rate(params), params_width(params),
 		params_channels(params));
 
-	hdmi->audio.channels = params_channels(params);
-	hdmi->audio.samplerate = params_rate(params);
+	vc4_hdmi->audio.channels = params_channels(params);
+	vc4_hdmi->audio.samplerate = params_rate(params);
 
 	HD_WRITE(VC4_HD_MAI_CTL,
 		 VC4_HD_MAI_CTL_RESET |
@@ -771,23 +771,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 		 VC4_HD_MAI_CTL_ERRORE |
 		 VC4_HD_MAI_CTL_ERRORF);
 
-	vc4_hdmi_audio_set_mai_clock(hdmi);
+	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
 	audio_packet_config =
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
 		VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
 
-	channel_mask = GENMASK(hdmi->audio.channels - 1, 0);
+	channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
 	audio_packet_config |= VC4_SET_FIELD(channel_mask,
 					     VC4_HDMI_AUDIO_PACKET_CEA_MASK);
 
 	/* Set the MAI threshold.  This logic mimics the firmware's. */
-	if (hdmi->audio.samplerate > 96000) {
+	if (vc4_hdmi->audio.samplerate > 96000) {
 		HD_WRITE(VC4_HD_MAI_THR,
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
-	} else if (hdmi->audio.samplerate > 48000) {
+	} else if (vc4_hdmi->audio.samplerate > 48000) {
 		HD_WRITE(VC4_HD_MAI_THR,
 			 VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
@@ -811,7 +811,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
 	HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
-	vc4_hdmi_set_n_cts(hdmi);
+	vc4_hdmi_set_n_cts(vc4_hdmi);
 
 	return 0;
 }
@@ -819,8 +819,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -831,7 +831,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
 			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
 		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_SET_FIELD(hdmi->audio.channels,
+			 VC4_SET_FIELD(vc4_hdmi->audio.channels,
 				       VC4_HD_MAI_CTL_CHNUM) |
 			 VC4_HD_MAI_CTL_ENABLE);
 		break;
@@ -863,8 +863,8 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 	uinfo->count = sizeof(connector->eld);
@@ -876,8 +876,8 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 
 	memcpy(ucontrol->value.bytes.data, connector->eld,
 	       sizeof(connector->eld));
@@ -946,9 +946,9 @@ static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
 
 static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 
-	snd_soc_dai_init_dma_data(dai, &hdmi->audio.dma_data, NULL);
+	snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL);
 
 	return 0;
 }
@@ -974,11 +974,11 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
 	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
 };
 
-static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
+static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
-	struct snd_soc_dai_link *dai_link = &hdmi->audio.link;
-	struct snd_soc_card *card = &hdmi->audio.card;
-	struct device *dev = &hdmi->pdev->dev;
+	struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
+	struct snd_soc_card *card = &vc4_hdmi->audio.card;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	const __be32 *addr;
 	int ret;
 
@@ -996,9 +996,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
 	addr = of_get_address(dev->of_node, 1, NULL, NULL);
-	hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
-	hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	hdmi->audio.dma_data.maxburst = 2;
+	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
+	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	vc4_hdmi->audio.dma_data.maxburst = 2;
 
 	ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
 	if (ret) {
@@ -1021,9 +1021,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 		return ret;
 	}
 
-	dai_link->cpus		= &hdmi->audio.cpu;
-	dai_link->codecs	= &hdmi->audio.codec;
-	dai_link->platforms	= &hdmi->audio.platform;
+	dai_link->cpus		= &vc4_hdmi->audio.cpu;
+	dai_link->codecs	= &vc4_hdmi->audio.codec;
+	dai_link->platforms	= &vc4_hdmi->audio.platform;
 
 	dai_link->num_cpus	= 1;
 	dai_link->num_codecs	= 1;
@@ -1048,7 +1048,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 	 * now stored in card->drvdata and should be retrieved with
 	 * snd_soc_card_get_drvdata() if needed.
 	 */
-	snd_soc_card_set_drvdata(card, hdmi);
+	snd_soc_card_set_drvdata(card, vc4_hdmi);
 	ret = devm_snd_soc_register_card(dev, card);
 	if (ret)
 		dev_err(dev, "Could not register sound card: %d\n", ret);
@@ -1061,20 +1061,21 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 {
 	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
-
-	if (hdmi->cec_irq_was_rx) {
-		if (hdmi->cec_rx_msg.len)
-			cec_received_msg(hdmi->cec_adap, &hdmi->cec_rx_msg);
-	} else if (hdmi->cec_tx_ok) {
-		cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_OK,
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+
+	if (vc4_hdmi->cec_irq_was_rx) {
+		if (vc4_hdmi->cec_rx_msg.len)
+			cec_received_msg(vc4_hdmi->cec_adap,
+					 &vc4_hdmi->cec_rx_msg);
+	} else if (vc4_hdmi->cec_tx_ok) {
+		cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK,
 				  0, 0, 0, 0);
 	} else {
 		/*
 		 * This CEC implementation makes 1 retry, so if we
 		 * get a NACK, then that means it made 2 attempts.
 		 */
-		cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_NACK,
+		cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK,
 				  0, 2, 0, 0);
 	}
 	return IRQ_HANDLED;
@@ -1100,23 +1101,23 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
 	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
 	if (!(stat & VC4_HDMI_CPU_CEC))
 		return IRQ_NONE;
-	hdmi->cec_rx_msg.len = 0;
+	vc4_hdmi->cec_rx_msg.len = 0;
 	cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
 	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
-	hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
-	if (hdmi->cec_irq_was_rx) {
+	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
+	if (vc4_hdmi->cec_irq_was_rx) {
 		vc4_cec_read_msg(vc4, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 	} else {
-		hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
+		vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
 		cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
 	}
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
@@ -1218,46 +1219,46 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi;
+	struct vc4_hdmi *vc4_hdmi;
 	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
 
-	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
-	if (!hdmi)
+	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+	if (!vc4_hdmi)
 		return -ENOMEM;
 
-	encoder = &hdmi->encoder.base.base;
-	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->pdev = pdev;
+	encoder = &vc4_hdmi->encoder.base.base;
+	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->pdev = pdev;
 
-	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
-	if (IS_ERR(hdmi->hdmicore_regs))
-		return PTR_ERR(hdmi->hdmicore_regs);
+	vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
+	if (IS_ERR(vc4_hdmi->hdmicore_regs))
+		return PTR_ERR(vc4_hdmi->hdmicore_regs);
 
-	hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
-	if (IS_ERR(hdmi->hd_regs))
-		return PTR_ERR(hdmi->hd_regs);
+	vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
+	if (IS_ERR(vc4_hdmi->hd_regs))
+		return PTR_ERR(vc4_hdmi->hd_regs);
 
-	hdmi->hdmi_regset.base = hdmi->hdmicore_regs;
-	hdmi->hdmi_regset.regs = hdmi_regs;
-	hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
-	hdmi->hd_regset.base = hdmi->hd_regs;
-	hdmi->hd_regset.regs = hd_regs;
-	hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
+	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
+	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
+	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
+	vc4_hdmi->hd_regset.regs = hd_regs;
+	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
 
-	hdmi->pixel_clock = devm_clk_get(dev, "pixel");
-	if (IS_ERR(hdmi->pixel_clock)) {
-		ret = PTR_ERR(hdmi->pixel_clock);
+	vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
+	if (IS_ERR(vc4_hdmi->pixel_clock)) {
+		ret = PTR_ERR(vc4_hdmi->pixel_clock);
 		if (ret != -EPROBE_DEFER)
 			DRM_ERROR("Failed to get pixel clock\n");
 		return ret;
 	}
-	hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
-	if (IS_ERR(hdmi->hsm_clock)) {
+	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+	if (IS_ERR(vc4_hdmi->hsm_clock)) {
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
-		return PTR_ERR(hdmi->hsm_clock);
+		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
 
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
@@ -1266,9 +1267,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		return -ENODEV;
 	}
 
-	hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+	vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
 	of_node_put(ddc_node);
-	if (!hdmi->ddc) {
+	if (!vc4_hdmi->ddc) {
 		DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
 		return -EPROBE_DEFER;
 	}
@@ -1277,13 +1278,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	 * needs to be a bit higher than the pixel clock rate
 	 * (generally 148.5Mhz).
 	 */
-	ret = clk_set_rate(hdmi->hsm_clock, HSM_CLOCK_FREQ);
+	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
 		goto err_put_i2c;
 	}
 
-	ret = clk_prepare_enable(hdmi->hsm_clock);
+	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
 	if (ret) {
 		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
 			  ret);
@@ -1296,18 +1297,18 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
 		enum of_gpio_flags hpd_gpio_flags;
 
-		hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
-							 "hpd-gpios", 0,
-							 &hpd_gpio_flags);
-		if (hdmi->hpd_gpio < 0) {
-			ret = hdmi->hpd_gpio;
+		vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
+							     "hpd-gpios", 0,
+							     &hpd_gpio_flags);
+		if (vc4_hdmi->hpd_gpio < 0) {
+			ret = vc4_hdmi->hpd_gpio;
 			goto err_unprepare_hsm;
 		}
 
-		hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
+		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	vc4->hdmi = hdmi;
+	vc4->hdmi = vc4_hdmi;
 
 	/* HDMI core must be enabled. */
 	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
@@ -1322,21 +1323,21 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	ret = vc4_hdmi_connector_init(drm, hdmi);
+	ret = vc4_hdmi_connector_init(drm, vc4_hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
-	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-					      vc4, "vc4",
-					      CEC_CAP_DEFAULTS |
-					      CEC_CAP_CONNECTOR_INFO, 1);
-	ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
+	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+						  vc4, "vc4",
+						  CEC_CAP_DEFAULTS |
+						  CEC_CAP_CONNECTOR_INFO, 1);
+	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
-	cec_s_conn_info(hdmi->cec_adap, &conn_info);
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base);
+	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
 	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
@@ -1355,32 +1356,32 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 					"vc4 hdmi cec", vc4);
 	if (ret)
 		goto err_delete_cec_adap;
-	ret = cec_register_adapter(hdmi->cec_adap, dev);
+	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
 	if (ret < 0)
 		goto err_delete_cec_adap;
 #endif
 
-	ret = vc4_hdmi_audio_init(hdmi);
+	ret = vc4_hdmi_audio_init(vc4_hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
-	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, hdmi);
+	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
 
 	return 0;
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 err_delete_cec_adap:
-	cec_delete_adapter(hdmi->cec_adap);
+	cec_delete_adapter(vc4_hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
 #endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
-	clk_disable_unprepare(hdmi->hsm_clock);
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 err_put_i2c:
-	put_device(&hdmi->ddc->dev);
+	put_device(&vc4_hdmi->ddc->dev);
 
 	return ret;
 }
@@ -1390,16 +1391,16 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
-	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(&hdmi->connector.base);
-	drm_encoder_cleanup(&hdmi->encoder.base.base);
+	cec_unregister_adapter(vc4_hdmi->cec_adap);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-	clk_disable_unprepare(hdmi->hsm_clock);
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 
-	put_device(&hdmi->ddc->dev);
+	put_device(&vc4_hdmi->ddc->dev);
 
 	vc4->hdmi = NULL;
 }
-- 
git-series 0.9.1

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

* [PATCH v4 42/78] drm/vc4: hdmi: Rename hdmi to vc4_hdmi
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The driver isn't consistent with the name given to the vc4_hdmi
structure pointer in its functions. Make sure to use a consistent name.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 283 +++++++++++++++++-----------------
 1 file changed, 142 insertions(+), 141 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f0fed167149c..5b7202f97883 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -109,11 +109,11 @@ static const struct debugfs_reg32 hd_regs[] = {
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
-	struct vc4_hdmi *hdmi = node->info_ent->data;
+	struct vc4_hdmi *vc4_hdmi = node->info_ent->data;
 	struct drm_printer p = drm_seq_file_printer(m);
 
-	drm_print_regset32(&p, &hdmi->hdmi_regset);
-	drm_print_regset32(&p, &hdmi->hd_regset);
+	drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+	drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 
 	return 0;
 }
@@ -291,8 +291,8 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
@@ -337,7 +337,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 {
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -346,7 +346,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 	frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
 	frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
 	frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
-	frame.audio.channels = hdmi->audio.channels;
+	frame.audio.channels = vc4_hdmi->audio.channels;
 
 	vc4_hdmi_write_infoframe(encoder, &frame);
 }
@@ -361,7 +361,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	int ret;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
@@ -370,9 +370,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	HD_WRITE(VC4_HD_VID_CTL,
 		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
-	clk_disable_unprepare(hdmi->pixel_clock);
+	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
-	ret = pm_runtime_put(&hdmi->pdev->dev);
+	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
 	if (ret < 0)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
@@ -383,7 +383,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
@@ -405,13 +405,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	u32 csc_ctl;
 	int ret;
 
-	ret = pm_runtime_get_sync(&hdmi->pdev->dev);
+	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
 	if (ret < 0) {
 		DRM_ERROR("Failed to retain power domain: %d\n", ret);
 		return;
 	}
 
-	ret = clk_set_rate(hdmi->pixel_clock,
+	ret = clk_set_rate(vc4_hdmi->pixel_clock,
 			   mode->clock * 1000 *
 			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
 	if (ret) {
@@ -419,7 +419,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	ret = clk_prepare_enable(hdmi->pixel_clock);
+	ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
 	if (ret) {
 		DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
 		return;
@@ -439,11 +439,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
 
 	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
+		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
 
-		dev_info(&hdmi->pdev->dev, "HDMI regs before:\n");
-		drm_print_regset32(&p, &hdmi->hdmi_regset);
-		drm_print_regset32(&p, &hdmi->hd_regset);
+		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
+		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
 	HD_WRITE(VC4_HD_VID_CTL, 0);
@@ -518,11 +518,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
+		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
 
-		dev_info(&hdmi->pdev->dev, "HDMI regs after:\n");
-		drm_print_regset32(&p, &hdmi->hdmi_regset);
-		drm_print_regset32(&p, &hdmi->hd_regset);
+		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
+		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
 	HD_WRITE(VC4_HD_VID_CTL,
@@ -621,15 +621,15 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 };
 
 /* HDMI audio codec callbacks */
-static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
-	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
+	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
 	unsigned long n, m;
 
-	rational_best_approximation(hsm_clock, hdmi->audio.samplerate,
+	rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
 				    VC4_HD_MAI_SMP_N_MASK >>
 				    VC4_HD_MAI_SMP_N_SHIFT,
 				    (VC4_HD_MAI_SMP_M_MASK >>
@@ -641,14 +641,14 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 		 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
 }
 
-static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-	u32 samplerate = hdmi->audio.samplerate;
+	u32 samplerate = vc4_hdmi->audio.samplerate;
 	u32 n, cts;
 	u64 tmp;
 
@@ -680,16 +680,16 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
 static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
-	if (hdmi->audio.substream && hdmi->audio.substream != substream)
+	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
 		return -EINVAL;
 
-	hdmi->audio.substream = substream;
+	vc4_hdmi->audio.substream = substream;
 
 	/*
 	 * If the HDMI encoder hasn't probed, or the encoder is
@@ -711,11 +711,11 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
-static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
-	struct device *dev = &hdmi->pdev->dev;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	int ret;
 
@@ -731,14 +731,14 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 
-	if (substream != hdmi->audio.substream)
+	if (substream != vc4_hdmi->audio.substream)
 		return;
 
-	vc4_hdmi_audio_reset(hdmi);
+	vc4_hdmi_audio_reset(vc4_hdmi);
 
-	hdmi->audio.substream = NULL;
+	vc4_hdmi->audio.substream = NULL;
 }
 
 /* HDMI audio codec callbacks */
@@ -746,23 +746,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
-	struct device *dev = &hdmi->pdev->dev;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 audio_packet_config, channel_mask;
 	u32 channel_map, i;
 
-	if (substream != hdmi->audio.substream)
+	if (substream != vc4_hdmi->audio.substream)
 		return -EINVAL;
 
 	dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
 		params_rate(params), params_width(params),
 		params_channels(params));
 
-	hdmi->audio.channels = params_channels(params);
-	hdmi->audio.samplerate = params_rate(params);
+	vc4_hdmi->audio.channels = params_channels(params);
+	vc4_hdmi->audio.samplerate = params_rate(params);
 
 	HD_WRITE(VC4_HD_MAI_CTL,
 		 VC4_HD_MAI_CTL_RESET |
@@ -771,23 +771,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 		 VC4_HD_MAI_CTL_ERRORE |
 		 VC4_HD_MAI_CTL_ERRORF);
 
-	vc4_hdmi_audio_set_mai_clock(hdmi);
+	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
 	audio_packet_config =
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
 		VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
 
-	channel_mask = GENMASK(hdmi->audio.channels - 1, 0);
+	channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
 	audio_packet_config |= VC4_SET_FIELD(channel_mask,
 					     VC4_HDMI_AUDIO_PACKET_CEA_MASK);
 
 	/* Set the MAI threshold.  This logic mimics the firmware's. */
-	if (hdmi->audio.samplerate > 96000) {
+	if (vc4_hdmi->audio.samplerate > 96000) {
 		HD_WRITE(VC4_HD_MAI_THR,
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
-	} else if (hdmi->audio.samplerate > 48000) {
+	} else if (vc4_hdmi->audio.samplerate > 48000) {
 		HD_WRITE(VC4_HD_MAI_THR,
 			 VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
@@ -811,7 +811,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
 	HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
-	vc4_hdmi_set_n_cts(hdmi);
+	vc4_hdmi_set_n_cts(vc4_hdmi);
 
 	return 0;
 }
@@ -819,8 +819,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -831,7 +831,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
 			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
 		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_SET_FIELD(hdmi->audio.channels,
+			 VC4_SET_FIELD(vc4_hdmi->audio.channels,
 				       VC4_HD_MAI_CTL_CHNUM) |
 			 VC4_HD_MAI_CTL_ENABLE);
 		break;
@@ -863,8 +863,8 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 	uinfo->count = sizeof(connector->eld);
@@ -876,8 +876,8 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 
 	memcpy(ucontrol->value.bytes.data, connector->eld,
 	       sizeof(connector->eld));
@@ -946,9 +946,9 @@ static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
 
 static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 
-	snd_soc_dai_init_dma_data(dai, &hdmi->audio.dma_data, NULL);
+	snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL);
 
 	return 0;
 }
@@ -974,11 +974,11 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
 	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
 };
 
-static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
+static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
-	struct snd_soc_dai_link *dai_link = &hdmi->audio.link;
-	struct snd_soc_card *card = &hdmi->audio.card;
-	struct device *dev = &hdmi->pdev->dev;
+	struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
+	struct snd_soc_card *card = &vc4_hdmi->audio.card;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	const __be32 *addr;
 	int ret;
 
@@ -996,9 +996,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
 	addr = of_get_address(dev->of_node, 1, NULL, NULL);
-	hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
-	hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	hdmi->audio.dma_data.maxburst = 2;
+	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
+	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	vc4_hdmi->audio.dma_data.maxburst = 2;
 
 	ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
 	if (ret) {
@@ -1021,9 +1021,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 		return ret;
 	}
 
-	dai_link->cpus		= &hdmi->audio.cpu;
-	dai_link->codecs	= &hdmi->audio.codec;
-	dai_link->platforms	= &hdmi->audio.platform;
+	dai_link->cpus		= &vc4_hdmi->audio.cpu;
+	dai_link->codecs	= &vc4_hdmi->audio.codec;
+	dai_link->platforms	= &vc4_hdmi->audio.platform;
 
 	dai_link->num_cpus	= 1;
 	dai_link->num_codecs	= 1;
@@ -1048,7 +1048,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 	 * now stored in card->drvdata and should be retrieved with
 	 * snd_soc_card_get_drvdata() if needed.
 	 */
-	snd_soc_card_set_drvdata(card, hdmi);
+	snd_soc_card_set_drvdata(card, vc4_hdmi);
 	ret = devm_snd_soc_register_card(dev, card);
 	if (ret)
 		dev_err(dev, "Could not register sound card: %d\n", ret);
@@ -1061,20 +1061,21 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 {
 	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
-
-	if (hdmi->cec_irq_was_rx) {
-		if (hdmi->cec_rx_msg.len)
-			cec_received_msg(hdmi->cec_adap, &hdmi->cec_rx_msg);
-	} else if (hdmi->cec_tx_ok) {
-		cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_OK,
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+
+	if (vc4_hdmi->cec_irq_was_rx) {
+		if (vc4_hdmi->cec_rx_msg.len)
+			cec_received_msg(vc4_hdmi->cec_adap,
+					 &vc4_hdmi->cec_rx_msg);
+	} else if (vc4_hdmi->cec_tx_ok) {
+		cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK,
 				  0, 0, 0, 0);
 	} else {
 		/*
 		 * This CEC implementation makes 1 retry, so if we
 		 * get a NACK, then that means it made 2 attempts.
 		 */
-		cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_NACK,
+		cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK,
 				  0, 2, 0, 0);
 	}
 	return IRQ_HANDLED;
@@ -1100,23 +1101,23 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
 	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
 	if (!(stat & VC4_HDMI_CPU_CEC))
 		return IRQ_NONE;
-	hdmi->cec_rx_msg.len = 0;
+	vc4_hdmi->cec_rx_msg.len = 0;
 	cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
 	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
-	hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
-	if (hdmi->cec_irq_was_rx) {
+	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
+	if (vc4_hdmi->cec_irq_was_rx) {
 		vc4_cec_read_msg(vc4, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 	} else {
-		hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
+		vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
 		cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
 	}
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
@@ -1218,46 +1219,46 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi;
+	struct vc4_hdmi *vc4_hdmi;
 	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
 
-	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
-	if (!hdmi)
+	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+	if (!vc4_hdmi)
 		return -ENOMEM;
 
-	encoder = &hdmi->encoder.base.base;
-	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->pdev = pdev;
+	encoder = &vc4_hdmi->encoder.base.base;
+	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->pdev = pdev;
 
-	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
-	if (IS_ERR(hdmi->hdmicore_regs))
-		return PTR_ERR(hdmi->hdmicore_regs);
+	vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
+	if (IS_ERR(vc4_hdmi->hdmicore_regs))
+		return PTR_ERR(vc4_hdmi->hdmicore_regs);
 
-	hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
-	if (IS_ERR(hdmi->hd_regs))
-		return PTR_ERR(hdmi->hd_regs);
+	vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
+	if (IS_ERR(vc4_hdmi->hd_regs))
+		return PTR_ERR(vc4_hdmi->hd_regs);
 
-	hdmi->hdmi_regset.base = hdmi->hdmicore_regs;
-	hdmi->hdmi_regset.regs = hdmi_regs;
-	hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
-	hdmi->hd_regset.base = hdmi->hd_regs;
-	hdmi->hd_regset.regs = hd_regs;
-	hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
+	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
+	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
+	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
+	vc4_hdmi->hd_regset.regs = hd_regs;
+	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
 
-	hdmi->pixel_clock = devm_clk_get(dev, "pixel");
-	if (IS_ERR(hdmi->pixel_clock)) {
-		ret = PTR_ERR(hdmi->pixel_clock);
+	vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
+	if (IS_ERR(vc4_hdmi->pixel_clock)) {
+		ret = PTR_ERR(vc4_hdmi->pixel_clock);
 		if (ret != -EPROBE_DEFER)
 			DRM_ERROR("Failed to get pixel clock\n");
 		return ret;
 	}
-	hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
-	if (IS_ERR(hdmi->hsm_clock)) {
+	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+	if (IS_ERR(vc4_hdmi->hsm_clock)) {
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
-		return PTR_ERR(hdmi->hsm_clock);
+		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
 
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
@@ -1266,9 +1267,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		return -ENODEV;
 	}
 
-	hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+	vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
 	of_node_put(ddc_node);
-	if (!hdmi->ddc) {
+	if (!vc4_hdmi->ddc) {
 		DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
 		return -EPROBE_DEFER;
 	}
@@ -1277,13 +1278,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	 * needs to be a bit higher than the pixel clock rate
 	 * (generally 148.5Mhz).
 	 */
-	ret = clk_set_rate(hdmi->hsm_clock, HSM_CLOCK_FREQ);
+	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
 		goto err_put_i2c;
 	}
 
-	ret = clk_prepare_enable(hdmi->hsm_clock);
+	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
 	if (ret) {
 		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
 			  ret);
@@ -1296,18 +1297,18 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
 		enum of_gpio_flags hpd_gpio_flags;
 
-		hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
-							 "hpd-gpios", 0,
-							 &hpd_gpio_flags);
-		if (hdmi->hpd_gpio < 0) {
-			ret = hdmi->hpd_gpio;
+		vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
+							     "hpd-gpios", 0,
+							     &hpd_gpio_flags);
+		if (vc4_hdmi->hpd_gpio < 0) {
+			ret = vc4_hdmi->hpd_gpio;
 			goto err_unprepare_hsm;
 		}
 
-		hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
+		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	vc4->hdmi = hdmi;
+	vc4->hdmi = vc4_hdmi;
 
 	/* HDMI core must be enabled. */
 	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
@@ -1322,21 +1323,21 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	ret = vc4_hdmi_connector_init(drm, hdmi);
+	ret = vc4_hdmi_connector_init(drm, vc4_hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
-	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-					      vc4, "vc4",
-					      CEC_CAP_DEFAULTS |
-					      CEC_CAP_CONNECTOR_INFO, 1);
-	ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
+	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+						  vc4, "vc4",
+						  CEC_CAP_DEFAULTS |
+						  CEC_CAP_CONNECTOR_INFO, 1);
+	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
-	cec_s_conn_info(hdmi->cec_adap, &conn_info);
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base);
+	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
 	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
@@ -1355,32 +1356,32 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 					"vc4 hdmi cec", vc4);
 	if (ret)
 		goto err_delete_cec_adap;
-	ret = cec_register_adapter(hdmi->cec_adap, dev);
+	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
 	if (ret < 0)
 		goto err_delete_cec_adap;
 #endif
 
-	ret = vc4_hdmi_audio_init(hdmi);
+	ret = vc4_hdmi_audio_init(vc4_hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
-	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, hdmi);
+	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
 
 	return 0;
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 err_delete_cec_adap:
-	cec_delete_adapter(hdmi->cec_adap);
+	cec_delete_adapter(vc4_hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
 #endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
-	clk_disable_unprepare(hdmi->hsm_clock);
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 err_put_i2c:
-	put_device(&hdmi->ddc->dev);
+	put_device(&vc4_hdmi->ddc->dev);
 
 	return ret;
 }
@@ -1390,16 +1391,16 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
-	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(&hdmi->connector.base);
-	drm_encoder_cleanup(&hdmi->encoder.base.base);
+	cec_unregister_adapter(vc4_hdmi->cec_adap);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-	clk_disable_unprepare(hdmi->hsm_clock);
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 
-	put_device(&hdmi->ddc->dev);
+	put_device(&vc4_hdmi->ddc->dev);
 
 	vc4->hdmi = NULL;
 }
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 42/78] drm/vc4: hdmi: Rename hdmi to vc4_hdmi
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The driver isn't consistent with the name given to the vc4_hdmi
structure pointer in its functions. Make sure to use a consistent name.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 283 +++++++++++++++++-----------------
 1 file changed, 142 insertions(+), 141 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f0fed167149c..5b7202f97883 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -109,11 +109,11 @@ static const struct debugfs_reg32 hd_regs[] = {
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
-	struct vc4_hdmi *hdmi = node->info_ent->data;
+	struct vc4_hdmi *vc4_hdmi = node->info_ent->data;
 	struct drm_printer p = drm_seq_file_printer(m);
 
-	drm_print_regset32(&p, &hdmi->hdmi_regset);
-	drm_print_regset32(&p, &hdmi->hd_regset);
+	drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+	drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 
 	return 0;
 }
@@ -291,8 +291,8 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct vc4_dev *vc4 = encoder->dev->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
@@ -337,7 +337,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 {
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -346,7 +346,7 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 	frame.audio.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
 	frame.audio.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
 	frame.audio.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
-	frame.audio.channels = hdmi->audio.channels;
+	frame.audio.channels = vc4_hdmi->audio.channels;
 
 	vc4_hdmi_write_infoframe(encoder, &frame);
 }
@@ -361,7 +361,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	int ret;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
@@ -370,9 +370,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	HD_WRITE(VC4_HD_VID_CTL,
 		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
-	clk_disable_unprepare(hdmi->pixel_clock);
+	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
-	ret = pm_runtime_put(&hdmi->pdev->dev);
+	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
 	if (ret < 0)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
@@ -383,7 +383,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
@@ -405,13 +405,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	u32 csc_ctl;
 	int ret;
 
-	ret = pm_runtime_get_sync(&hdmi->pdev->dev);
+	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
 	if (ret < 0) {
 		DRM_ERROR("Failed to retain power domain: %d\n", ret);
 		return;
 	}
 
-	ret = clk_set_rate(hdmi->pixel_clock,
+	ret = clk_set_rate(vc4_hdmi->pixel_clock,
 			   mode->clock * 1000 *
 			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
 	if (ret) {
@@ -419,7 +419,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	ret = clk_prepare_enable(hdmi->pixel_clock);
+	ret = clk_prepare_enable(vc4_hdmi->pixel_clock);
 	if (ret) {
 		DRM_ERROR("Failed to turn on pixel clock: %d\n", ret);
 		return;
@@ -439,11 +439,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
 
 	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
+		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
 
-		dev_info(&hdmi->pdev->dev, "HDMI regs before:\n");
-		drm_print_regset32(&p, &hdmi->hdmi_regset);
-		drm_print_regset32(&p, &hdmi->hd_regset);
+		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
+		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
 	HD_WRITE(VC4_HD_VID_CTL, 0);
@@ -518,11 +518,11 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&hdmi->pdev->dev);
+		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
 
-		dev_info(&hdmi->pdev->dev, "HDMI regs after:\n");
-		drm_print_regset32(&p, &hdmi->hdmi_regset);
-		drm_print_regset32(&p, &hdmi->hd_regset);
+		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
+		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
+		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
 	HD_WRITE(VC4_HD_VID_CTL,
@@ -621,15 +621,15 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 };
 
 /* HDMI audio codec callbacks */
-static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
-	u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
+	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
 	unsigned long n, m;
 
-	rational_best_approximation(hsm_clock, hdmi->audio.samplerate,
+	rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
 				    VC4_HD_MAI_SMP_N_MASK >>
 				    VC4_HD_MAI_SMP_N_SHIFT,
 				    (VC4_HD_MAI_SMP_M_MASK >>
@@ -641,14 +641,14 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
 		 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
 }
 
-static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
-	u32 samplerate = hdmi->audio.samplerate;
+	u32 samplerate = vc4_hdmi->audio.samplerate;
 	u32 n, cts;
 	u64 tmp;
 
@@ -680,16 +680,16 @@ static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
 static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 				  struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
-	if (hdmi->audio.substream && hdmi->audio.substream != substream)
+	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
 		return -EINVAL;
 
-	hdmi->audio.substream = substream;
+	vc4_hdmi->audio.substream = substream;
 
 	/*
 	 * If the HDMI encoder hasn't probed, or the encoder is
@@ -711,11 +711,11 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
-static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
+static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
-	struct device *dev = &hdmi->pdev->dev;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	int ret;
 
@@ -731,14 +731,14 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 
-	if (substream != hdmi->audio.substream)
+	if (substream != vc4_hdmi->audio.substream)
 		return;
 
-	vc4_hdmi_audio_reset(hdmi);
+	vc4_hdmi_audio_reset(vc4_hdmi);
 
-	hdmi->audio.substream = NULL;
+	vc4_hdmi->audio.substream = NULL;
 }
 
 /* HDMI audio codec callbacks */
@@ -746,23 +746,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_pcm_hw_params *params,
 				    struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
-	struct device *dev = &hdmi->pdev->dev;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 audio_packet_config, channel_mask;
 	u32 channel_map, i;
 
-	if (substream != hdmi->audio.substream)
+	if (substream != vc4_hdmi->audio.substream)
 		return -EINVAL;
 
 	dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
 		params_rate(params), params_width(params),
 		params_channels(params));
 
-	hdmi->audio.channels = params_channels(params);
-	hdmi->audio.samplerate = params_rate(params);
+	vc4_hdmi->audio.channels = params_channels(params);
+	vc4_hdmi->audio.samplerate = params_rate(params);
 
 	HD_WRITE(VC4_HD_MAI_CTL,
 		 VC4_HD_MAI_CTL_RESET |
@@ -771,23 +771,23 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 		 VC4_HD_MAI_CTL_ERRORE |
 		 VC4_HD_MAI_CTL_ERRORF);
 
-	vc4_hdmi_audio_set_mai_clock(hdmi);
+	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
 	audio_packet_config =
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
 		VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
 
-	channel_mask = GENMASK(hdmi->audio.channels - 1, 0);
+	channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
 	audio_packet_config |= VC4_SET_FIELD(channel_mask,
 					     VC4_HDMI_AUDIO_PACKET_CEA_MASK);
 
 	/* Set the MAI threshold.  This logic mimics the firmware's. */
-	if (hdmi->audio.samplerate > 96000) {
+	if (vc4_hdmi->audio.samplerate > 96000) {
 		HD_WRITE(VC4_HD_MAI_THR,
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
-	} else if (hdmi->audio.samplerate > 48000) {
+	} else if (vc4_hdmi->audio.samplerate > 48000) {
 		HD_WRITE(VC4_HD_MAI_THR,
 			 VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
 			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
@@ -811,7 +811,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
 	HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
-	vc4_hdmi_set_n_cts(hdmi);
+	vc4_hdmi_set_n_cts(vc4_hdmi);
 
 	return 0;
 }
@@ -819,8 +819,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 				  struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &hdmi->encoder.base.base;
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
+	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_device *drm = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
@@ -831,7 +831,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
 			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
 		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_SET_FIELD(hdmi->audio.channels,
+			 VC4_SET_FIELD(vc4_hdmi->audio.channels,
 				       VC4_HD_MAI_CTL_CHNUM) |
 			 VC4_HD_MAI_CTL_ENABLE);
 		break;
@@ -863,8 +863,8 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 	uinfo->count = sizeof(connector->eld);
@@ -876,8 +876,8 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-	struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &hdmi->connector.base;
+	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
+	struct drm_connector *connector = &vc4_hdmi->connector.base;
 
 	memcpy(ucontrol->value.bytes.data, connector->eld,
 	       sizeof(connector->eld));
@@ -946,9 +946,9 @@ static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
 
 static int vc4_hdmi_audio_cpu_dai_probe(struct snd_soc_dai *dai)
 {
-	struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
+	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 
-	snd_soc_dai_init_dma_data(dai, &hdmi->audio.dma_data, NULL);
+	snd_soc_dai_init_dma_data(dai, &vc4_hdmi->audio.dma_data, NULL);
 
 	return 0;
 }
@@ -974,11 +974,11 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
 	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
 };
 
-static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
+static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
-	struct snd_soc_dai_link *dai_link = &hdmi->audio.link;
-	struct snd_soc_card *card = &hdmi->audio.card;
-	struct device *dev = &hdmi->pdev->dev;
+	struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
+	struct snd_soc_card *card = &vc4_hdmi->audio.card;
+	struct device *dev = &vc4_hdmi->pdev->dev;
 	const __be32 *addr;
 	int ret;
 
@@ -996,9 +996,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
 	addr = of_get_address(dev->of_node, 1, NULL, NULL);
-	hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
-	hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	hdmi->audio.dma_data.maxburst = 2;
+	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
+	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	vc4_hdmi->audio.dma_data.maxburst = 2;
 
 	ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
 	if (ret) {
@@ -1021,9 +1021,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 		return ret;
 	}
 
-	dai_link->cpus		= &hdmi->audio.cpu;
-	dai_link->codecs	= &hdmi->audio.codec;
-	dai_link->platforms	= &hdmi->audio.platform;
+	dai_link->cpus		= &vc4_hdmi->audio.cpu;
+	dai_link->codecs	= &vc4_hdmi->audio.codec;
+	dai_link->platforms	= &vc4_hdmi->audio.platform;
 
 	dai_link->num_cpus	= 1;
 	dai_link->num_codecs	= 1;
@@ -1048,7 +1048,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 	 * now stored in card->drvdata and should be retrieved with
 	 * snd_soc_card_get_drvdata() if needed.
 	 */
-	snd_soc_card_set_drvdata(card, hdmi);
+	snd_soc_card_set_drvdata(card, vc4_hdmi);
 	ret = devm_snd_soc_register_card(dev, card);
 	if (ret)
 		dev_err(dev, "Could not register sound card: %d\n", ret);
@@ -1061,20 +1061,21 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *hdmi)
 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 {
 	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
-
-	if (hdmi->cec_irq_was_rx) {
-		if (hdmi->cec_rx_msg.len)
-			cec_received_msg(hdmi->cec_adap, &hdmi->cec_rx_msg);
-	} else if (hdmi->cec_tx_ok) {
-		cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_OK,
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+
+	if (vc4_hdmi->cec_irq_was_rx) {
+		if (vc4_hdmi->cec_rx_msg.len)
+			cec_received_msg(vc4_hdmi->cec_adap,
+					 &vc4_hdmi->cec_rx_msg);
+	} else if (vc4_hdmi->cec_tx_ok) {
+		cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_OK,
 				  0, 0, 0, 0);
 	} else {
 		/*
 		 * This CEC implementation makes 1 retry, so if we
 		 * get a NACK, then that means it made 2 attempts.
 		 */
-		cec_transmit_done(hdmi->cec_adap, CEC_TX_STATUS_NACK,
+		cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK,
 				  0, 2, 0, 0);
 	}
 	return IRQ_HANDLED;
@@ -1100,23 +1101,23 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
 	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
 	if (!(stat & VC4_HDMI_CPU_CEC))
 		return IRQ_NONE;
-	hdmi->cec_rx_msg.len = 0;
+	vc4_hdmi->cec_rx_msg.len = 0;
 	cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
 	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
-	hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
-	if (hdmi->cec_irq_was_rx) {
+	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
+	if (vc4_hdmi->cec_irq_was_rx) {
 		vc4_cec_read_msg(vc4, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 	} else {
-		hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
+		vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
 		cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
 	}
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
@@ -1218,46 +1219,46 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi;
+	struct vc4_hdmi *vc4_hdmi;
 	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
 	u32 value;
 	int ret;
 
-	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
-	if (!hdmi)
+	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+	if (!vc4_hdmi)
 		return -ENOMEM;
 
-	encoder = &hdmi->encoder.base.base;
-	hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
-	hdmi->pdev = pdev;
+	encoder = &vc4_hdmi->encoder.base.base;
+	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->pdev = pdev;
 
-	hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
-	if (IS_ERR(hdmi->hdmicore_regs))
-		return PTR_ERR(hdmi->hdmicore_regs);
+	vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
+	if (IS_ERR(vc4_hdmi->hdmicore_regs))
+		return PTR_ERR(vc4_hdmi->hdmicore_regs);
 
-	hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
-	if (IS_ERR(hdmi->hd_regs))
-		return PTR_ERR(hdmi->hd_regs);
+	vc4_hdmi->hd_regs = vc4_ioremap_regs(pdev, 1);
+	if (IS_ERR(vc4_hdmi->hd_regs))
+		return PTR_ERR(vc4_hdmi->hd_regs);
 
-	hdmi->hdmi_regset.base = hdmi->hdmicore_regs;
-	hdmi->hdmi_regset.regs = hdmi_regs;
-	hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
-	hdmi->hd_regset.base = hdmi->hd_regs;
-	hdmi->hd_regset.regs = hd_regs;
-	hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
+	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
+	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
+	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
+	vc4_hdmi->hd_regset.regs = hd_regs;
+	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
 
-	hdmi->pixel_clock = devm_clk_get(dev, "pixel");
-	if (IS_ERR(hdmi->pixel_clock)) {
-		ret = PTR_ERR(hdmi->pixel_clock);
+	vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
+	if (IS_ERR(vc4_hdmi->pixel_clock)) {
+		ret = PTR_ERR(vc4_hdmi->pixel_clock);
 		if (ret != -EPROBE_DEFER)
 			DRM_ERROR("Failed to get pixel clock\n");
 		return ret;
 	}
-	hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
-	if (IS_ERR(hdmi->hsm_clock)) {
+	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+	if (IS_ERR(vc4_hdmi->hsm_clock)) {
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
-		return PTR_ERR(hdmi->hsm_clock);
+		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
 
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
@@ -1266,9 +1267,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		return -ENODEV;
 	}
 
-	hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+	vc4_hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
 	of_node_put(ddc_node);
-	if (!hdmi->ddc) {
+	if (!vc4_hdmi->ddc) {
 		DRM_DEBUG("Failed to get ddc i2c adapter by node\n");
 		return -EPROBE_DEFER;
 	}
@@ -1277,13 +1278,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	 * needs to be a bit higher than the pixel clock rate
 	 * (generally 148.5Mhz).
 	 */
-	ret = clk_set_rate(hdmi->hsm_clock, HSM_CLOCK_FREQ);
+	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
 		goto err_put_i2c;
 	}
 
-	ret = clk_prepare_enable(hdmi->hsm_clock);
+	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
 	if (ret) {
 		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
 			  ret);
@@ -1296,18 +1297,18 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
 		enum of_gpio_flags hpd_gpio_flags;
 
-		hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
-							 "hpd-gpios", 0,
-							 &hpd_gpio_flags);
-		if (hdmi->hpd_gpio < 0) {
-			ret = hdmi->hpd_gpio;
+		vc4_hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
+							     "hpd-gpios", 0,
+							     &hpd_gpio_flags);
+		if (vc4_hdmi->hpd_gpio < 0) {
+			ret = vc4_hdmi->hpd_gpio;
 			goto err_unprepare_hsm;
 		}
 
-		hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
+		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	vc4->hdmi = hdmi;
+	vc4->hdmi = vc4_hdmi;
 
 	/* HDMI core must be enabled. */
 	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
@@ -1322,21 +1323,21 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
-	ret = vc4_hdmi_connector_init(drm, hdmi);
+	ret = vc4_hdmi_connector_init(drm, vc4_hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
-	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-					      vc4, "vc4",
-					      CEC_CAP_DEFAULTS |
-					      CEC_CAP_CONNECTOR_INFO, 1);
-	ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
+	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+						  vc4, "vc4",
+						  CEC_CAP_DEFAULTS |
+						  CEC_CAP_CONNECTOR_INFO, 1);
+	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
-	cec_s_conn_info(hdmi->cec_adap, &conn_info);
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base);
+	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
 	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
@@ -1355,32 +1356,32 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 					"vc4 hdmi cec", vc4);
 	if (ret)
 		goto err_delete_cec_adap;
-	ret = cec_register_adapter(hdmi->cec_adap, dev);
+	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
 	if (ret < 0)
 		goto err_delete_cec_adap;
 #endif
 
-	ret = vc4_hdmi_audio_init(hdmi);
+	ret = vc4_hdmi_audio_init(vc4_hdmi);
 	if (ret)
 		goto err_destroy_encoder;
 
-	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, hdmi);
+	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
 
 	return 0;
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 err_delete_cec_adap:
-	cec_delete_adapter(hdmi->cec_adap);
+	cec_delete_adapter(vc4_hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(&hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
 #endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
-	clk_disable_unprepare(hdmi->hsm_clock);
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 err_put_i2c:
-	put_device(&hdmi->ddc->dev);
+	put_device(&vc4_hdmi->ddc->dev);
 
 	return ret;
 }
@@ -1390,16 +1391,16 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
-	cec_unregister_adapter(hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(&hdmi->connector.base);
-	drm_encoder_cleanup(&hdmi->encoder.base.base);
+	cec_unregister_adapter(vc4_hdmi->cec_adap);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-	clk_disable_unprepare(hdmi->hsm_clock);
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 
-	put_device(&hdmi->ddc->dev);
+	put_device(&vc4_hdmi->ddc->dev);
 
 	vc4->hdmi = NULL;
 }
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 43/78] drm/vc4: hdmi: Move accessors to vc4_hdmi
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The current driver only supports a single HDMI controller, and part of
the issue is that the main vc4_dev structure holds a pointer to its
(only) HDMI controller, and the HDMI registers accessors will use it to
retrieve the mapped addresses.

Let's modify those accessors to use directly the vc4_hdmi structure so
that we can eventually get rid of that single global pointer.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 22 ++++++++--------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  8 ++++----
 2 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5b7202f97883..8955b0cf76ed 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -123,6 +123,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
 	struct drm_device *dev = connector->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
 	if (vc4->hdmi->hpd_gpio) {
 		if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
@@ -230,6 +231,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 packet_id = type - 0x80;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
@@ -244,6 +246,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 packet_id = frame->any.type - 0x80;
 	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
@@ -623,9 +626,6 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
 	unsigned long n, m;
 
@@ -645,8 +645,6 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 {
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	u32 samplerate = vc4_hdmi->audio.samplerate;
 	u32 n, cts;
@@ -683,7 +681,6 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_connector *connector = &vc4_hdmi->connector.base;
-	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
 	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
@@ -714,9 +711,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 {
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
 	struct device *dev = &vc4_hdmi->pdev->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	int ret;
 
 	ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
@@ -747,10 +742,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
 	struct device *dev = &vc4_hdmi->pdev->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 audio_packet_config, channel_mask;
 	u32 channel_map, i;
 
@@ -821,8 +813,6 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1083,7 +1073,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 
 static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 {
-	struct cec_msg *msg = &vc4->hdmi->cec_rx_msg;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
 	unsigned int i;
 
 	msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
@@ -1129,6 +1120,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
 	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
@@ -1172,6 +1164,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
 		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
@@ -1183,6 +1176,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 val;
 	unsigned int i;
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 17079a39f1b1..cdc9d90f62ac 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -78,9 +78,9 @@ struct vc4_hdmi {
 	struct debugfs_regset32 hd_regset;
 };
 
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
 
 #endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1

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

* [PATCH v4 43/78] drm/vc4: hdmi: Move accessors to vc4_hdmi
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The current driver only supports a single HDMI controller, and part of
the issue is that the main vc4_dev structure holds a pointer to its
(only) HDMI controller, and the HDMI registers accessors will use it to
retrieve the mapped addresses.

Let's modify those accessors to use directly the vc4_hdmi structure so
that we can eventually get rid of that single global pointer.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 22 ++++++++--------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  8 ++++----
 2 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5b7202f97883..8955b0cf76ed 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -123,6 +123,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
 	struct drm_device *dev = connector->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
 	if (vc4->hdmi->hpd_gpio) {
 		if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
@@ -230,6 +231,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 packet_id = type - 0x80;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
@@ -244,6 +246,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 packet_id = frame->any.type - 0x80;
 	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
@@ -623,9 +626,6 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
 	unsigned long n, m;
 
@@ -645,8 +645,6 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 {
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	u32 samplerate = vc4_hdmi->audio.samplerate;
 	u32 n, cts;
@@ -683,7 +681,6 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_connector *connector = &vc4_hdmi->connector.base;
-	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
 	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
@@ -714,9 +711,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 {
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
 	struct device *dev = &vc4_hdmi->pdev->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	int ret;
 
 	ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
@@ -747,10 +742,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
 	struct device *dev = &vc4_hdmi->pdev->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 audio_packet_config, channel_mask;
 	u32 channel_map, i;
 
@@ -821,8 +813,6 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1083,7 +1073,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 
 static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 {
-	struct cec_msg *msg = &vc4->hdmi->cec_rx_msg;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
 	unsigned int i;
 
 	msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
@@ -1129,6 +1120,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
 	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
@@ -1172,6 +1164,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
 		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
@@ -1183,6 +1176,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 val;
 	unsigned int i;
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 17079a39f1b1..cdc9d90f62ac 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -78,9 +78,9 @@ struct vc4_hdmi {
 	struct debugfs_regset32 hd_regset;
 };
 
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
 
 #endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 43/78] drm/vc4: hdmi: Move accessors to vc4_hdmi
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The current driver only supports a single HDMI controller, and part of
the issue is that the main vc4_dev structure holds a pointer to its
(only) HDMI controller, and the HDMI registers accessors will use it to
retrieve the mapped addresses.

Let's modify those accessors to use directly the vc4_hdmi structure so
that we can eventually get rid of that single global pointer.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 22 ++++++++--------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  8 ++++----
 2 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 5b7202f97883..8955b0cf76ed 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -123,6 +123,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
 	struct drm_device *dev = connector->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
 	if (vc4->hdmi->hpd_gpio) {
 		if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
@@ -230,6 +231,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 packet_id = type - 0x80;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
@@ -244,6 +246,7 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 packet_id = frame->any.type - 0x80;
 	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
@@ -623,9 +626,6 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
 	unsigned long n, m;
 
@@ -645,8 +645,6 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 {
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_crtc *crtc = encoder->crtc;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	u32 samplerate = vc4_hdmi->audio.samplerate;
 	u32 n, cts;
@@ -683,7 +681,6 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	struct drm_connector *connector = &vc4_hdmi->connector.base;
-	struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
 	int ret;
 
 	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
@@ -714,9 +711,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 {
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
 	struct device *dev = &vc4_hdmi->pdev->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	int ret;
 
 	ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
@@ -747,10 +742,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 				    struct snd_soc_dai *dai)
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
-	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
 	struct device *dev = &vc4_hdmi->pdev->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 	u32 audio_packet_config, channel_mask;
 	u32 channel_map, i;
 
@@ -821,8 +813,6 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1083,7 +1073,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 
 static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 {
-	struct cec_msg *msg = &vc4->hdmi->cec_rx_msg;
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
 	unsigned int i;
 
 	msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
@@ -1129,6 +1120,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
 	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
@@ -1172,6 +1164,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
 		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
@@ -1183,6 +1176,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg)
 {
 	struct vc4_dev *vc4 = cec_get_drvdata(adap);
+	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	u32 val;
 	unsigned int i;
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 17079a39f1b1..cdc9d90f62ac 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -78,9 +78,9 @@ struct vc4_hdmi {
 	struct debugfs_regset32 hd_regset;
 };
 
-#define HDMI_READ(offset) readl(vc4->hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4->hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
+#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
+#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
+#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
+#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
 
 #endif /* _VC4_HDMI_H_ */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 44/78] drm/vc4: hdmi: Use local vc4_hdmi directly
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The function vc4_hdmi_connector_detect access its vc4_hdmi struct by
dereferencing the pointer in the structure vc4_dev. This will cause some
issues when we will have multiple HDMI controllers, so let's just use the
local variable for now instead of dereferencing that pointer all the time,
and we'll fix the local variable later.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8955b0cf76ed..a3fb93322ebb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -125,20 +125,20 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
-	if (vc4->hdmi->hpd_gpio) {
-		if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
-		    vc4->hdmi->hpd_active_low)
+	if (vc4_hdmi->hpd_gpio) {
+		if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
+		    vc4_hdmi->hpd_active_low)
 			return connector_status_connected;
-		cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
+		cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 		return connector_status_disconnected;
 	}
 
-	if (drm_probe_ddc(vc4->hdmi->ddc))
+	if (drm_probe_ddc(vc4_hdmi->ddc))
 		return connector_status_connected;
 
 	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
 		return connector_status_connected;
-	cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
+	cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 	return connector_status_disconnected;
 }
 
-- 
git-series 0.9.1

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

* [PATCH v4 44/78] drm/vc4: hdmi: Use local vc4_hdmi directly
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The function vc4_hdmi_connector_detect access its vc4_hdmi struct by
dereferencing the pointer in the structure vc4_dev. This will cause some
issues when we will have multiple HDMI controllers, so let's just use the
local variable for now instead of dereferencing that pointer all the time,
and we'll fix the local variable later.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8955b0cf76ed..a3fb93322ebb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -125,20 +125,20 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
-	if (vc4->hdmi->hpd_gpio) {
-		if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
-		    vc4->hdmi->hpd_active_low)
+	if (vc4_hdmi->hpd_gpio) {
+		if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
+		    vc4_hdmi->hpd_active_low)
 			return connector_status_connected;
-		cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
+		cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 		return connector_status_disconnected;
 	}
 
-	if (drm_probe_ddc(vc4->hdmi->ddc))
+	if (drm_probe_ddc(vc4_hdmi->ddc))
 		return connector_status_connected;
 
 	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
 		return connector_status_connected;
-	cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
+	cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 	return connector_status_disconnected;
 }
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 44/78] drm/vc4: hdmi: Use local vc4_hdmi directly
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The function vc4_hdmi_connector_detect access its vc4_hdmi struct by
dereferencing the pointer in the structure vc4_dev. This will cause some
issues when we will have multiple HDMI controllers, so let's just use the
local variable for now instead of dereferencing that pointer all the time,
and we'll fix the local variable later.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8955b0cf76ed..a3fb93322ebb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -125,20 +125,20 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 
-	if (vc4->hdmi->hpd_gpio) {
-		if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
-		    vc4->hdmi->hpd_active_low)
+	if (vc4_hdmi->hpd_gpio) {
+		if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
+		    vc4_hdmi->hpd_active_low)
 			return connector_status_connected;
-		cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
+		cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 		return connector_status_disconnected;
 	}
 
-	if (drm_probe_ddc(vc4->hdmi->ddc))
+	if (drm_probe_ddc(vc4_hdmi->ddc))
 		return connector_status_connected;
 
 	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
 		return connector_status_connected;
-	cec_phys_addr_invalidate(vc4->hdmi->cec_adap);
+	cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 	return connector_status_disconnected;
 }
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 45/78] drm/vc4: hdmi: Add container_of macros for encoders and connectors
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Whenever the code needs to access the vc4_hdmi structure from a DRM
connector or encoder, it first accesses the drm_device associated to the
connector, then retrieve the drm_dev private data which gives it a
pointer to our vc4_dev, and will finally follow the vc4_hdmi pointer in
that structure.

That will also give us some trouble when having multiple controllers,
but now that we have our encoder and connector structures that are part
of vc4_hdmi, we can simply call container_of on the DRM connector or
encoder and retrieve the vc4_hdmi structure directly.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 41 ++++++++++-------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 16 ++++++++++++++-
 2 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a3fb93322ebb..d9db3c38f433 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -121,9 +121,7 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
-	struct drm_device *dev = connector->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
 
 	if (vc4_hdmi->hpd_gpio) {
 		if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
@@ -150,17 +148,13 @@ static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
 
 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 {
-	struct vc4_hdmi_connector *vc4_connector =
-		to_vc4_hdmi_connector(connector);
-	struct drm_encoder *encoder = vc4_connector->encoder;
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_device *dev = connector->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
 	int ret = 0;
 	struct edid *edid;
 
-	edid = drm_get_edid(connector, vc4->hdmi->ddc);
-	cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
+	edid = drm_get_edid(connector, vc4_hdmi->ddc);
+	cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
 	if (!edid)
 		return -ENODEV;
 
@@ -229,9 +223,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 				enum hdmi_infoframe_type type)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = type - 0x80;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
@@ -244,9 +236,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 				     union hdmi_infoframe *frame)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = frame->any.type - 0x80;
 	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
@@ -292,9 +282,8 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 
 static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct vc4_dev *vc4 = encoder->dev->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
@@ -338,9 +327,7 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
 
 static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 {
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -362,9 +349,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 
 static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
@@ -383,10 +368,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index cdc9d90f62ac..749a807cd1f3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -78,6 +78,22 @@ struct vc4_hdmi {
 	struct debugfs_regset32 hd_regset;
 };
 
+static inline struct vc4_hdmi *
+connector_to_vc4_hdmi(struct drm_connector *connector)
+{
+	struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector);
+
+	return container_of(_connector, struct vc4_hdmi, connector);
+}
+
+static inline struct vc4_hdmi *
+encoder_to_vc4_hdmi(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder);
+
+	return container_of(_encoder, struct vc4_hdmi, encoder);
+}
+
 #define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
 #define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
 #define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
-- 
git-series 0.9.1

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

* [PATCH v4 45/78] drm/vc4: hdmi: Add container_of macros for encoders and connectors
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Whenever the code needs to access the vc4_hdmi structure from a DRM
connector or encoder, it first accesses the drm_device associated to the
connector, then retrieve the drm_dev private data which gives it a
pointer to our vc4_dev, and will finally follow the vc4_hdmi pointer in
that structure.

That will also give us some trouble when having multiple controllers,
but now that we have our encoder and connector structures that are part
of vc4_hdmi, we can simply call container_of on the DRM connector or
encoder and retrieve the vc4_hdmi structure directly.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 41 ++++++++++-------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 16 ++++++++++++++-
 2 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a3fb93322ebb..d9db3c38f433 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -121,9 +121,7 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
-	struct drm_device *dev = connector->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
 
 	if (vc4_hdmi->hpd_gpio) {
 		if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
@@ -150,17 +148,13 @@ static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
 
 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 {
-	struct vc4_hdmi_connector *vc4_connector =
-		to_vc4_hdmi_connector(connector);
-	struct drm_encoder *encoder = vc4_connector->encoder;
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_device *dev = connector->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
 	int ret = 0;
 	struct edid *edid;
 
-	edid = drm_get_edid(connector, vc4->hdmi->ddc);
-	cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
+	edid = drm_get_edid(connector, vc4_hdmi->ddc);
+	cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
 	if (!edid)
 		return -ENODEV;
 
@@ -229,9 +223,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 				enum hdmi_infoframe_type type)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = type - 0x80;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
@@ -244,9 +236,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 				     union hdmi_infoframe *frame)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = frame->any.type - 0x80;
 	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
@@ -292,9 +282,8 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 
 static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct vc4_dev *vc4 = encoder->dev->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
@@ -338,9 +327,7 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
 
 static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 {
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -362,9 +349,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 
 static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
@@ -383,10 +368,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index cdc9d90f62ac..749a807cd1f3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -78,6 +78,22 @@ struct vc4_hdmi {
 	struct debugfs_regset32 hd_regset;
 };
 
+static inline struct vc4_hdmi *
+connector_to_vc4_hdmi(struct drm_connector *connector)
+{
+	struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector);
+
+	return container_of(_connector, struct vc4_hdmi, connector);
+}
+
+static inline struct vc4_hdmi *
+encoder_to_vc4_hdmi(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder);
+
+	return container_of(_encoder, struct vc4_hdmi, encoder);
+}
+
 #define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
 #define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
 #define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 45/78] drm/vc4: hdmi: Add container_of macros for encoders and connectors
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Whenever the code needs to access the vc4_hdmi structure from a DRM
connector or encoder, it first accesses the drm_device associated to the
connector, then retrieve the drm_dev private data which gives it a
pointer to our vc4_dev, and will finally follow the vc4_hdmi pointer in
that structure.

That will also give us some trouble when having multiple controllers,
but now that we have our encoder and connector structures that are part
of vc4_hdmi, we can simply call container_of on the DRM connector or
encoder and retrieve the vc4_hdmi structure directly.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 41 ++++++++++-------------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 16 ++++++++++++++-
 2 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a3fb93322ebb..d9db3c38f433 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -121,9 +121,7 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
-	struct drm_device *dev = connector->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
 
 	if (vc4_hdmi->hpd_gpio) {
 		if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^
@@ -150,17 +148,13 @@ static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
 
 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 {
-	struct vc4_hdmi_connector *vc4_connector =
-		to_vc4_hdmi_connector(connector);
-	struct drm_encoder *encoder = vc4_connector->encoder;
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_device *dev = connector->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
 	int ret = 0;
 	struct edid *edid;
 
-	edid = drm_get_edid(connector, vc4->hdmi->ddc);
-	cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
+	edid = drm_get_edid(connector, vc4_hdmi->ddc);
+	cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
 	if (!edid)
 		return -ENODEV;
 
@@ -229,9 +223,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 				enum hdmi_infoframe_type type)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = type - 0x80;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
@@ -244,9 +236,7 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 				     union hdmi_infoframe *frame)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = frame->any.type - 0x80;
 	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
@@ -292,9 +282,8 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 
 static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct vc4_dev *vc4 = encoder->dev->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	struct drm_connector *connector = &vc4_hdmi->connector.base;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
@@ -338,9 +327,7 @@ static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
 
 static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 {
-	struct drm_device *drm = encoder->dev;
-	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -362,9 +349,7 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 
 static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
 
 	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
@@ -383,10 +368,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct vc4_dev *vc4 = to_vc4_dev(dev);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
 	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index cdc9d90f62ac..749a807cd1f3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -78,6 +78,22 @@ struct vc4_hdmi {
 	struct debugfs_regset32 hd_regset;
 };
 
+static inline struct vc4_hdmi *
+connector_to_vc4_hdmi(struct drm_connector *connector)
+{
+	struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector);
+
+	return container_of(_connector, struct vc4_hdmi, connector);
+}
+
+static inline struct vc4_hdmi *
+encoder_to_vc4_hdmi(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi_encoder *_encoder = to_vc4_hdmi_encoder(encoder);
+
+	return container_of(_encoder, struct vc4_hdmi, encoder);
+}
+
 #define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
 #define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
 #define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 46/78] drm/vc4: hdmi: Pass vc4_hdmi to CEC code
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Our CEC code also retrieves the associated vc4_hdmi by setting the
vc4_dev pointer as its private data, and then dereferences its vc4_hdmi
pointer.

In order to eventually get rid of that pointer, we can simply pass the
vc4_hdmi pointer directly.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d9db3c38f433..09b297a1b39d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1033,8 +1033,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 {
-	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = priv;
 
 	if (vc4_hdmi->cec_irq_was_rx) {
 		if (vc4_hdmi->cec_rx_msg.len)
@@ -1054,9 +1053,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 	return IRQ_HANDLED;
 }
 
-static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
+static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 {
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
 	unsigned int i;
 
@@ -1074,8 +1072,7 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
-	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = priv;
 	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
@@ -1086,7 +1083,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
 	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
 	if (vc4_hdmi->cec_irq_was_rx) {
-		vc4_cec_read_msg(vc4, cntrl1);
+		vc4_cec_read_msg(vc4_hdmi, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
@@ -1102,8 +1099,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 
 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
 	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
@@ -1146,8 +1142,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
 		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
@@ -1158,8 +1153,7 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	u32 val;
 	unsigned int i;
 
@@ -1306,7 +1300,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-						  vc4, "vc4",
+						  vc4_hdmi, "vc4",
 						  CEC_CAP_DEFAULTS |
 						  CEC_CAP_CONNECTOR_INFO, 1);
 	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
@@ -1330,7 +1324,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
 					vc4_cec_irq_handler,
 					vc4_cec_irq_handler_thread, 0,
-					"vc4 hdmi cec", vc4);
+					"vc4 hdmi cec", vc4_hdmi);
 	if (ret)
 		goto err_delete_cec_adap;
 	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
-- 
git-series 0.9.1

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

* [PATCH v4 46/78] drm/vc4: hdmi: Pass vc4_hdmi to CEC code
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Our CEC code also retrieves the associated vc4_hdmi by setting the
vc4_dev pointer as its private data, and then dereferences its vc4_hdmi
pointer.

In order to eventually get rid of that pointer, we can simply pass the
vc4_hdmi pointer directly.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d9db3c38f433..09b297a1b39d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1033,8 +1033,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 {
-	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = priv;
 
 	if (vc4_hdmi->cec_irq_was_rx) {
 		if (vc4_hdmi->cec_rx_msg.len)
@@ -1054,9 +1053,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 	return IRQ_HANDLED;
 }
 
-static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
+static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 {
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
 	unsigned int i;
 
@@ -1074,8 +1072,7 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
-	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = priv;
 	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
@@ -1086,7 +1083,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
 	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
 	if (vc4_hdmi->cec_irq_was_rx) {
-		vc4_cec_read_msg(vc4, cntrl1);
+		vc4_cec_read_msg(vc4_hdmi, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
@@ -1102,8 +1099,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 
 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
 	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
@@ -1146,8 +1142,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
 		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
@@ -1158,8 +1153,7 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	u32 val;
 	unsigned int i;
 
@@ -1306,7 +1300,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-						  vc4, "vc4",
+						  vc4_hdmi, "vc4",
 						  CEC_CAP_DEFAULTS |
 						  CEC_CAP_CONNECTOR_INFO, 1);
 	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
@@ -1330,7 +1324,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
 					vc4_cec_irq_handler,
 					vc4_cec_irq_handler_thread, 0,
-					"vc4 hdmi cec", vc4);
+					"vc4 hdmi cec", vc4_hdmi);
 	if (ret)
 		goto err_delete_cec_adap;
 	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 46/78] drm/vc4: hdmi: Pass vc4_hdmi to CEC code
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Our CEC code also retrieves the associated vc4_hdmi by setting the
vc4_dev pointer as its private data, and then dereferences its vc4_hdmi
pointer.

In order to eventually get rid of that pointer, we can simply pass the
vc4_hdmi pointer directly.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d9db3c38f433..09b297a1b39d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1033,8 +1033,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 {
-	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = priv;
 
 	if (vc4_hdmi->cec_irq_was_rx) {
 		if (vc4_hdmi->cec_rx_msg.len)
@@ -1054,9 +1053,8 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
 	return IRQ_HANDLED;
 }
 
-static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
+static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 {
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
 	struct cec_msg *msg = &vc4_hdmi->cec_rx_msg;
 	unsigned int i;
 
@@ -1074,8 +1072,7 @@ static void vc4_cec_read_msg(struct vc4_dev *vc4, u32 cntrl1)
 
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
-	struct vc4_dev *vc4 = priv;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = priv;
 	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
@@ -1086,7 +1083,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
 	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
 	if (vc4_hdmi->cec_irq_was_rx) {
-		vc4_cec_read_msg(vc4, cntrl1);
+		vc4_cec_read_msg(vc4_hdmi, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
@@ -1102,8 +1099,7 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 
 static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
 	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
@@ -1146,8 +1142,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 
 	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
 		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
@@ -1158,8 +1153,7 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg)
 {
-	struct vc4_dev *vc4 = cec_get_drvdata(adap);
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	u32 val;
 	unsigned int i;
 
@@ -1306,7 +1300,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-						  vc4, "vc4",
+						  vc4_hdmi, "vc4",
 						  CEC_CAP_DEFAULTS |
 						  CEC_CAP_CONNECTOR_INFO, 1);
 	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
@@ -1330,7 +1324,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
 					vc4_cec_irq_handler,
 					vc4_cec_irq_handler_thread, 0,
-					"vc4 hdmi cec", vc4);
+					"vc4 hdmi cec", vc4_hdmi);
 	if (ret)
 		goto err_delete_cec_adap;
 	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The unbind function needs to retrieve a vc4_hdmi structure pointer through
the struct device that we're given since we want to support multiple HDMI
controllers.

However, our optional ASoC support doesn't make that trivial since it will
overwrite the device drvdata if we use it, but obviously won't if we don't
use it.

Let's make sure the fields are at the proper offset to be able to cast
between the snd_soc_card structure and the vc4_hdmi structure
transparently so we can support both cases.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 09b297a1b39d..7cd1394c10fa 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1200,6 +1200,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!vc4_hdmi)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
 	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	vc4_hdmi->pdev = pdev;
@@ -1362,7 +1363,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi;
+
+	/*
+	 * ASoC makes it a bit hard to retrieve a pointer to the
+	 * vc4_hdmi structure. Registering the card will overwrite our
+	 * device drvdata with a pointer to the snd_soc_card structure,
+	 * which can then be used to retrieve whatever drvdata we want
+	 * to associate.
+	 *
+	 * However, that doesn't fly in the case where we wouldn't
+	 * register an ASoC card (because of an old DT that is missing
+	 * the dmas properties for example), then the card isn't
+	 * registered and the device drvdata wouldn't be set.
+	 *
+	 * We can deal with both cases by making sure a snd_soc_card
+	 * pointer and a vc4_hdmi structure are pointing to the same
+	 * memory address, so we can treat them indistinctly without any
+	 * issue.
+	 */
+	BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
+	BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
+	vc4_hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 749a807cd1f3..d43462789450 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -53,13 +53,13 @@ struct vc4_hdmi_audio {
 
 /* General HDMI hardware state. */
 struct vc4_hdmi {
+	struct vc4_hdmi_audio audio;
+
 	struct platform_device *pdev;
 
 	struct vc4_hdmi_encoder encoder;
 	struct vc4_hdmi_connector connector;
 
-	struct vc4_hdmi_audio audio;
-
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
 	void __iomem *hd_regs;
-- 
git-series 0.9.1

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

* [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The unbind function needs to retrieve a vc4_hdmi structure pointer through
the struct device that we're given since we want to support multiple HDMI
controllers.

However, our optional ASoC support doesn't make that trivial since it will
overwrite the device drvdata if we use it, but obviously won't if we don't
use it.

Let's make sure the fields are at the proper offset to be able to cast
between the snd_soc_card structure and the vc4_hdmi structure
transparently so we can support both cases.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 09b297a1b39d..7cd1394c10fa 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1200,6 +1200,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!vc4_hdmi)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
 	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	vc4_hdmi->pdev = pdev;
@@ -1362,7 +1363,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi;
+
+	/*
+	 * ASoC makes it a bit hard to retrieve a pointer to the
+	 * vc4_hdmi structure. Registering the card will overwrite our
+	 * device drvdata with a pointer to the snd_soc_card structure,
+	 * which can then be used to retrieve whatever drvdata we want
+	 * to associate.
+	 *
+	 * However, that doesn't fly in the case where we wouldn't
+	 * register an ASoC card (because of an old DT that is missing
+	 * the dmas properties for example), then the card isn't
+	 * registered and the device drvdata wouldn't be set.
+	 *
+	 * We can deal with both cases by making sure a snd_soc_card
+	 * pointer and a vc4_hdmi structure are pointing to the same
+	 * memory address, so we can treat them indistinctly without any
+	 * issue.
+	 */
+	BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
+	BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
+	vc4_hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 749a807cd1f3..d43462789450 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -53,13 +53,13 @@ struct vc4_hdmi_audio {
 
 /* General HDMI hardware state. */
 struct vc4_hdmi {
+	struct vc4_hdmi_audio audio;
+
 	struct platform_device *pdev;
 
 	struct vc4_hdmi_encoder encoder;
 	struct vc4_hdmi_connector connector;
 
-	struct vc4_hdmi_audio audio;
-
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
 	void __iomem *hd_regs;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The unbind function needs to retrieve a vc4_hdmi structure pointer through
the struct device that we're given since we want to support multiple HDMI
controllers.

However, our optional ASoC support doesn't make that trivial since it will
overwrite the device drvdata if we use it, but obviously won't if we don't
use it.

Let's make sure the fields are at the proper offset to be able to cast
between the snd_soc_card structure and the vc4_hdmi structure
transparently so we can support both cases.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 09b297a1b39d..7cd1394c10fa 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1200,6 +1200,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (!vc4_hdmi)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
 	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
 	vc4_hdmi->pdev = pdev;
@@ -1362,7 +1363,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 {
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
-	struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
+	struct vc4_hdmi *vc4_hdmi;
+
+	/*
+	 * ASoC makes it a bit hard to retrieve a pointer to the
+	 * vc4_hdmi structure. Registering the card will overwrite our
+	 * device drvdata with a pointer to the snd_soc_card structure,
+	 * which can then be used to retrieve whatever drvdata we want
+	 * to associate.
+	 *
+	 * However, that doesn't fly in the case where we wouldn't
+	 * register an ASoC card (because of an old DT that is missing
+	 * the dmas properties for example), then the card isn't
+	 * registered and the device drvdata wouldn't be set.
+	 *
+	 * We can deal with both cases by making sure a snd_soc_card
+	 * pointer and a vc4_hdmi structure are pointing to the same
+	 * memory address, so we can treat them indistinctly without any
+	 * issue.
+	 */
+	BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
+	BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
+	vc4_hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 749a807cd1f3..d43462789450 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -53,13 +53,13 @@ struct vc4_hdmi_audio {
 
 /* General HDMI hardware state. */
 struct vc4_hdmi {
+	struct vc4_hdmi_audio audio;
+
 	struct platform_device *pdev;
 
 	struct vc4_hdmi_encoder encoder;
 	struct vc4_hdmi_connector connector;
 
-	struct vc4_hdmi_audio audio;
-
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
 	void __iomem *hd_regs;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 48/78] drm/vc4: hdmi: Remove vc4_dev hdmi pointer
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Now that we don't have any users anymore, we can kill that pointer.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h  | 1 -
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 -------
 2 files changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 1a97545b9244..501a48a714d3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -73,7 +73,6 @@ struct vc4_perfmon {
 struct vc4_dev {
 	struct drm_device *dev;
 
-	struct vc4_hdmi *hdmi;
 	struct vc4_hvs *hvs;
 	struct vc4_v3d *v3d;
 	struct vc4_dpi *dpi;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 7cd1394c10fa..c5c9f7bf5dee 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1189,7 +1189,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 #endif
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *vc4_hdmi;
 	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
@@ -1280,8 +1279,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	vc4->hdmi = vc4_hdmi;
-
 	/* HDMI core must be enabled. */
 	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
 		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
@@ -1361,8 +1358,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 			    void *data)
 {
-	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *vc4_hdmi;
 
 	/*
@@ -1394,8 +1389,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	pm_runtime_disable(dev);
 
 	put_device(&vc4_hdmi->ddc->dev);
-
-	vc4->hdmi = NULL;
 }
 
 static const struct component_ops vc4_hdmi_ops = {
-- 
git-series 0.9.1

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

* [PATCH v4 48/78] drm/vc4: hdmi: Remove vc4_dev hdmi pointer
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that we don't have any users anymore, we can kill that pointer.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h  | 1 -
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 -------
 2 files changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 1a97545b9244..501a48a714d3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -73,7 +73,6 @@ struct vc4_perfmon {
 struct vc4_dev {
 	struct drm_device *dev;
 
-	struct vc4_hdmi *hdmi;
 	struct vc4_hvs *hvs;
 	struct vc4_v3d *v3d;
 	struct vc4_dpi *dpi;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 7cd1394c10fa..c5c9f7bf5dee 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1189,7 +1189,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 #endif
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *vc4_hdmi;
 	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
@@ -1280,8 +1279,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	vc4->hdmi = vc4_hdmi;
-
 	/* HDMI core must be enabled. */
 	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
 		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
@@ -1361,8 +1358,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 			    void *data)
 {
-	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *vc4_hdmi;
 
 	/*
@@ -1394,8 +1389,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	pm_runtime_disable(dev);
 
 	put_device(&vc4_hdmi->ddc->dev);
-
-	vc4->hdmi = NULL;
 }
 
 static const struct component_ops vc4_hdmi_ops = {
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 48/78] drm/vc4: hdmi: Remove vc4_dev hdmi pointer
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that we don't have any users anymore, we can kill that pointer.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.h  | 1 -
 drivers/gpu/drm/vc4/vc4_hdmi.c | 7 -------
 2 files changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 1a97545b9244..501a48a714d3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -73,7 +73,6 @@ struct vc4_perfmon {
 struct vc4_dev {
 	struct drm_device *dev;
 
-	struct vc4_hdmi *hdmi;
 	struct vc4_hvs *hvs;
 	struct vc4_v3d *v3d;
 	struct vc4_dpi *dpi;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 7cd1394c10fa..c5c9f7bf5dee 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1189,7 +1189,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 #endif
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *vc4_hdmi;
 	struct drm_encoder *encoder;
 	struct device_node *ddc_node;
@@ -1280,8 +1279,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	vc4->hdmi = vc4_hdmi;
-
 	/* HDMI core must be enabled. */
 	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
 		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
@@ -1361,8 +1358,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 			    void *data)
 {
-	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_dev *vc4 = drm->dev_private;
 	struct vc4_hdmi *vc4_hdmi;
 
 	/*
@@ -1394,8 +1389,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	pm_runtime_disable(dev);
 
 	put_device(&vc4_hdmi->ddc->dev);
-
-	vc4->hdmi = NULL;
 }
 
 static const struct component_ops vc4_hdmi_ops = {
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 49/78] drm/vc4: hdmi: Remove vc4_hdmi_connector
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The vc4_hdmi_connector was only used to switch between drm_connector to
drm_encoder. However, we can now use vc4_hdmi to do the switch, so that
structure is redundant.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 19 ++++++++-----------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 23 ++---------------------
 2 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c5c9f7bf5dee..ec7710dfd04e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -189,13 +189,10 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 static int vc4_hdmi_connector_init(struct drm_device *dev,
 				   struct vc4_hdmi *vc4_hdmi)
 {
-	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
-	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector->encoder = encoder;
-
 	drm_connector_init_with_ddc(dev, connector,
 				    &vc4_hdmi_connector_funcs,
 				    DRM_MODE_CONNECTOR_HDMIA,
@@ -284,7 +281,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
@@ -663,7 +660,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	int ret;
 
 	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
@@ -837,7 +834,7 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 	uinfo->count = sizeof(connector->eld);
@@ -850,7 +847,7 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 
 	memcpy(ucontrol->value.bytes.data, connector->eld,
 	       sizeof(connector->eld));
@@ -1305,7 +1302,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base);
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
 	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1342,7 +1339,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(vc4_hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 #endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
@@ -1382,7 +1379,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	vc4_hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
 	clk_disable_unprepare(vc4_hdmi->hsm_clock);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index d43462789450..674541493909 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,23 +21,6 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -58,7 +41,7 @@ struct vc4_hdmi {
 	struct platform_device *pdev;
 
 	struct vc4_hdmi_encoder encoder;
-	struct vc4_hdmi_connector connector;
+	struct drm_connector connector;
 
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
@@ -81,9 +64,7 @@ struct vc4_hdmi {
 static inline struct vc4_hdmi *
 connector_to_vc4_hdmi(struct drm_connector *connector)
 {
-	struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector);
-
-	return container_of(_connector, struct vc4_hdmi, connector);
+	return container_of(connector, struct vc4_hdmi, connector);
 }
 
 static inline struct vc4_hdmi *
-- 
git-series 0.9.1

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

* [PATCH v4 49/78] drm/vc4: hdmi: Remove vc4_hdmi_connector
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4_hdmi_connector was only used to switch between drm_connector to
drm_encoder. However, we can now use vc4_hdmi to do the switch, so that
structure is redundant.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 19 ++++++++-----------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 23 ++---------------------
 2 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c5c9f7bf5dee..ec7710dfd04e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -189,13 +189,10 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 static int vc4_hdmi_connector_init(struct drm_device *dev,
 				   struct vc4_hdmi *vc4_hdmi)
 {
-	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
-	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector->encoder = encoder;
-
 	drm_connector_init_with_ddc(dev, connector,
 				    &vc4_hdmi_connector_funcs,
 				    DRM_MODE_CONNECTOR_HDMIA,
@@ -284,7 +281,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
@@ -663,7 +660,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	int ret;
 
 	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
@@ -837,7 +834,7 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 	uinfo->count = sizeof(connector->eld);
@@ -850,7 +847,7 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 
 	memcpy(ucontrol->value.bytes.data, connector->eld,
 	       sizeof(connector->eld));
@@ -1305,7 +1302,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base);
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
 	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1342,7 +1339,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(vc4_hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 #endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
@@ -1382,7 +1379,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	vc4_hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
 	clk_disable_unprepare(vc4_hdmi->hsm_clock);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index d43462789450..674541493909 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,23 +21,6 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -58,7 +41,7 @@ struct vc4_hdmi {
 	struct platform_device *pdev;
 
 	struct vc4_hdmi_encoder encoder;
-	struct vc4_hdmi_connector connector;
+	struct drm_connector connector;
 
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
@@ -81,9 +64,7 @@ struct vc4_hdmi {
 static inline struct vc4_hdmi *
 connector_to_vc4_hdmi(struct drm_connector *connector)
 {
-	struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector);
-
-	return container_of(_connector, struct vc4_hdmi, connector);
+	return container_of(connector, struct vc4_hdmi, connector);
 }
 
 static inline struct vc4_hdmi *
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 49/78] drm/vc4: hdmi: Remove vc4_hdmi_connector
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4_hdmi_connector was only used to switch between drm_connector to
drm_encoder. However, we can now use vc4_hdmi to do the switch, so that
structure is redundant.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 19 ++++++++-----------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 23 ++---------------------
 2 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c5c9f7bf5dee..ec7710dfd04e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -189,13 +189,10 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
 static int vc4_hdmi_connector_init(struct drm_device *dev,
 				   struct vc4_hdmi *vc4_hdmi)
 {
-	struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
-	struct drm_connector *connector = &hdmi_connector->base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
 	int ret;
 
-	hdmi_connector->encoder = encoder;
-
 	drm_connector_init_with_ddc(dev, connector,
 				    &vc4_hdmi_connector_funcs,
 				    DRM_MODE_CONNECTOR_HDMIA,
@@ -284,7 +281,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	struct drm_connector_state *cstate = connector->state;
 	struct drm_crtc *crtc = encoder->crtc;
 	const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
@@ -663,7 +660,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 {
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 	int ret;
 
 	if (vc4_hdmi->audio.substream && vc4_hdmi->audio.substream != substream)
@@ -837,7 +834,7 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 	uinfo->count = sizeof(connector->eld);
@@ -850,7 +847,7 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 	struct vc4_hdmi *vc4_hdmi = snd_component_to_hdmi(component);
-	struct drm_connector *connector = &vc4_hdmi->connector.base;
+	struct drm_connector *connector = &vc4_hdmi->connector;
 
 	memcpy(ucontrol->value.bytes.data, connector->eld,
 	       sizeof(connector->eld));
@@ -1305,7 +1302,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret < 0)
 		goto err_destroy_conn;
 
-	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector.base);
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
 	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
@@ -1342,7 +1339,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_delete_cec_adap:
 	cec_delete_adapter(vc4_hdmi->cec_adap);
 err_destroy_conn:
-	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 #endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
@@ -1382,7 +1379,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	vc4_hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
-	vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
 	clk_disable_unprepare(vc4_hdmi->hsm_clock);
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index d43462789450..674541493909 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,23 +21,6 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
-/* VC4 HDMI connector KMS struct */
-struct vc4_hdmi_connector {
-	struct drm_connector base;
-
-	/* Since the connector is attached to just the one encoder,
-	 * this is the reference to it so we can do the best_encoder()
-	 * hook.
-	 */
-	struct drm_encoder *encoder;
-};
-
-static inline struct vc4_hdmi_connector *
-to_vc4_hdmi_connector(struct drm_connector *connector)
-{
-	return container_of(connector, struct vc4_hdmi_connector, base);
-}
-
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -58,7 +41,7 @@ struct vc4_hdmi {
 	struct platform_device *pdev;
 
 	struct vc4_hdmi_encoder encoder;
-	struct vc4_hdmi_connector connector;
+	struct drm_connector connector;
 
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
@@ -81,9 +64,7 @@ struct vc4_hdmi {
 static inline struct vc4_hdmi *
 connector_to_vc4_hdmi(struct drm_connector *connector)
 {
-	struct vc4_hdmi_connector *_connector = to_vc4_hdmi_connector(connector);
-
-	return container_of(_connector, struct vc4_hdmi, connector);
+	return container_of(connector, struct vc4_hdmi, connector);
 }
 
 static inline struct vc4_hdmi *
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HDMI controllers found in the BCM2711 has a pretty different clock and
registers areas than found in the older BCM283x SoCs.

Let's create a variant structure to store the various adjustments we'll
need later on, and a function to get the resources needed for one
particular version.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++-
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ec7710dfd04e..ac021e07a8cb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1179,28 +1179,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 };
 #endif
 
-static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 {
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	struct cec_connector_info conn_info;
-#endif
-	struct platform_device *pdev = to_platform_device(dev);
-	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_hdmi *vc4_hdmi;
-	struct drm_encoder *encoder;
-	struct device_node *ddc_node;
-	u32 value;
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	struct device *dev = &pdev->dev;
 	int ret;
 
-	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
-	if (!vc4_hdmi)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, vc4_hdmi);
-	encoder = &vc4_hdmi->encoder.base.base;
-	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
-	vc4_hdmi->pdev = pdev;
-
 	vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(vc4_hdmi->hdmicore_regs))
 		return PTR_ERR(vc4_hdmi->hdmicore_regs);
@@ -1212,6 +1196,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
 	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
 	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+
 	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
 	vc4_hdmi->hd_regset.regs = hd_regs;
 	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
@@ -1223,12 +1208,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 			DRM_ERROR("Failed to get pixel clock\n");
 		return ret;
 	}
+
 	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
 	if (IS_ERR(vc4_hdmi->hsm_clock)) {
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
 		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
 
+	return 0;
+}
+
+static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
+	struct cec_connector_info conn_info;
+#endif
+	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_hdmi *vc4_hdmi;
+	struct drm_encoder *encoder;
+	struct device_node *ddc_node;
+	u32 value;
+	int ret;
+
+	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+	if (!vc4_hdmi)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, vc4_hdmi);
+	encoder = &vc4_hdmi->encoder.base.base;
+	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->pdev = pdev;
+	vc4_hdmi->variant = variant;
+
+	ret = variant->init_resources(vc4_hdmi);
+	if (ret)
+		return ret;
+
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
 	if (!ddc_node) {
 		DRM_ERROR("Failed to find ddc node in device tree\n");
@@ -1404,8 +1421,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct vc4_hdmi_variant bcm2835_variant = {
+	.init_resources		= vc4_hdmi_init_resources,
+};
+
 static const struct of_device_id vc4_hdmi_dt_match[] = {
-	{ .compatible = "brcm,bcm2835-hdmi" },
+	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 674541493909..0eaf979fe811 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct vc4_hdmi;
+
+struct vc4_hdmi_variant {
+	/* Callback to get the resources (memory region, interrupts,
+	 * clocks, etc) for that variant.
+	 */
+	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+};
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -39,6 +48,7 @@ struct vc4_hdmi {
 	struct vc4_hdmi_audio audio;
 
 	struct platform_device *pdev;
+	const struct vc4_hdmi_variant *variant;
 
 	struct vc4_hdmi_encoder encoder;
 	struct drm_connector connector;
-- 
git-series 0.9.1

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

* [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI controllers found in the BCM2711 has a pretty different clock and
registers areas than found in the older BCM283x SoCs.

Let's create a variant structure to store the various adjustments we'll
need later on, and a function to get the resources needed for one
particular version.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++-
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ec7710dfd04e..ac021e07a8cb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1179,28 +1179,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 };
 #endif
 
-static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 {
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	struct cec_connector_info conn_info;
-#endif
-	struct platform_device *pdev = to_platform_device(dev);
-	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_hdmi *vc4_hdmi;
-	struct drm_encoder *encoder;
-	struct device_node *ddc_node;
-	u32 value;
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	struct device *dev = &pdev->dev;
 	int ret;
 
-	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
-	if (!vc4_hdmi)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, vc4_hdmi);
-	encoder = &vc4_hdmi->encoder.base.base;
-	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
-	vc4_hdmi->pdev = pdev;
-
 	vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(vc4_hdmi->hdmicore_regs))
 		return PTR_ERR(vc4_hdmi->hdmicore_regs);
@@ -1212,6 +1196,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
 	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
 	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+
 	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
 	vc4_hdmi->hd_regset.regs = hd_regs;
 	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
@@ -1223,12 +1208,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 			DRM_ERROR("Failed to get pixel clock\n");
 		return ret;
 	}
+
 	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
 	if (IS_ERR(vc4_hdmi->hsm_clock)) {
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
 		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
 
+	return 0;
+}
+
+static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
+	struct cec_connector_info conn_info;
+#endif
+	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_hdmi *vc4_hdmi;
+	struct drm_encoder *encoder;
+	struct device_node *ddc_node;
+	u32 value;
+	int ret;
+
+	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+	if (!vc4_hdmi)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, vc4_hdmi);
+	encoder = &vc4_hdmi->encoder.base.base;
+	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->pdev = pdev;
+	vc4_hdmi->variant = variant;
+
+	ret = variant->init_resources(vc4_hdmi);
+	if (ret)
+		return ret;
+
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
 	if (!ddc_node) {
 		DRM_ERROR("Failed to find ddc node in device tree\n");
@@ -1404,8 +1421,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct vc4_hdmi_variant bcm2835_variant = {
+	.init_resources		= vc4_hdmi_init_resources,
+};
+
 static const struct of_device_id vc4_hdmi_dt_match[] = {
-	{ .compatible = "brcm,bcm2835-hdmi" },
+	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 674541493909..0eaf979fe811 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct vc4_hdmi;
+
+struct vc4_hdmi_variant {
+	/* Callback to get the resources (memory region, interrupts,
+	 * clocks, etc) for that variant.
+	 */
+	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+};
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -39,6 +48,7 @@ struct vc4_hdmi {
 	struct vc4_hdmi_audio audio;
 
 	struct platform_device *pdev;
+	const struct vc4_hdmi_variant *variant;
 
 	struct vc4_hdmi_encoder encoder;
 	struct drm_connector connector;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI controllers found in the BCM2711 has a pretty different clock and
registers areas than found in the older BCM283x SoCs.

Let's create a variant structure to store the various adjustments we'll
need later on, and a function to get the resources needed for one
particular version.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++------------
 drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++-
 2 files changed, 51 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ec7710dfd04e..ac021e07a8cb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1179,28 +1179,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 };
 #endif
 
-static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 {
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	struct cec_connector_info conn_info;
-#endif
-	struct platform_device *pdev = to_platform_device(dev);
-	struct drm_device *drm = dev_get_drvdata(master);
-	struct vc4_hdmi *vc4_hdmi;
-	struct drm_encoder *encoder;
-	struct device_node *ddc_node;
-	u32 value;
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	struct device *dev = &pdev->dev;
 	int ret;
 
-	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
-	if (!vc4_hdmi)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, vc4_hdmi);
-	encoder = &vc4_hdmi->encoder.base.base;
-	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
-	vc4_hdmi->pdev = pdev;
-
 	vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
 	if (IS_ERR(vc4_hdmi->hdmicore_regs))
 		return PTR_ERR(vc4_hdmi->hdmicore_regs);
@@ -1212,6 +1196,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
 	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
 	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+
 	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
 	vc4_hdmi->hd_regset.regs = hd_regs;
 	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
@@ -1223,12 +1208,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 			DRM_ERROR("Failed to get pixel clock\n");
 		return ret;
 	}
+
 	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
 	if (IS_ERR(vc4_hdmi->hsm_clock)) {
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
 		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
 
+	return 0;
+}
+
+static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
+	struct cec_connector_info conn_info;
+#endif
+	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_hdmi *vc4_hdmi;
+	struct drm_encoder *encoder;
+	struct device_node *ddc_node;
+	u32 value;
+	int ret;
+
+	vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+	if (!vc4_hdmi)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, vc4_hdmi);
+	encoder = &vc4_hdmi->encoder.base.base;
+	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->pdev = pdev;
+	vc4_hdmi->variant = variant;
+
+	ret = variant->init_resources(vc4_hdmi);
+	if (ret)
+		return ret;
+
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
 	if (!ddc_node) {
 		DRM_ERROR("Failed to find ddc node in device tree\n");
@@ -1404,8 +1421,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct vc4_hdmi_variant bcm2835_variant = {
+	.init_resources		= vc4_hdmi_init_resources,
+};
+
 static const struct of_device_id vc4_hdmi_dt_match[] = {
-	{ .compatible = "brcm,bcm2835-hdmi" },
+	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 674541493909..0eaf979fe811 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct vc4_hdmi;
+
+struct vc4_hdmi_variant {
+	/* Callback to get the resources (memory region, interrupts,
+	 * clocks, etc) for that variant.
+	 */
+	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+};
+
 /* HDMI audio information */
 struct vc4_hdmi_audio {
 	struct snd_soc_card card;
@@ -39,6 +48,7 @@ struct vc4_hdmi {
 	struct vc4_hdmi_audio audio;
 
 	struct platform_device *pdev;
+	const struct vc4_hdmi_variant *variant;
 
 	struct vc4_hdmi_encoder encoder;
 	struct drm_connector connector;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:41     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HDMI controllers found in the BCM2711 have most of the registers
reorganized in multiple registers areas and at different offsets than
previously found.

The logic however remains pretty much the same, so it doesn't really make
sense to create a whole new driver and we should share the code as much as
possible.

Let's implement some indirection to wrap around a register and depending on
the variant will lookup the associated register on that particular variant.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 427 ++++++++++++++---------------
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  12 +-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h      |  92 +------
 4 files changed, 464 insertions(+), 308 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ac021e07a8cb..a4fed1439bf3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -50,62 +50,13 @@
 #include "media/cec.h"
 #include "vc4_drv.h"
 #include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
-static const struct debugfs_reg32 hdmi_regs[] = {
-	VC4_REG32(VC4_HDMI_CORE_REV),
-	VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
-	VC4_REG32(VC4_HDMI_HOTPLUG_INT),
-	VC4_REG32(VC4_HDMI_HOTPLUG),
-	VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
-	VC4_REG32(VC4_HDMI_MAI_CONFIG),
-	VC4_REG32(VC4_HDMI_MAI_FORMAT),
-	VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
-	VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
-	VC4_REG32(VC4_HDMI_HORZA),
-	VC4_REG32(VC4_HDMI_HORZB),
-	VC4_REG32(VC4_HDMI_FIFO_CTL),
-	VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
-	VC4_REG32(VC4_HDMI_VERTA0),
-	VC4_REG32(VC4_HDMI_VERTA1),
-	VC4_REG32(VC4_HDMI_VERTB0),
-	VC4_REG32(VC4_HDMI_VERTB1),
-	VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
-	VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
-
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
-	VC4_REG32(VC4_HDMI_CPU_STATUS),
-	VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
-
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
-};
-
-static const struct debugfs_reg32 hd_regs[] = {
-	VC4_REG32(VC4_HD_M_CTL),
-	VC4_REG32(VC4_HD_MAI_CTL),
-	VC4_REG32(VC4_HD_MAI_THR),
-	VC4_REG32(VC4_HD_MAI_FMT),
-	VC4_REG32(VC4_HD_MAI_SMP),
-	VC4_REG32(VC4_HD_VID_CTL),
-	VC4_REG32(VC4_HD_CSC_CTL),
-	VC4_REG32(VC4_HD_FRAME_COUNT),
-};
-
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	if (drm_probe_ddc(vc4_hdmi->ddc))
 		return connector_status_connected;
 
-	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
+	if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
 		return connector_status_connected;
 	cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 	return connector_status_disconnected;
@@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = type - 0x80;
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+		   HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
 
-	return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
+	return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
 			  BIT(packet_id)), 100);
 }
 
@@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = frame->any.type - 0x80;
-	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
+	const struct vc4_hdmi_register *ram_packet_start =
+		&vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
+	u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
+	void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
+						       ram_packet_start->reg);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
 	ssize_t len, i;
 	int ret;
 
-	WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+	WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 		    VC4_HDMI_RAM_PACKET_ENABLE),
 		  "Packet RAM has to be on to store the packet.");
 
@@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 	}
 
 	for (i = 0; i < len; i += 7) {
-		HDMI_WRITE(packet_reg,
-			   buffer[i + 0] << 0 |
-			   buffer[i + 1] << 8 |
-			   buffer[i + 2] << 16);
+		writel(buffer[i + 0] << 0 |
+		       buffer[i + 1] << 8 |
+		       buffer[i + 2] << 16,
+		       base + packet_reg);
 		packet_reg += 4;
 
-		HDMI_WRITE(packet_reg,
-			   buffer[i + 3] << 0 |
-			   buffer[i + 4] << 8 |
-			   buffer[i + 5] << 16 |
-			   buffer[i + 6] << 24);
+		writel(buffer[i + 3] << 0 |
+		       buffer[i + 4] << 8 |
+		       buffer[i + 5] << 16 |
+		       buffer[i + 6] << 24,
+		       base + packet_reg);
 		packet_reg += 4;
 	}
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
-	ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+		   HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
+	ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
 			BIT(packet_id)), 100);
 	if (ret)
 		DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
@@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-	HD_WRITE(VC4_HD_VID_CTL,
-		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
 	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
@@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
 		   VC4_HDMI_SW_RESET_HDMI |
 		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
 
-	HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
 	 */
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
 
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
-	HD_WRITE(VC4_HD_VID_CTL, 0);
+	HDMI_WRITE(HDMI_VID_CTL, 0);
 
-	HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-		   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
-	HDMI_WRITE(VC4_HDMI_HORZA,
+	HDMI_WRITE(HDMI_HORZA,
 		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
 		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
 		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
 				 VC4_HDMI_HORZA_HAP));
 
-	HDMI_WRITE(VC4_HDMI_HORZB,
+	HDMI_WRITE(HDMI_HORZB,
 		   VC4_SET_FIELD((mode->htotal -
 				  mode->hsync_end) * pixel_rep,
 				 VC4_HDMI_HORZB_HBP) |
@@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 				  mode->hdisplay) * pixel_rep,
 				 VC4_HDMI_HORZB_HFP));
 
-	HDMI_WRITE(VC4_HDMI_VERTA0, verta);
-	HDMI_WRITE(VC4_HDMI_VERTA1, verta);
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
 
-	HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
-	HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
 
-	HD_WRITE(VC4_HD_VID_CTL,
-		 (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		 (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+	HDMI_WRITE(HDMI_VID_CTL,
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
 	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
 				VC4_HD_CSC_CTL_ORDER);
@@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
 					 VC4_HD_CSC_CTL_MODE);
 
-		HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
-		HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
-		HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
 		vc4_encoder->limited_rgb_range = true;
 	} else {
 		vc4_encoder->limited_rgb_range = false;
 	}
 
 	/* The RGB order applies even when CSC is disabled. */
-	HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 
-	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
-	HD_WRITE(VC4_HD_VID_CTL,
-		 HD_READ(VC4_HD_VID_CTL) |
-		 VC4_HD_VID_CTL_ENABLE |
-		 VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
-		 VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) |
+		   VC4_HD_VID_CTL_ENABLE |
+		   VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
+		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
 
 	if (vc4_encoder->hdmi_monitor) {
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 			   VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
-		ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 	} else {
-		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-			   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+			   HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 			   ~(VC4_HDMI_RAM_PACKET_ENABLE));
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			   ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
-		ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
@@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_encoder->hdmi_monitor) {
 		u32 drift;
 
-		WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 			   VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
 
-		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
+		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 			   VC4_HDMI_RAM_PACKET_ENABLE);
 
 		vc4_hdmi_set_infoframes(encoder);
 
-		drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
+		drift = HDMI_READ(HDMI_FIFO_CTL);
 		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
 
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
 		usleep_range(1000, 1100);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
 
-		ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
+		ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
 			       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
@@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 				     VC4_HD_MAI_SMP_M_SHIFT) + 1,
 				    &n, &m);
 
-	HD_WRITE(VC4_HD_MAI_SMP,
-		 VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
-		 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
+	HDMI_WRITE(HDMI_MAI_SMP,
+		   VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
+		   VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
 }
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
@@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 	do_div(tmp, 128 * samplerate);
 	cts = tmp;
 
-	HDMI_WRITE(VC4_HDMI_CRP_CFG,
+	HDMI_WRITE(HDMI_CRP_CFG,
 		   VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
 		   VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
 
@@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 	 * providing a CTS_1 value.  The two CTS values are alternated
 	 * between based on the period fields
 	 */
-	HDMI_WRITE(VC4_HDMI_CTS_0, cts);
-	HDMI_WRITE(VC4_HDMI_CTS_1, cts);
+	HDMI_WRITE(HDMI_CTS_0, cts);
+	HDMI_WRITE(HDMI_CTS_1, cts);
 }
 
 static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
@@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 	 * If the HDMI encoder hasn't probed, or the encoder is
 	 * currently in DVI mode, treat the codec dai as missing.
 	 */
-	if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+	if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
@@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 	if (ret)
 		dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
 
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
 }
 
 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
@@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 	vc4_hdmi->audio.channels = params_channels(params);
 	vc4_hdmi->audio.samplerate = params_rate(params);
 
-	HD_WRITE(VC4_HD_MAI_CTL,
-		 VC4_HD_MAI_CTL_RESET |
-		 VC4_HD_MAI_CTL_FLUSH |
-		 VC4_HD_MAI_CTL_DLATE |
-		 VC4_HD_MAI_CTL_ERRORE |
-		 VC4_HD_MAI_CTL_ERRORF);
+	HDMI_WRITE(HDMI_MAI_CTL,
+		   VC4_HD_MAI_CTL_RESET |
+		   VC4_HD_MAI_CTL_FLUSH |
+		   VC4_HD_MAI_CTL_DLATE |
+		   VC4_HD_MAI_CTL_ERRORE |
+		   VC4_HD_MAI_CTL_ERRORF);
 
 	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
@@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	/* Set the MAI threshold.  This logic mimics the firmware's. */
 	if (vc4_hdmi->audio.samplerate > 96000) {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
 	} else if (vc4_hdmi->audio.samplerate > 48000) {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
 	} else {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
 	}
 
-	HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
+	HDMI_WRITE(HDMI_MAI_CONFIG,
 		   VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
 		   VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
 
@@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 			channel_map |= i << (3 * i);
 	}
 
-	HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
-	HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
+	HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
+	HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
 	vc4_hdmi_set_n_cts(vc4_hdmi);
 
 	return 0;
@@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
-		HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
-			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
+		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+			   HDMI_READ(HDMI_TX_PHY_CTL_0) &
 			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
-		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_SET_FIELD(vc4_hdmi->audio.channels,
-				       VC4_HD_MAI_CTL_CHNUM) |
-			 VC4_HD_MAI_CTL_ENABLE);
+
+		HDMI_WRITE(HDMI_MAI_CTL,
+			   VC4_SET_FIELD(vc4_hdmi->audio.channels,
+					 VC4_HD_MAI_CTL_CHNUM) |
+			   VC4_HD_MAI_CTL_ENABLE);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_HD_MAI_CTL_DLATE |
-			 VC4_HD_MAI_CTL_ERRORE |
-			 VC4_HD_MAI_CTL_ERRORF);
-		HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
-			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
+		HDMI_WRITE(HDMI_MAI_CTL,
+			   VC4_HD_MAI_CTL_DLATE |
+			   VC4_HD_MAI_CTL_ERRORE |
+			   VC4_HD_MAI_CTL_ERRORF);
+		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+			   HDMI_READ(HDMI_TX_PHY_CTL_0) |
 			   VC4_HDMI_TX_PHY_RNG_PWRDN);
 		break;
 	default:
@@ -946,6 +902,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
 
 static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
+	const struct vc4_hdmi_register *mai_data =
+		&vc4_hdmi->variant->registers[HDMI_MAI_DATA];
 	struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
 	struct snd_soc_card *card = &vc4_hdmi->audio.card;
 	struct device *dev = &vc4_hdmi->pdev->dev;
@@ -958,6 +916,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 		return 0;
 	}
 
+	if (mai_data->reg != VC4_HD) {
+		WARN_ONCE(true, "MAI isn't in the HD block\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve
 	 * the bus address specified in the DT, because the physical address
@@ -966,7 +929,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
 	addr = of_get_address(dev->of_node, 1, NULL, NULL);
-	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
+	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
 	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	vc4_hdmi->audio.dma_data.maxburst = 2;
 
@@ -1058,7 +1021,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 	msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
 					VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
 	for (i = 0; i < msg->len; i += 4) {
-		u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
+		u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i);
 
 		msg->msg[i] = val & 0xff;
 		msg->msg[i + 1] = (val >> 8) & 0xff;
@@ -1070,26 +1033,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
 	struct vc4_hdmi *vc4_hdmi = priv;
-	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
+	u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
 	if (!(stat & VC4_HDMI_CPU_CEC))
 		return IRQ_NONE;
 	vc4_hdmi->cec_rx_msg.len = 0;
-	cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
-	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
+	cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
+	cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
 	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
 	if (vc4_hdmi->cec_irq_was_rx) {
 		vc4_cec_read_msg(vc4_hdmi, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
+		HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 	} else {
 		vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
 		cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
 	}
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
-	HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
+	HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
 
 	return IRQ_WAKE_THREAD;
 }
@@ -1099,7 +1062,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
-	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
+	u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
 
 	val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
 		 VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
@@ -1108,30 +1071,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 	       ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
 
 	if (enable) {
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
 			   VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
-			 ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
-			 ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
-			 ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
-			 ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
-			 ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
-			 ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
-			 ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
-			 ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
-			 ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
-			 ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
-			 ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
-			 ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
-			 ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
-
-		HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
+		HDMI_WRITE(HDMI_CEC_CNTRL_2,
+			   ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
+			   ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
+			   ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
+			   ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
+			   ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
+		HDMI_WRITE(HDMI_CEC_CNTRL_3,
+			   ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
+			   ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
+			   ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
+			   ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
+		HDMI_WRITE(HDMI_CEC_CNTRL_4,
+			   ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
+			   ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
+			   ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
+			   ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
+
+		HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
 	} else {
-		HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
+		HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
 			   VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
 	}
 	return 0;
@@ -1141,8 +1104,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
 	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
-		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
+	HDMI_WRITE(HDMI_CEC_CNTRL_1,
+		   (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
 		   (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
 	return 0;
 }
@@ -1155,20 +1118,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 	unsigned int i;
 
 	for (i = 0; i < msg->len; i += 4)
-		HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
+		HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i,
 			   (msg->msg[i]) |
 			   (msg->msg[i + 1] << 8) |
 			   (msg->msg[i + 2] << 16) |
 			   (msg->msg[i + 3] << 24));
 
-	val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
+	val = HDMI_READ(HDMI_CEC_CNTRL_1);
 	val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
 	val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
 	val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
 	val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
 
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
 	return 0;
 }
 
@@ -1179,6 +1142,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 };
 #endif
 
+static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
+				 struct debugfs_regset32 *regset,
+				 enum vc4_hdmi_regs reg)
+{
+	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+	struct debugfs_reg32 *regs, *new_regs;
+	unsigned int count = 0;
+	unsigned int i;
+
+	regs = kcalloc(variant->num_registers, sizeof(*regs),
+		       GFP_KERNEL);
+	if (!regs)
+		return -ENOMEM;
+
+	for (i = 0; i < variant->num_registers; i++) {
+		const struct vc4_hdmi_register *field =	&variant->registers[i];
+
+		if (field->reg != reg)
+			continue;
+
+		regs[count].name = field->name;
+		regs[count].offset = field->offset;
+		count++;
+	}
+
+	new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
+	if (!new_regs)
+		return -ENOMEM;
+
+	regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
+	regset->regs = new_regs;
+	regset->nregs = count;
+
+	return 0;
+}
+
 static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 {
 	struct platform_device *pdev = vc4_hdmi->pdev;
@@ -1193,13 +1192,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 	if (IS_ERR(vc4_hdmi->hd_regs))
 		return PTR_ERR(vc4_hdmi->hd_regs);
 
-	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
-	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
-	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+	ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
+	if (ret)
+		return ret;
 
-	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
-	vc4_hdmi->hd_regset.regs = hd_regs;
-	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
+	ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
+	if (ret)
+		return ret;
 
 	vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
 	if (IS_ERR(vc4_hdmi->pixel_clock)) {
@@ -1294,12 +1293,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 
 	/* HDMI core must be enabled. */
-	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
-		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
+	if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
+		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
 		udelay(1);
-		HD_WRITE(VC4_HD_M_CTL, 0);
+		HDMI_WRITE(HDMI_M_CTL, 0);
 
-		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
+		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
 	}
 	pm_runtime_enable(dev);
 
@@ -1322,8 +1321,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
 	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
-	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
-	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
+	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
+	value = HDMI_READ(HDMI_CEC_CNTRL_1);
 	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
 	/*
 	 * Set the logical address to Unregistered and set the clock
@@ -1332,7 +1331,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	 */
 	value |= VC4_HDMI_CEC_ADDR_MASK |
 		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
 	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
 					vc4_cec_irq_handler,
 					vc4_cec_irq_handler_thread, 0,
@@ -1395,6 +1394,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
 	vc4_hdmi = dev_get_drvdata(dev);
 
+	kfree(vc4_hdmi->hdmi_regset.regs);
+	kfree(vc4_hdmi->hd_regset.regs);
+
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
@@ -1422,6 +1424,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
+	.registers		= vc4_hdmi_fields,
+	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
+
 	.init_resources		= vc4_hdmi_init_resources,
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0eaf979fe811..b36e0210671f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_hdmi;
+struct vc4_hdmi_register;
 
 struct vc4_hdmi_variant {
+	/* List of the registers available on that variant */
+	const struct vc4_hdmi_register *registers;
+
+	/* Number of registers on that variant */
+	unsigned int num_registers;
+
 	/* Callback to get the resources (memory region, interrupts,
 	 * clocks, etc) for that variant.
 	 */
@@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
-#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
-
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
new file mode 100644
index 000000000000..bc47cc9bc883
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -0,0 +1,241 @@
+#ifndef _VC4_HDMI_REGS_H_
+#define _VC4_HDMI_REGS_H_
+
+#include "vc4_hdmi.h"
+
+#define VC4_HDMI_PACKET_STRIDE			0x24
+
+enum vc4_hdmi_regs {
+	VC4_INVALID = 0,
+	VC4_HDMI,
+	VC4_HD,
+};
+
+enum vc4_hdmi_field {
+	HDMI_AUDIO_PACKET_CONFIG,
+	HDMI_CEC_CNTRL_1,
+	HDMI_CEC_CNTRL_2,
+	HDMI_CEC_CNTRL_3,
+	HDMI_CEC_CNTRL_4,
+	HDMI_CEC_CNTRL_5,
+	HDMI_CEC_CPU_CLEAR,
+	HDMI_CEC_CPU_MASK_CLEAR,
+	HDMI_CEC_CPU_MASK_SET,
+	HDMI_CEC_CPU_MASK_STATUS,
+	HDMI_CEC_CPU_STATUS,
+
+	/*
+	 * Transmit data, first byte is low byte of the 32-bit reg.
+	 * MSB of each byte transmitted first.
+	 */
+	HDMI_CEC_RX_DATA_1,
+	HDMI_CEC_RX_DATA_2,
+	HDMI_CEC_RX_DATA_3,
+	HDMI_CEC_RX_DATA_4,
+	HDMI_CEC_TX_DATA_1,
+	HDMI_CEC_TX_DATA_2,
+	HDMI_CEC_TX_DATA_3,
+	HDMI_CEC_TX_DATA_4,
+	HDMI_CORE_REV,
+	HDMI_CRP_CFG,
+	HDMI_CSC_12_11,
+	HDMI_CSC_14_13,
+	HDMI_CSC_22_21,
+	HDMI_CSC_24_23,
+	HDMI_CSC_32_31,
+	HDMI_CSC_34_33,
+	HDMI_CSC_CTL,
+
+	/*
+	 * 20-bit fields containing CTS values to be transmitted if
+	 * !EXTERNAL_CTS_EN
+	 */
+	HDMI_CTS_0,
+	HDMI_CTS_1,
+	HDMI_FIFO_CTL,
+	HDMI_FRAME_COUNT,
+	HDMI_HORZA,
+	HDMI_HORZB,
+	HDMI_HOTPLUG,
+	HDMI_HOTPLUG_INT,
+
+	/*
+	 * 3 bits per field, where each field maps from that
+	 * corresponding MAI bus channel to the given HDMI channel.
+	 */
+	HDMI_MAI_CHANNEL_MAP,
+	HDMI_MAI_CONFIG,
+	HDMI_MAI_CTL,
+
+	/*
+	 * Register for DMAing in audio data to be transported over
+	 * the MAI bus to the Falcon core.
+	 */
+	HDMI_MAI_DATA,
+
+	/* Format header to be placed on the MAI data. Unused. */
+	HDMI_MAI_FMT,
+
+	/* Last received format word on the MAI bus. */
+	HDMI_MAI_FORMAT,
+	HDMI_MAI_SMP,
+	HDMI_MAI_THR,
+	HDMI_M_CTL,
+	HDMI_RAM_PACKET_CONFIG,
+	HDMI_RAM_PACKET_START,
+	HDMI_RAM_PACKET_STATUS,
+	HDMI_SCHEDULER_CONTROL,
+	HDMI_SW_RESET_CONTROL,
+	HDMI_TX_PHY_CTL_0,
+	HDMI_TX_PHY_RESET_CTL,
+	HDMI_VERTA0,
+	HDMI_VERTA1,
+	HDMI_VERTB0,
+	HDMI_VERTB1,
+	HDMI_VID_CTL,
+};
+
+struct vc4_hdmi_register {
+	char *name;
+	enum vc4_hdmi_regs reg;
+	unsigned int offset;
+};
+
+#define _VC4_REG(_base, _reg, _offset)	\
+	[_reg] = {				\
+		.name = #_reg,			\
+		.reg = _base,			\
+		.offset = _offset,		\
+	}
+
+#define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
+#define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
+
+static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
+	VC4_HD_REG(HDMI_M_CTL, 0x000c),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0018),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x001c),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x0020),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x002c),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0038),
+	VC4_HD_REG(HDMI_CSC_CTL, 0x0040),
+	VC4_HD_REG(HDMI_CSC_12_11, 0x0044),
+	VC4_HD_REG(HDMI_CSC_14_13, 0x0048),
+	VC4_HD_REG(HDMI_CSC_22_21, 0x004c),
+	VC4_HD_REG(HDMI_CSC_24_23, 0x0050),
+	VC4_HD_REG(HDMI_CSC_32_31, 0x0054),
+	VC4_HD_REG(HDMI_CSC_34_33, 0x0058),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068),
+
+	VC4_HDMI_REG(HDMI_CORE_REV, 0x0000),
+	VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004),
+	VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c),
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094),
+	VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x00ac),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x00b0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x00c4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x00c8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x00cc),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x00d0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x00d4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x00d8),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118),
+	VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0),
+	VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4),
+	VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340),
+	VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
+};
+
+static inline
+void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
+					enum vc4_hdmi_regs reg)
+{
+	switch (reg) {
+	case VC4_HD:
+		return hdmi->hd_regs;
+
+	case VC4_HDMI:
+		return hdmi->hdmicore_regs;
+
+	default:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
+				enum vc4_hdmi_regs reg)
+{
+	const struct vc4_hdmi_register *field;
+	const struct vc4_hdmi_variant *variant = hdmi->variant;
+	void __iomem *base;
+
+	if (reg > variant->num_registers) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Invalid register ID %u\n", reg);
+		return 0;
+	}
+
+	field = &variant->registers[reg];
+	base = __vc4_hdmi_get_field_base(hdmi, field->reg);
+	if (!base) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Unknown register ID %u\n", reg);
+		return 0;
+	}
+
+	return readl(base + field->offset);
+}
+#define HDMI_READ(reg)		vc4_hdmi_read(vc4_hdmi, reg)
+
+static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
+				  enum vc4_hdmi_regs reg,
+				  u32 value)
+{
+	const struct vc4_hdmi_register *field;
+	const struct vc4_hdmi_variant *variant = hdmi->variant;
+	void __iomem *base;
+
+	if (reg > variant->num_registers) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Invalid register ID %u\n", reg);
+		return;
+	}
+
+	field = &variant->registers[reg];
+	base = __vc4_hdmi_get_field_base(hdmi, field->reg);
+	if (!base)
+		return;
+
+	writel(value, base + field->offset);
+}
+#define HDMI_WRITE(reg, val)	vc4_hdmi_write(vc4_hdmi, reg, val)
+
+#endif /* _VC4_HDMI_REGS_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index c0031ab19689..d1e8961edaa0 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -493,32 +493,16 @@
 
 #define SCALER5_DLIST_START			0x00004000
 
-#define VC4_HDMI_CORE_REV			0x000
-
-#define VC4_HDMI_SW_RESET_CONTROL		0x004
 # define VC4_HDMI_SW_RESET_FORMAT_DETECT	BIT(1)
 # define VC4_HDMI_SW_RESET_HDMI			BIT(0)
 
-#define VC4_HDMI_HOTPLUG_INT			0x008
-
-#define VC4_HDMI_HOTPLUG			0x00c
 # define VC4_HDMI_HOTPLUG_CONNECTED		BIT(0)
 
-/* 3 bits per field, where each field maps from that corresponding MAI
- * bus channel to the given HDMI channel.
- */
-#define VC4_HDMI_MAI_CHANNEL_MAP		0x090
-
-#define VC4_HDMI_MAI_CONFIG			0x094
 # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE		BIT(27)
 # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE		BIT(26)
 # define VC4_HDMI_MAI_CHANNEL_MASK_MASK			VC4_MASK(15, 0)
 # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT		0
 
-/* Last received format word on the MAI bus. */
-#define VC4_HDMI_MAI_FORMAT			0x098
-
-#define VC4_HDMI_AUDIO_PACKET_CONFIG		0x09c
 # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT		BIT(29)
 # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS	BIT(24)
 # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT		BIT(19)
@@ -532,12 +516,8 @@
 # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK			VC4_MASK(7, 0)
 # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT			0
 
-#define VC4_HDMI_RAM_PACKET_CONFIG		0x0a0
 # define VC4_HDMI_RAM_PACKET_ENABLE		BIT(16)
 
-#define VC4_HDMI_RAM_PACKET_STATUS		0x0a4
-
-#define VC4_HDMI_CRP_CFG			0x0a8
 /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
  * of pixel clock.
  */
@@ -551,23 +531,12 @@
 # define VC4_HDMI_CRP_CFG_N_MASK		VC4_MASK(19, 0)
 # define VC4_HDMI_CRP_CFG_N_SHIFT		0
 
-/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */
-#define VC4_HDMI_CTS_0				0x0ac
-#define VC4_HDMI_CTS_1				0x0b0
-/* 20-bit fields containing number of clocks to send CTS0/1 before
- * switching to the other one.
- */
-#define VC4_HDMI_CTS_PERIOD_0			0x0b4
-#define VC4_HDMI_CTS_PERIOD_1			0x0b8
-
-#define VC4_HDMI_HORZA				0x0c4
 # define VC4_HDMI_HORZA_VPOS			BIT(14)
 # define VC4_HDMI_HORZA_HPOS			BIT(13)
 /* Horizontal active pixels (hdisplay). */
 # define VC4_HDMI_HORZA_HAP_MASK		VC4_MASK(12, 0)
 # define VC4_HDMI_HORZA_HAP_SHIFT		0
 
-#define VC4_HDMI_HORZB				0x0c8
 /* Horizontal pack porch (htotal - hsync_end). */
 # define VC4_HDMI_HORZB_HBP_MASK		VC4_MASK(29, 20)
 # define VC4_HDMI_HORZB_HBP_SHIFT		20
@@ -578,7 +547,6 @@
 # define VC4_HDMI_HORZB_HFP_MASK		VC4_MASK(9, 0)
 # define VC4_HDMI_HORZB_HFP_SHIFT		0
 
-#define VC4_HDMI_FIFO_CTL			0x05c
 # define VC4_HDMI_FIFO_CTL_RECENTER_DONE	BIT(14)
 # define VC4_HDMI_FIFO_CTL_USE_EMPTY		BIT(13)
 # define VC4_HDMI_FIFO_CTL_ON_VB		BIT(7)
@@ -591,15 +559,12 @@
 # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N	BIT(0)
 # define VC4_HDMI_FIFO_VALID_WRITE_MASK		0xefff
 
-#define VC4_HDMI_SCHEDULER_CONTROL		0x0c0
 # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
 # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
 # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT	BIT(3)
 # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE	BIT(1)
 # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI	BIT(0)
 
-#define VC4_HDMI_VERTA0				0x0cc
-#define VC4_HDMI_VERTA1				0x0d4
 /* Vertical sync pulse (vsync_end - vsync_start). */
 # define VC4_HDMI_VERTA_VSP_MASK		VC4_MASK(24, 20)
 # define VC4_HDMI_VERTA_VSP_SHIFT		20
@@ -610,8 +575,6 @@
 # define VC4_HDMI_VERTA_VAL_MASK		VC4_MASK(12, 0)
 # define VC4_HDMI_VERTA_VAL_SHIFT		0
 
-#define VC4_HDMI_VERTB0				0x0d0
-#define VC4_HDMI_VERTB1				0x0d8
 /* Vertical sync pulse offset (for interlaced) */
 # define VC4_HDMI_VERTB_VSPO_MASK		VC4_MASK(21, 9)
 # define VC4_HDMI_VERTB_VSPO_SHIFT		9
@@ -619,7 +582,6 @@
 # define VC4_HDMI_VERTB_VBP_MASK		VC4_MASK(8, 0)
 # define VC4_HDMI_VERTB_VBP_SHIFT		0
 
-#define VC4_HDMI_CEC_CNTRL_1			0x0e8
 /* Set when the transmission has ended. */
 # define VC4_HDMI_CEC_TX_EOM			BIT(31)
 /* If set, transmission was acked on the 1st or 2nd attempt (only one
@@ -660,7 +622,6 @@
 /* Set these fields to how many bit clock cycles get to that many
  * microseconds.
  */
-#define VC4_HDMI_CEC_CNTRL_2			0x0ec
 # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK	VC4_MASK(30, 24)
 # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK	VC4_MASK(23, 17)
@@ -672,7 +633,6 @@
 # define VC4_HDMI_CEC_CNT_TO_400_US_MASK	VC4_MASK(4, 0)
 # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_3			0x0f0
 # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK	VC4_MASK(31, 24)
 # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK	VC4_MASK(23, 16)
@@ -682,7 +642,6 @@
 # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_4			0x0f4
 # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK	VC4_MASK(31, 24)
 # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK	VC4_MASK(23, 16)
@@ -692,7 +651,6 @@
 # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_5			0x0f8
 # define VC4_HDMI_CEC_TX_SW_RESET		BIT(27)
 # define VC4_HDMI_CEC_RX_SW_RESET		BIT(26)
 # define VC4_HDMI_CEC_PAD_SW_RESET		BIT(25)
@@ -705,39 +663,11 @@
 # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT	0
 
-/* Transmit data, first byte is low byte of the 32-bit reg.  MSB of
- * each byte transmitted first.
- */
-#define VC4_HDMI_CEC_TX_DATA_1			0x0fc
-#define VC4_HDMI_CEC_TX_DATA_2			0x100
-#define VC4_HDMI_CEC_TX_DATA_3			0x104
-#define VC4_HDMI_CEC_TX_DATA_4			0x108
-#define VC4_HDMI_CEC_RX_DATA_1			0x10c
-#define VC4_HDMI_CEC_RX_DATA_2			0x110
-#define VC4_HDMI_CEC_RX_DATA_3			0x114
-#define VC4_HDMI_CEC_RX_DATA_4			0x118
-
-#define VC4_HDMI_TX_PHY_RESET_CTL		0x2c0
-
-#define VC4_HDMI_TX_PHY_CTL0			0x2c4
 # define VC4_HDMI_TX_PHY_RNG_PWRDN		BIT(25)
 
-/* Interrupt status bits */
-#define VC4_HDMI_CPU_STATUS			0x340
-#define VC4_HDMI_CPU_SET			0x344
-#define VC4_HDMI_CPU_CLEAR			0x348
 # define VC4_HDMI_CPU_CEC			BIT(6)
 # define VC4_HDMI_CPU_HOTPLUG			BIT(0)
 
-#define VC4_HDMI_CPU_MASK_STATUS		0x34c
-#define VC4_HDMI_CPU_MASK_SET			0x350
-#define VC4_HDMI_CPU_MASK_CLEAR			0x354
-
-#define VC4_HDMI_GCP(x)				(0x400 + ((x) * 0x4))
-#define VC4_HDMI_RAM_PACKET(x)			(0x400 + ((x) * 0x24))
-#define VC4_HDMI_PACKET_STRIDE			0x24
-
-#define VC4_HD_M_CTL				0x00c
 /* Debug: Current receive value on the CEC pad. */
 # define VC4_HD_CECRXD				BIT(9)
 /* Debug: Override CEC output to 0. */
@@ -747,7 +677,6 @@
 # define VC4_HD_M_SW_RST			BIT(2)
 # define VC4_HD_M_ENABLE			BIT(0)
 
-#define VC4_HD_MAI_CTL				0x014
 /* Set when audio stream is received at a slower rate than the
  * sampling period, so MAI fifo goes empty.  Write 1 to clear.
  */
@@ -772,7 +701,6 @@
 /* Single-shot reset bit.  Read value is undefined. */
 # define VC4_HD_MAI_CTL_RESET			BIT(0)
 
-#define VC4_HD_MAI_THR				0x018
 # define VC4_HD_MAI_THR_PANICHIGH_MASK		VC4_MASK(29, 24)
 # define VC4_HD_MAI_THR_PANICHIGH_SHIFT		24
 # define VC4_HD_MAI_THR_PANICLOW_MASK		VC4_MASK(21, 16)
@@ -782,31 +710,20 @@
 # define VC4_HD_MAI_THR_DREQLOW_MASK		VC4_MASK(5, 0)
 # define VC4_HD_MAI_THR_DREQLOW_SHIFT		0
 
-/* Format header to be placed on the MAI data. Unused. */
-#define VC4_HD_MAI_FMT				0x01c
-
-/* Register for DMAing in audio data to be transported over the MAI
- * bus to the Falcon core.
- */
-#define VC4_HD_MAI_DATA				0x020
-
 /* Divider from HDMI HSM clock to MAI serial clock.  Sampling period
  * converges to N / (M + 1) cycles.
  */
-#define VC4_HD_MAI_SMP				0x02c
 # define VC4_HD_MAI_SMP_N_MASK			VC4_MASK(31, 8)
 # define VC4_HD_MAI_SMP_N_SHIFT			8
 # define VC4_HD_MAI_SMP_M_MASK			VC4_MASK(7, 0)
 # define VC4_HD_MAI_SMP_M_SHIFT			0
 
-#define VC4_HD_VID_CTL				0x038
 # define VC4_HD_VID_CTL_ENABLE			BIT(31)
 # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE	BIT(30)
 # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET	BIT(29)
 # define VC4_HD_VID_CTL_VSYNC_LOW		BIT(28)
 # define VC4_HD_VID_CTL_HSYNC_LOW		BIT(27)
 
-#define VC4_HD_CSC_CTL				0x040
 # define VC4_HD_CSC_CTL_ORDER_MASK		VC4_MASK(7, 5)
 # define VC4_HD_CSC_CTL_ORDER_SHIFT		5
 # define VC4_HD_CSC_CTL_ORDER_RGB		0
@@ -824,15 +741,6 @@
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
 
-#define VC4_HD_CSC_12_11			0x044
-#define VC4_HD_CSC_14_13			0x048
-#define VC4_HD_CSC_22_21			0x04c
-#define VC4_HD_CSC_24_23			0x050
-#define VC4_HD_CSC_32_31			0x054
-#define VC4_HD_CSC_34_33			0x058
-
-#define VC4_HD_FRAME_COUNT			0x068
-
 /* HVS display list information. */
 #define HVS_BOOTLOADER_DLIST_END                32
 
-- 
git-series 0.9.1

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

* [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI controllers found in the BCM2711 have most of the registers
reorganized in multiple registers areas and at different offsets than
previously found.

The logic however remains pretty much the same, so it doesn't really make
sense to create a whole new driver and we should share the code as much as
possible.

Let's implement some indirection to wrap around a register and depending on
the variant will lookup the associated register on that particular variant.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 427 ++++++++++++++---------------
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  12 +-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h      |  92 +------
 4 files changed, 464 insertions(+), 308 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ac021e07a8cb..a4fed1439bf3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -50,62 +50,13 @@
 #include "media/cec.h"
 #include "vc4_drv.h"
 #include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
-static const struct debugfs_reg32 hdmi_regs[] = {
-	VC4_REG32(VC4_HDMI_CORE_REV),
-	VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
-	VC4_REG32(VC4_HDMI_HOTPLUG_INT),
-	VC4_REG32(VC4_HDMI_HOTPLUG),
-	VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
-	VC4_REG32(VC4_HDMI_MAI_CONFIG),
-	VC4_REG32(VC4_HDMI_MAI_FORMAT),
-	VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
-	VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
-	VC4_REG32(VC4_HDMI_HORZA),
-	VC4_REG32(VC4_HDMI_HORZB),
-	VC4_REG32(VC4_HDMI_FIFO_CTL),
-	VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
-	VC4_REG32(VC4_HDMI_VERTA0),
-	VC4_REG32(VC4_HDMI_VERTA1),
-	VC4_REG32(VC4_HDMI_VERTB0),
-	VC4_REG32(VC4_HDMI_VERTB1),
-	VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
-	VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
-
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
-	VC4_REG32(VC4_HDMI_CPU_STATUS),
-	VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
-
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
-};
-
-static const struct debugfs_reg32 hd_regs[] = {
-	VC4_REG32(VC4_HD_M_CTL),
-	VC4_REG32(VC4_HD_MAI_CTL),
-	VC4_REG32(VC4_HD_MAI_THR),
-	VC4_REG32(VC4_HD_MAI_FMT),
-	VC4_REG32(VC4_HD_MAI_SMP),
-	VC4_REG32(VC4_HD_VID_CTL),
-	VC4_REG32(VC4_HD_CSC_CTL),
-	VC4_REG32(VC4_HD_FRAME_COUNT),
-};
-
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	if (drm_probe_ddc(vc4_hdmi->ddc))
 		return connector_status_connected;
 
-	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
+	if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
 		return connector_status_connected;
 	cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 	return connector_status_disconnected;
@@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = type - 0x80;
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+		   HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
 
-	return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
+	return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
 			  BIT(packet_id)), 100);
 }
 
@@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = frame->any.type - 0x80;
-	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
+	const struct vc4_hdmi_register *ram_packet_start =
+		&vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
+	u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
+	void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
+						       ram_packet_start->reg);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
 	ssize_t len, i;
 	int ret;
 
-	WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+	WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 		    VC4_HDMI_RAM_PACKET_ENABLE),
 		  "Packet RAM has to be on to store the packet.");
 
@@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 	}
 
 	for (i = 0; i < len; i += 7) {
-		HDMI_WRITE(packet_reg,
-			   buffer[i + 0] << 0 |
-			   buffer[i + 1] << 8 |
-			   buffer[i + 2] << 16);
+		writel(buffer[i + 0] << 0 |
+		       buffer[i + 1] << 8 |
+		       buffer[i + 2] << 16,
+		       base + packet_reg);
 		packet_reg += 4;
 
-		HDMI_WRITE(packet_reg,
-			   buffer[i + 3] << 0 |
-			   buffer[i + 4] << 8 |
-			   buffer[i + 5] << 16 |
-			   buffer[i + 6] << 24);
+		writel(buffer[i + 3] << 0 |
+		       buffer[i + 4] << 8 |
+		       buffer[i + 5] << 16 |
+		       buffer[i + 6] << 24,
+		       base + packet_reg);
 		packet_reg += 4;
 	}
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
-	ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+		   HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
+	ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
 			BIT(packet_id)), 100);
 	if (ret)
 		DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
@@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-	HD_WRITE(VC4_HD_VID_CTL,
-		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
 	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
@@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
 		   VC4_HDMI_SW_RESET_HDMI |
 		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
 
-	HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
 	 */
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
 
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
-	HD_WRITE(VC4_HD_VID_CTL, 0);
+	HDMI_WRITE(HDMI_VID_CTL, 0);
 
-	HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-		   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
-	HDMI_WRITE(VC4_HDMI_HORZA,
+	HDMI_WRITE(HDMI_HORZA,
 		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
 		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
 		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
 				 VC4_HDMI_HORZA_HAP));
 
-	HDMI_WRITE(VC4_HDMI_HORZB,
+	HDMI_WRITE(HDMI_HORZB,
 		   VC4_SET_FIELD((mode->htotal -
 				  mode->hsync_end) * pixel_rep,
 				 VC4_HDMI_HORZB_HBP) |
@@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 				  mode->hdisplay) * pixel_rep,
 				 VC4_HDMI_HORZB_HFP));
 
-	HDMI_WRITE(VC4_HDMI_VERTA0, verta);
-	HDMI_WRITE(VC4_HDMI_VERTA1, verta);
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
 
-	HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
-	HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
 
-	HD_WRITE(VC4_HD_VID_CTL,
-		 (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		 (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+	HDMI_WRITE(HDMI_VID_CTL,
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
 	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
 				VC4_HD_CSC_CTL_ORDER);
@@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
 					 VC4_HD_CSC_CTL_MODE);
 
-		HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
-		HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
-		HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
 		vc4_encoder->limited_rgb_range = true;
 	} else {
 		vc4_encoder->limited_rgb_range = false;
 	}
 
 	/* The RGB order applies even when CSC is disabled. */
-	HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 
-	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
-	HD_WRITE(VC4_HD_VID_CTL,
-		 HD_READ(VC4_HD_VID_CTL) |
-		 VC4_HD_VID_CTL_ENABLE |
-		 VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
-		 VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) |
+		   VC4_HD_VID_CTL_ENABLE |
+		   VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
+		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
 
 	if (vc4_encoder->hdmi_monitor) {
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 			   VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
-		ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 	} else {
-		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-			   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+			   HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 			   ~(VC4_HDMI_RAM_PACKET_ENABLE));
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			   ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
-		ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
@@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_encoder->hdmi_monitor) {
 		u32 drift;
 
-		WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 			   VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
 
-		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
+		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 			   VC4_HDMI_RAM_PACKET_ENABLE);
 
 		vc4_hdmi_set_infoframes(encoder);
 
-		drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
+		drift = HDMI_READ(HDMI_FIFO_CTL);
 		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
 
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
 		usleep_range(1000, 1100);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
 
-		ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
+		ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
 			       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
@@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 				     VC4_HD_MAI_SMP_M_SHIFT) + 1,
 				    &n, &m);
 
-	HD_WRITE(VC4_HD_MAI_SMP,
-		 VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
-		 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
+	HDMI_WRITE(HDMI_MAI_SMP,
+		   VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
+		   VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
 }
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
@@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 	do_div(tmp, 128 * samplerate);
 	cts = tmp;
 
-	HDMI_WRITE(VC4_HDMI_CRP_CFG,
+	HDMI_WRITE(HDMI_CRP_CFG,
 		   VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
 		   VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
 
@@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 	 * providing a CTS_1 value.  The two CTS values are alternated
 	 * between based on the period fields
 	 */
-	HDMI_WRITE(VC4_HDMI_CTS_0, cts);
-	HDMI_WRITE(VC4_HDMI_CTS_1, cts);
+	HDMI_WRITE(HDMI_CTS_0, cts);
+	HDMI_WRITE(HDMI_CTS_1, cts);
 }
 
 static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
@@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 	 * If the HDMI encoder hasn't probed, or the encoder is
 	 * currently in DVI mode, treat the codec dai as missing.
 	 */
-	if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+	if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
@@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 	if (ret)
 		dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
 
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
 }
 
 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
@@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 	vc4_hdmi->audio.channels = params_channels(params);
 	vc4_hdmi->audio.samplerate = params_rate(params);
 
-	HD_WRITE(VC4_HD_MAI_CTL,
-		 VC4_HD_MAI_CTL_RESET |
-		 VC4_HD_MAI_CTL_FLUSH |
-		 VC4_HD_MAI_CTL_DLATE |
-		 VC4_HD_MAI_CTL_ERRORE |
-		 VC4_HD_MAI_CTL_ERRORF);
+	HDMI_WRITE(HDMI_MAI_CTL,
+		   VC4_HD_MAI_CTL_RESET |
+		   VC4_HD_MAI_CTL_FLUSH |
+		   VC4_HD_MAI_CTL_DLATE |
+		   VC4_HD_MAI_CTL_ERRORE |
+		   VC4_HD_MAI_CTL_ERRORF);
 
 	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
@@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	/* Set the MAI threshold.  This logic mimics the firmware's. */
 	if (vc4_hdmi->audio.samplerate > 96000) {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
 	} else if (vc4_hdmi->audio.samplerate > 48000) {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
 	} else {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
 	}
 
-	HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
+	HDMI_WRITE(HDMI_MAI_CONFIG,
 		   VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
 		   VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
 
@@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 			channel_map |= i << (3 * i);
 	}
 
-	HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
-	HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
+	HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
+	HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
 	vc4_hdmi_set_n_cts(vc4_hdmi);
 
 	return 0;
@@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
-		HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
-			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
+		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+			   HDMI_READ(HDMI_TX_PHY_CTL_0) &
 			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
-		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_SET_FIELD(vc4_hdmi->audio.channels,
-				       VC4_HD_MAI_CTL_CHNUM) |
-			 VC4_HD_MAI_CTL_ENABLE);
+
+		HDMI_WRITE(HDMI_MAI_CTL,
+			   VC4_SET_FIELD(vc4_hdmi->audio.channels,
+					 VC4_HD_MAI_CTL_CHNUM) |
+			   VC4_HD_MAI_CTL_ENABLE);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_HD_MAI_CTL_DLATE |
-			 VC4_HD_MAI_CTL_ERRORE |
-			 VC4_HD_MAI_CTL_ERRORF);
-		HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
-			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
+		HDMI_WRITE(HDMI_MAI_CTL,
+			   VC4_HD_MAI_CTL_DLATE |
+			   VC4_HD_MAI_CTL_ERRORE |
+			   VC4_HD_MAI_CTL_ERRORF);
+		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+			   HDMI_READ(HDMI_TX_PHY_CTL_0) |
 			   VC4_HDMI_TX_PHY_RNG_PWRDN);
 		break;
 	default:
@@ -946,6 +902,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
 
 static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
+	const struct vc4_hdmi_register *mai_data =
+		&vc4_hdmi->variant->registers[HDMI_MAI_DATA];
 	struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
 	struct snd_soc_card *card = &vc4_hdmi->audio.card;
 	struct device *dev = &vc4_hdmi->pdev->dev;
@@ -958,6 +916,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 		return 0;
 	}
 
+	if (mai_data->reg != VC4_HD) {
+		WARN_ONCE(true, "MAI isn't in the HD block\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve
 	 * the bus address specified in the DT, because the physical address
@@ -966,7 +929,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
 	addr = of_get_address(dev->of_node, 1, NULL, NULL);
-	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
+	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
 	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	vc4_hdmi->audio.dma_data.maxburst = 2;
 
@@ -1058,7 +1021,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 	msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
 					VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
 	for (i = 0; i < msg->len; i += 4) {
-		u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
+		u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i);
 
 		msg->msg[i] = val & 0xff;
 		msg->msg[i + 1] = (val >> 8) & 0xff;
@@ -1070,26 +1033,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
 	struct vc4_hdmi *vc4_hdmi = priv;
-	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
+	u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
 	if (!(stat & VC4_HDMI_CPU_CEC))
 		return IRQ_NONE;
 	vc4_hdmi->cec_rx_msg.len = 0;
-	cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
-	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
+	cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
+	cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
 	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
 	if (vc4_hdmi->cec_irq_was_rx) {
 		vc4_cec_read_msg(vc4_hdmi, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
+		HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 	} else {
 		vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
 		cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
 	}
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
-	HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
+	HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
 
 	return IRQ_WAKE_THREAD;
 }
@@ -1099,7 +1062,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
-	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
+	u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
 
 	val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
 		 VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
@@ -1108,30 +1071,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 	       ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
 
 	if (enable) {
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
 			   VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
-			 ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
-			 ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
-			 ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
-			 ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
-			 ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
-			 ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
-			 ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
-			 ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
-			 ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
-			 ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
-			 ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
-			 ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
-			 ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
-
-		HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
+		HDMI_WRITE(HDMI_CEC_CNTRL_2,
+			   ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
+			   ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
+			   ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
+			   ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
+			   ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
+		HDMI_WRITE(HDMI_CEC_CNTRL_3,
+			   ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
+			   ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
+			   ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
+			   ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
+		HDMI_WRITE(HDMI_CEC_CNTRL_4,
+			   ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
+			   ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
+			   ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
+			   ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
+
+		HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
 	} else {
-		HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
+		HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
 			   VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
 	}
 	return 0;
@@ -1141,8 +1104,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
 	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
-		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
+	HDMI_WRITE(HDMI_CEC_CNTRL_1,
+		   (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
 		   (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
 	return 0;
 }
@@ -1155,20 +1118,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 	unsigned int i;
 
 	for (i = 0; i < msg->len; i += 4)
-		HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
+		HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i,
 			   (msg->msg[i]) |
 			   (msg->msg[i + 1] << 8) |
 			   (msg->msg[i + 2] << 16) |
 			   (msg->msg[i + 3] << 24));
 
-	val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
+	val = HDMI_READ(HDMI_CEC_CNTRL_1);
 	val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
 	val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
 	val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
 	val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
 
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
 	return 0;
 }
 
@@ -1179,6 +1142,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 };
 #endif
 
+static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
+				 struct debugfs_regset32 *regset,
+				 enum vc4_hdmi_regs reg)
+{
+	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+	struct debugfs_reg32 *regs, *new_regs;
+	unsigned int count = 0;
+	unsigned int i;
+
+	regs = kcalloc(variant->num_registers, sizeof(*regs),
+		       GFP_KERNEL);
+	if (!regs)
+		return -ENOMEM;
+
+	for (i = 0; i < variant->num_registers; i++) {
+		const struct vc4_hdmi_register *field =	&variant->registers[i];
+
+		if (field->reg != reg)
+			continue;
+
+		regs[count].name = field->name;
+		regs[count].offset = field->offset;
+		count++;
+	}
+
+	new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
+	if (!new_regs)
+		return -ENOMEM;
+
+	regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
+	regset->regs = new_regs;
+	regset->nregs = count;
+
+	return 0;
+}
+
 static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 {
 	struct platform_device *pdev = vc4_hdmi->pdev;
@@ -1193,13 +1192,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 	if (IS_ERR(vc4_hdmi->hd_regs))
 		return PTR_ERR(vc4_hdmi->hd_regs);
 
-	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
-	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
-	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+	ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
+	if (ret)
+		return ret;
 
-	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
-	vc4_hdmi->hd_regset.regs = hd_regs;
-	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
+	ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
+	if (ret)
+		return ret;
 
 	vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
 	if (IS_ERR(vc4_hdmi->pixel_clock)) {
@@ -1294,12 +1293,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 
 	/* HDMI core must be enabled. */
-	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
-		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
+	if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
+		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
 		udelay(1);
-		HD_WRITE(VC4_HD_M_CTL, 0);
+		HDMI_WRITE(HDMI_M_CTL, 0);
 
-		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
+		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
 	}
 	pm_runtime_enable(dev);
 
@@ -1322,8 +1321,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
 	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
-	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
-	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
+	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
+	value = HDMI_READ(HDMI_CEC_CNTRL_1);
 	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
 	/*
 	 * Set the logical address to Unregistered and set the clock
@@ -1332,7 +1331,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	 */
 	value |= VC4_HDMI_CEC_ADDR_MASK |
 		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
 	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
 					vc4_cec_irq_handler,
 					vc4_cec_irq_handler_thread, 0,
@@ -1395,6 +1394,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
 	vc4_hdmi = dev_get_drvdata(dev);
 
+	kfree(vc4_hdmi->hdmi_regset.regs);
+	kfree(vc4_hdmi->hd_regset.regs);
+
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
@@ -1422,6 +1424,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
+	.registers		= vc4_hdmi_fields,
+	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
+
 	.init_resources		= vc4_hdmi_init_resources,
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0eaf979fe811..b36e0210671f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_hdmi;
+struct vc4_hdmi_register;
 
 struct vc4_hdmi_variant {
+	/* List of the registers available on that variant */
+	const struct vc4_hdmi_register *registers;
+
+	/* Number of registers on that variant */
+	unsigned int num_registers;
+
 	/* Callback to get the resources (memory region, interrupts,
 	 * clocks, etc) for that variant.
 	 */
@@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
-#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
-
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
new file mode 100644
index 000000000000..bc47cc9bc883
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -0,0 +1,241 @@
+#ifndef _VC4_HDMI_REGS_H_
+#define _VC4_HDMI_REGS_H_
+
+#include "vc4_hdmi.h"
+
+#define VC4_HDMI_PACKET_STRIDE			0x24
+
+enum vc4_hdmi_regs {
+	VC4_INVALID = 0,
+	VC4_HDMI,
+	VC4_HD,
+};
+
+enum vc4_hdmi_field {
+	HDMI_AUDIO_PACKET_CONFIG,
+	HDMI_CEC_CNTRL_1,
+	HDMI_CEC_CNTRL_2,
+	HDMI_CEC_CNTRL_3,
+	HDMI_CEC_CNTRL_4,
+	HDMI_CEC_CNTRL_5,
+	HDMI_CEC_CPU_CLEAR,
+	HDMI_CEC_CPU_MASK_CLEAR,
+	HDMI_CEC_CPU_MASK_SET,
+	HDMI_CEC_CPU_MASK_STATUS,
+	HDMI_CEC_CPU_STATUS,
+
+	/*
+	 * Transmit data, first byte is low byte of the 32-bit reg.
+	 * MSB of each byte transmitted first.
+	 */
+	HDMI_CEC_RX_DATA_1,
+	HDMI_CEC_RX_DATA_2,
+	HDMI_CEC_RX_DATA_3,
+	HDMI_CEC_RX_DATA_4,
+	HDMI_CEC_TX_DATA_1,
+	HDMI_CEC_TX_DATA_2,
+	HDMI_CEC_TX_DATA_3,
+	HDMI_CEC_TX_DATA_4,
+	HDMI_CORE_REV,
+	HDMI_CRP_CFG,
+	HDMI_CSC_12_11,
+	HDMI_CSC_14_13,
+	HDMI_CSC_22_21,
+	HDMI_CSC_24_23,
+	HDMI_CSC_32_31,
+	HDMI_CSC_34_33,
+	HDMI_CSC_CTL,
+
+	/*
+	 * 20-bit fields containing CTS values to be transmitted if
+	 * !EXTERNAL_CTS_EN
+	 */
+	HDMI_CTS_0,
+	HDMI_CTS_1,
+	HDMI_FIFO_CTL,
+	HDMI_FRAME_COUNT,
+	HDMI_HORZA,
+	HDMI_HORZB,
+	HDMI_HOTPLUG,
+	HDMI_HOTPLUG_INT,
+
+	/*
+	 * 3 bits per field, where each field maps from that
+	 * corresponding MAI bus channel to the given HDMI channel.
+	 */
+	HDMI_MAI_CHANNEL_MAP,
+	HDMI_MAI_CONFIG,
+	HDMI_MAI_CTL,
+
+	/*
+	 * Register for DMAing in audio data to be transported over
+	 * the MAI bus to the Falcon core.
+	 */
+	HDMI_MAI_DATA,
+
+	/* Format header to be placed on the MAI data. Unused. */
+	HDMI_MAI_FMT,
+
+	/* Last received format word on the MAI bus. */
+	HDMI_MAI_FORMAT,
+	HDMI_MAI_SMP,
+	HDMI_MAI_THR,
+	HDMI_M_CTL,
+	HDMI_RAM_PACKET_CONFIG,
+	HDMI_RAM_PACKET_START,
+	HDMI_RAM_PACKET_STATUS,
+	HDMI_SCHEDULER_CONTROL,
+	HDMI_SW_RESET_CONTROL,
+	HDMI_TX_PHY_CTL_0,
+	HDMI_TX_PHY_RESET_CTL,
+	HDMI_VERTA0,
+	HDMI_VERTA1,
+	HDMI_VERTB0,
+	HDMI_VERTB1,
+	HDMI_VID_CTL,
+};
+
+struct vc4_hdmi_register {
+	char *name;
+	enum vc4_hdmi_regs reg;
+	unsigned int offset;
+};
+
+#define _VC4_REG(_base, _reg, _offset)	\
+	[_reg] = {				\
+		.name = #_reg,			\
+		.reg = _base,			\
+		.offset = _offset,		\
+	}
+
+#define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
+#define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
+
+static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
+	VC4_HD_REG(HDMI_M_CTL, 0x000c),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0018),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x001c),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x0020),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x002c),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0038),
+	VC4_HD_REG(HDMI_CSC_CTL, 0x0040),
+	VC4_HD_REG(HDMI_CSC_12_11, 0x0044),
+	VC4_HD_REG(HDMI_CSC_14_13, 0x0048),
+	VC4_HD_REG(HDMI_CSC_22_21, 0x004c),
+	VC4_HD_REG(HDMI_CSC_24_23, 0x0050),
+	VC4_HD_REG(HDMI_CSC_32_31, 0x0054),
+	VC4_HD_REG(HDMI_CSC_34_33, 0x0058),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068),
+
+	VC4_HDMI_REG(HDMI_CORE_REV, 0x0000),
+	VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004),
+	VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c),
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094),
+	VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x00ac),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x00b0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x00c4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x00c8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x00cc),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x00d0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x00d4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x00d8),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118),
+	VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0),
+	VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4),
+	VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340),
+	VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
+};
+
+static inline
+void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
+					enum vc4_hdmi_regs reg)
+{
+	switch (reg) {
+	case VC4_HD:
+		return hdmi->hd_regs;
+
+	case VC4_HDMI:
+		return hdmi->hdmicore_regs;
+
+	default:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
+				enum vc4_hdmi_regs reg)
+{
+	const struct vc4_hdmi_register *field;
+	const struct vc4_hdmi_variant *variant = hdmi->variant;
+	void __iomem *base;
+
+	if (reg > variant->num_registers) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Invalid register ID %u\n", reg);
+		return 0;
+	}
+
+	field = &variant->registers[reg];
+	base = __vc4_hdmi_get_field_base(hdmi, field->reg);
+	if (!base) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Unknown register ID %u\n", reg);
+		return 0;
+	}
+
+	return readl(base + field->offset);
+}
+#define HDMI_READ(reg)		vc4_hdmi_read(vc4_hdmi, reg)
+
+static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
+				  enum vc4_hdmi_regs reg,
+				  u32 value)
+{
+	const struct vc4_hdmi_register *field;
+	const struct vc4_hdmi_variant *variant = hdmi->variant;
+	void __iomem *base;
+
+	if (reg > variant->num_registers) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Invalid register ID %u\n", reg);
+		return;
+	}
+
+	field = &variant->registers[reg];
+	base = __vc4_hdmi_get_field_base(hdmi, field->reg);
+	if (!base)
+		return;
+
+	writel(value, base + field->offset);
+}
+#define HDMI_WRITE(reg, val)	vc4_hdmi_write(vc4_hdmi, reg, val)
+
+#endif /* _VC4_HDMI_REGS_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index c0031ab19689..d1e8961edaa0 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -493,32 +493,16 @@
 
 #define SCALER5_DLIST_START			0x00004000
 
-#define VC4_HDMI_CORE_REV			0x000
-
-#define VC4_HDMI_SW_RESET_CONTROL		0x004
 # define VC4_HDMI_SW_RESET_FORMAT_DETECT	BIT(1)
 # define VC4_HDMI_SW_RESET_HDMI			BIT(0)
 
-#define VC4_HDMI_HOTPLUG_INT			0x008
-
-#define VC4_HDMI_HOTPLUG			0x00c
 # define VC4_HDMI_HOTPLUG_CONNECTED		BIT(0)
 
-/* 3 bits per field, where each field maps from that corresponding MAI
- * bus channel to the given HDMI channel.
- */
-#define VC4_HDMI_MAI_CHANNEL_MAP		0x090
-
-#define VC4_HDMI_MAI_CONFIG			0x094
 # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE		BIT(27)
 # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE		BIT(26)
 # define VC4_HDMI_MAI_CHANNEL_MASK_MASK			VC4_MASK(15, 0)
 # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT		0
 
-/* Last received format word on the MAI bus. */
-#define VC4_HDMI_MAI_FORMAT			0x098
-
-#define VC4_HDMI_AUDIO_PACKET_CONFIG		0x09c
 # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT		BIT(29)
 # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS	BIT(24)
 # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT		BIT(19)
@@ -532,12 +516,8 @@
 # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK			VC4_MASK(7, 0)
 # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT			0
 
-#define VC4_HDMI_RAM_PACKET_CONFIG		0x0a0
 # define VC4_HDMI_RAM_PACKET_ENABLE		BIT(16)
 
-#define VC4_HDMI_RAM_PACKET_STATUS		0x0a4
-
-#define VC4_HDMI_CRP_CFG			0x0a8
 /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
  * of pixel clock.
  */
@@ -551,23 +531,12 @@
 # define VC4_HDMI_CRP_CFG_N_MASK		VC4_MASK(19, 0)
 # define VC4_HDMI_CRP_CFG_N_SHIFT		0
 
-/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */
-#define VC4_HDMI_CTS_0				0x0ac
-#define VC4_HDMI_CTS_1				0x0b0
-/* 20-bit fields containing number of clocks to send CTS0/1 before
- * switching to the other one.
- */
-#define VC4_HDMI_CTS_PERIOD_0			0x0b4
-#define VC4_HDMI_CTS_PERIOD_1			0x0b8
-
-#define VC4_HDMI_HORZA				0x0c4
 # define VC4_HDMI_HORZA_VPOS			BIT(14)
 # define VC4_HDMI_HORZA_HPOS			BIT(13)
 /* Horizontal active pixels (hdisplay). */
 # define VC4_HDMI_HORZA_HAP_MASK		VC4_MASK(12, 0)
 # define VC4_HDMI_HORZA_HAP_SHIFT		0
 
-#define VC4_HDMI_HORZB				0x0c8
 /* Horizontal pack porch (htotal - hsync_end). */
 # define VC4_HDMI_HORZB_HBP_MASK		VC4_MASK(29, 20)
 # define VC4_HDMI_HORZB_HBP_SHIFT		20
@@ -578,7 +547,6 @@
 # define VC4_HDMI_HORZB_HFP_MASK		VC4_MASK(9, 0)
 # define VC4_HDMI_HORZB_HFP_SHIFT		0
 
-#define VC4_HDMI_FIFO_CTL			0x05c
 # define VC4_HDMI_FIFO_CTL_RECENTER_DONE	BIT(14)
 # define VC4_HDMI_FIFO_CTL_USE_EMPTY		BIT(13)
 # define VC4_HDMI_FIFO_CTL_ON_VB		BIT(7)
@@ -591,15 +559,12 @@
 # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N	BIT(0)
 # define VC4_HDMI_FIFO_VALID_WRITE_MASK		0xefff
 
-#define VC4_HDMI_SCHEDULER_CONTROL		0x0c0
 # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
 # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
 # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT	BIT(3)
 # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE	BIT(1)
 # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI	BIT(0)
 
-#define VC4_HDMI_VERTA0				0x0cc
-#define VC4_HDMI_VERTA1				0x0d4
 /* Vertical sync pulse (vsync_end - vsync_start). */
 # define VC4_HDMI_VERTA_VSP_MASK		VC4_MASK(24, 20)
 # define VC4_HDMI_VERTA_VSP_SHIFT		20
@@ -610,8 +575,6 @@
 # define VC4_HDMI_VERTA_VAL_MASK		VC4_MASK(12, 0)
 # define VC4_HDMI_VERTA_VAL_SHIFT		0
 
-#define VC4_HDMI_VERTB0				0x0d0
-#define VC4_HDMI_VERTB1				0x0d8
 /* Vertical sync pulse offset (for interlaced) */
 # define VC4_HDMI_VERTB_VSPO_MASK		VC4_MASK(21, 9)
 # define VC4_HDMI_VERTB_VSPO_SHIFT		9
@@ -619,7 +582,6 @@
 # define VC4_HDMI_VERTB_VBP_MASK		VC4_MASK(8, 0)
 # define VC4_HDMI_VERTB_VBP_SHIFT		0
 
-#define VC4_HDMI_CEC_CNTRL_1			0x0e8
 /* Set when the transmission has ended. */
 # define VC4_HDMI_CEC_TX_EOM			BIT(31)
 /* If set, transmission was acked on the 1st or 2nd attempt (only one
@@ -660,7 +622,6 @@
 /* Set these fields to how many bit clock cycles get to that many
  * microseconds.
  */
-#define VC4_HDMI_CEC_CNTRL_2			0x0ec
 # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK	VC4_MASK(30, 24)
 # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK	VC4_MASK(23, 17)
@@ -672,7 +633,6 @@
 # define VC4_HDMI_CEC_CNT_TO_400_US_MASK	VC4_MASK(4, 0)
 # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_3			0x0f0
 # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK	VC4_MASK(31, 24)
 # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK	VC4_MASK(23, 16)
@@ -682,7 +642,6 @@
 # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_4			0x0f4
 # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK	VC4_MASK(31, 24)
 # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK	VC4_MASK(23, 16)
@@ -692,7 +651,6 @@
 # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_5			0x0f8
 # define VC4_HDMI_CEC_TX_SW_RESET		BIT(27)
 # define VC4_HDMI_CEC_RX_SW_RESET		BIT(26)
 # define VC4_HDMI_CEC_PAD_SW_RESET		BIT(25)
@@ -705,39 +663,11 @@
 # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT	0
 
-/* Transmit data, first byte is low byte of the 32-bit reg.  MSB of
- * each byte transmitted first.
- */
-#define VC4_HDMI_CEC_TX_DATA_1			0x0fc
-#define VC4_HDMI_CEC_TX_DATA_2			0x100
-#define VC4_HDMI_CEC_TX_DATA_3			0x104
-#define VC4_HDMI_CEC_TX_DATA_4			0x108
-#define VC4_HDMI_CEC_RX_DATA_1			0x10c
-#define VC4_HDMI_CEC_RX_DATA_2			0x110
-#define VC4_HDMI_CEC_RX_DATA_3			0x114
-#define VC4_HDMI_CEC_RX_DATA_4			0x118
-
-#define VC4_HDMI_TX_PHY_RESET_CTL		0x2c0
-
-#define VC4_HDMI_TX_PHY_CTL0			0x2c4
 # define VC4_HDMI_TX_PHY_RNG_PWRDN		BIT(25)
 
-/* Interrupt status bits */
-#define VC4_HDMI_CPU_STATUS			0x340
-#define VC4_HDMI_CPU_SET			0x344
-#define VC4_HDMI_CPU_CLEAR			0x348
 # define VC4_HDMI_CPU_CEC			BIT(6)
 # define VC4_HDMI_CPU_HOTPLUG			BIT(0)
 
-#define VC4_HDMI_CPU_MASK_STATUS		0x34c
-#define VC4_HDMI_CPU_MASK_SET			0x350
-#define VC4_HDMI_CPU_MASK_CLEAR			0x354
-
-#define VC4_HDMI_GCP(x)				(0x400 + ((x) * 0x4))
-#define VC4_HDMI_RAM_PACKET(x)			(0x400 + ((x) * 0x24))
-#define VC4_HDMI_PACKET_STRIDE			0x24
-
-#define VC4_HD_M_CTL				0x00c
 /* Debug: Current receive value on the CEC pad. */
 # define VC4_HD_CECRXD				BIT(9)
 /* Debug: Override CEC output to 0. */
@@ -747,7 +677,6 @@
 # define VC4_HD_M_SW_RST			BIT(2)
 # define VC4_HD_M_ENABLE			BIT(0)
 
-#define VC4_HD_MAI_CTL				0x014
 /* Set when audio stream is received at a slower rate than the
  * sampling period, so MAI fifo goes empty.  Write 1 to clear.
  */
@@ -772,7 +701,6 @@
 /* Single-shot reset bit.  Read value is undefined. */
 # define VC4_HD_MAI_CTL_RESET			BIT(0)
 
-#define VC4_HD_MAI_THR				0x018
 # define VC4_HD_MAI_THR_PANICHIGH_MASK		VC4_MASK(29, 24)
 # define VC4_HD_MAI_THR_PANICHIGH_SHIFT		24
 # define VC4_HD_MAI_THR_PANICLOW_MASK		VC4_MASK(21, 16)
@@ -782,31 +710,20 @@
 # define VC4_HD_MAI_THR_DREQLOW_MASK		VC4_MASK(5, 0)
 # define VC4_HD_MAI_THR_DREQLOW_SHIFT		0
 
-/* Format header to be placed on the MAI data. Unused. */
-#define VC4_HD_MAI_FMT				0x01c
-
-/* Register for DMAing in audio data to be transported over the MAI
- * bus to the Falcon core.
- */
-#define VC4_HD_MAI_DATA				0x020
-
 /* Divider from HDMI HSM clock to MAI serial clock.  Sampling period
  * converges to N / (M + 1) cycles.
  */
-#define VC4_HD_MAI_SMP				0x02c
 # define VC4_HD_MAI_SMP_N_MASK			VC4_MASK(31, 8)
 # define VC4_HD_MAI_SMP_N_SHIFT			8
 # define VC4_HD_MAI_SMP_M_MASK			VC4_MASK(7, 0)
 # define VC4_HD_MAI_SMP_M_SHIFT			0
 
-#define VC4_HD_VID_CTL				0x038
 # define VC4_HD_VID_CTL_ENABLE			BIT(31)
 # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE	BIT(30)
 # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET	BIT(29)
 # define VC4_HD_VID_CTL_VSYNC_LOW		BIT(28)
 # define VC4_HD_VID_CTL_HSYNC_LOW		BIT(27)
 
-#define VC4_HD_CSC_CTL				0x040
 # define VC4_HD_CSC_CTL_ORDER_MASK		VC4_MASK(7, 5)
 # define VC4_HD_CSC_CTL_ORDER_SHIFT		5
 # define VC4_HD_CSC_CTL_ORDER_RGB		0
@@ -824,15 +741,6 @@
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
 
-#define VC4_HD_CSC_12_11			0x044
-#define VC4_HD_CSC_14_13			0x048
-#define VC4_HD_CSC_22_21			0x04c
-#define VC4_HD_CSC_24_23			0x050
-#define VC4_HD_CSC_32_31			0x054
-#define VC4_HD_CSC_34_33			0x058
-
-#define VC4_HD_FRAME_COUNT			0x068
-
 /* HVS display list information. */
 #define HVS_BOOTLOADER_DLIST_END                32
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction
@ 2020-07-08 17:41     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:41 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI controllers found in the BCM2711 have most of the registers
reorganized in multiple registers areas and at different offsets than
previously found.

The logic however remains pretty much the same, so it doesn't really make
sense to create a whole new driver and we should share the code as much as
possible.

Let's implement some indirection to wrap around a register and depending on
the variant will lookup the associated register on that particular variant.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 427 ++++++++++++++---------------
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  12 +-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h      |  92 +------
 4 files changed, 464 insertions(+), 308 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ac021e07a8cb..a4fed1439bf3 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -50,62 +50,13 @@
 #include "media/cec.h"
 #include "vc4_drv.h"
 #include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
-static const struct debugfs_reg32 hdmi_regs[] = {
-	VC4_REG32(VC4_HDMI_CORE_REV),
-	VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
-	VC4_REG32(VC4_HDMI_HOTPLUG_INT),
-	VC4_REG32(VC4_HDMI_HOTPLUG),
-	VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
-	VC4_REG32(VC4_HDMI_MAI_CONFIG),
-	VC4_REG32(VC4_HDMI_MAI_FORMAT),
-	VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
-	VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
-	VC4_REG32(VC4_HDMI_HORZA),
-	VC4_REG32(VC4_HDMI_HORZB),
-	VC4_REG32(VC4_HDMI_FIFO_CTL),
-	VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
-	VC4_REG32(VC4_HDMI_VERTA0),
-	VC4_REG32(VC4_HDMI_VERTA1),
-	VC4_REG32(VC4_HDMI_VERTB0),
-	VC4_REG32(VC4_HDMI_VERTB1),
-	VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
-	VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
-
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
-	VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
-	VC4_REG32(VC4_HDMI_CPU_STATUS),
-	VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
-
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
-	VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
-	VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
-};
-
-static const struct debugfs_reg32 hd_regs[] = {
-	VC4_REG32(VC4_HD_M_CTL),
-	VC4_REG32(VC4_HD_MAI_CTL),
-	VC4_REG32(VC4_HD_MAI_THR),
-	VC4_REG32(VC4_HD_MAI_FMT),
-	VC4_REG32(VC4_HD_MAI_SMP),
-	VC4_REG32(VC4_HD_VID_CTL),
-	VC4_REG32(VC4_HD_CSC_CTL),
-	VC4_REG32(VC4_HD_FRAME_COUNT),
-};
-
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 	if (drm_probe_ddc(vc4_hdmi->ddc))
 		return connector_status_connected;
 
-	if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
+	if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
 		return connector_status_connected;
 	cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
 	return connector_status_disconnected;
@@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = type - 0x80;
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+		   HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
 
-	return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
+	return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
 			  BIT(packet_id)), 100);
 }
 
@@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	u32 packet_id = frame->any.type - 0x80;
-	u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
+	const struct vc4_hdmi_register *ram_packet_start =
+		&vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
+	u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
+	void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
+						       ram_packet_start->reg);
 	uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
 	ssize_t len, i;
 	int ret;
 
-	WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+	WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 		    VC4_HDMI_RAM_PACKET_ENABLE),
 		  "Packet RAM has to be on to store the packet.");
 
@@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 	}
 
 	for (i = 0; i < len; i += 7) {
-		HDMI_WRITE(packet_reg,
-			   buffer[i + 0] << 0 |
-			   buffer[i + 1] << 8 |
-			   buffer[i + 2] << 16);
+		writel(buffer[i + 0] << 0 |
+		       buffer[i + 1] << 8 |
+		       buffer[i + 2] << 16,
+		       base + packet_reg);
 		packet_reg += 4;
 
-		HDMI_WRITE(packet_reg,
-			   buffer[i + 3] << 0 |
-			   buffer[i + 4] << 8 |
-			   buffer[i + 5] << 16 |
-			   buffer[i + 6] << 24);
+		writel(buffer[i + 3] << 0 |
+		       buffer[i + 4] << 8 |
+		       buffer[i + 5] << 16 |
+		       buffer[i + 6] << 24,
+		       base + packet_reg);
 		packet_reg += 4;
 	}
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-		   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
-	ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+		   HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
+	ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
 			BIT(packet_id)), 100);
 	if (ret)
 		DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
@@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	int ret;
 
-	HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
+	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-	HD_WRITE(VC4_HD_VID_CTL,
-		 HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
 	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
@@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
 		   VC4_HDMI_SW_RESET_HDMI |
 		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
 
-	HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
 	 */
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
 
-	HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
-	HD_WRITE(VC4_HD_VID_CTL, 0);
+	HDMI_WRITE(HDMI_VID_CTL, 0);
 
-	HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-		   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
-	HDMI_WRITE(VC4_HDMI_HORZA,
+	HDMI_WRITE(HDMI_HORZA,
 		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
 		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
 		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
 				 VC4_HDMI_HORZA_HAP));
 
-	HDMI_WRITE(VC4_HDMI_HORZB,
+	HDMI_WRITE(HDMI_HORZB,
 		   VC4_SET_FIELD((mode->htotal -
 				  mode->hsync_end) * pixel_rep,
 				 VC4_HDMI_HORZB_HBP) |
@@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 				  mode->hdisplay) * pixel_rep,
 				 VC4_HDMI_HORZB_HFP));
 
-	HDMI_WRITE(VC4_HDMI_VERTA0, verta);
-	HDMI_WRITE(VC4_HDMI_VERTA1, verta);
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
 
-	HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
-	HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
 
-	HD_WRITE(VC4_HD_VID_CTL,
-		 (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		 (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+	HDMI_WRITE(HDMI_VID_CTL,
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
 	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
 				VC4_HD_CSC_CTL_ORDER);
@@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
 					 VC4_HD_CSC_CTL_MODE);
 
-		HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
-		HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
-		HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
-		HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
 		vc4_encoder->limited_rgb_range = true;
 	} else {
 		vc4_encoder->limited_rgb_range = false;
 	}
 
 	/* The RGB order applies even when CSC is disabled. */
-	HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 
-	HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
 	}
 
-	HD_WRITE(VC4_HD_VID_CTL,
-		 HD_READ(VC4_HD_VID_CTL) |
-		 VC4_HD_VID_CTL_ENABLE |
-		 VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
-		 VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) |
+		   VC4_HD_VID_CTL_ENABLE |
+		   VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
+		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
 
 	if (vc4_encoder->hdmi_monitor) {
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 			   VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
-		ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			       VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
 	} else {
-		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
-			   HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
+			   HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 			   ~(VC4_HDMI_RAM_PACKET_ENABLE));
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			   ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
 
-		ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 				 VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
@@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_encoder->hdmi_monitor) {
 		u32 drift;
 
-		WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
+		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
-		HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
-			   HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
+		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
+			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 			   VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
 
-		HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
+		HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
 			   VC4_HDMI_RAM_PACKET_ENABLE);
 
 		vc4_hdmi_set_infoframes(encoder);
 
-		drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
+		drift = HDMI_READ(HDMI_FIFO_CTL);
 		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
 
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
 		usleep_range(1000, 1100);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(VC4_HDMI_FIFO_CTL,
+		HDMI_WRITE(HDMI_FIFO_CTL,
 			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
 
-		ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
+		ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
 			       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
 		WARN_ONCE(ret, "Timeout waiting for "
 			  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
@@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 				     VC4_HD_MAI_SMP_M_SHIFT) + 1,
 				    &n, &m);
 
-	HD_WRITE(VC4_HD_MAI_SMP,
-		 VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
-		 VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
+	HDMI_WRITE(HDMI_MAI_SMP,
+		   VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
+		   VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
 }
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
@@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 	do_div(tmp, 128 * samplerate);
 	cts = tmp;
 
-	HDMI_WRITE(VC4_HDMI_CRP_CFG,
+	HDMI_WRITE(HDMI_CRP_CFG,
 		   VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
 		   VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
 
@@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
 	 * providing a CTS_1 value.  The two CTS values are alternated
 	 * between based on the period fields
 	 */
-	HDMI_WRITE(VC4_HDMI_CTS_0, cts);
-	HDMI_WRITE(VC4_HDMI_CTS_1, cts);
+	HDMI_WRITE(HDMI_CTS_0, cts);
+	HDMI_WRITE(HDMI_CTS_1, cts);
 }
 
 static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
@@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
 	 * If the HDMI encoder hasn't probed, or the encoder is
 	 * currently in DVI mode, treat the codec dai as missing.
 	 */
-	if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
+	if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
 				VC4_HDMI_RAM_PACKET_ENABLE))
 		return -ENODEV;
 
@@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 	if (ret)
 		dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
 
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
-	HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
+	HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
 }
 
 static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
@@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 	vc4_hdmi->audio.channels = params_channels(params);
 	vc4_hdmi->audio.samplerate = params_rate(params);
 
-	HD_WRITE(VC4_HD_MAI_CTL,
-		 VC4_HD_MAI_CTL_RESET |
-		 VC4_HD_MAI_CTL_FLUSH |
-		 VC4_HD_MAI_CTL_DLATE |
-		 VC4_HD_MAI_CTL_ERRORE |
-		 VC4_HD_MAI_CTL_ERRORF);
+	HDMI_WRITE(HDMI_MAI_CTL,
+		   VC4_HD_MAI_CTL_RESET |
+		   VC4_HD_MAI_CTL_FLUSH |
+		   VC4_HD_MAI_CTL_DLATE |
+		   VC4_HD_MAI_CTL_ERRORE |
+		   VC4_HD_MAI_CTL_ERRORF);
 
 	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
@@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	/* Set the MAI threshold.  This logic mimics the firmware's. */
 	if (vc4_hdmi->audio.samplerate > 96000) {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
 	} else if (vc4_hdmi->audio.samplerate > 48000) {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
 	} else {
-		HD_WRITE(VC4_HD_MAI_THR,
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
-			 VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
+		HDMI_WRITE(HDMI_MAI_THR,
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
+			   VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
 	}
 
-	HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
+	HDMI_WRITE(HDMI_MAI_CONFIG,
 		   VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
 		   VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
 
@@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 			channel_map |= i << (3 * i);
 	}
 
-	HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
-	HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
+	HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
+	HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
 	vc4_hdmi_set_n_cts(vc4_hdmi);
 
 	return 0;
@@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
-		HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
-			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
+		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+			   HDMI_READ(HDMI_TX_PHY_CTL_0) &
 			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
-		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_SET_FIELD(vc4_hdmi->audio.channels,
-				       VC4_HD_MAI_CTL_CHNUM) |
-			 VC4_HD_MAI_CTL_ENABLE);
+
+		HDMI_WRITE(HDMI_MAI_CTL,
+			   VC4_SET_FIELD(vc4_hdmi->audio.channels,
+					 VC4_HD_MAI_CTL_CHNUM) |
+			   VC4_HD_MAI_CTL_ENABLE);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		HD_WRITE(VC4_HD_MAI_CTL,
-			 VC4_HD_MAI_CTL_DLATE |
-			 VC4_HD_MAI_CTL_ERRORE |
-			 VC4_HD_MAI_CTL_ERRORF);
-		HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
-			   HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
+		HDMI_WRITE(HDMI_MAI_CTL,
+			   VC4_HD_MAI_CTL_DLATE |
+			   VC4_HD_MAI_CTL_ERRORE |
+			   VC4_HD_MAI_CTL_ERRORF);
+		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+			   HDMI_READ(HDMI_TX_PHY_CTL_0) |
 			   VC4_HDMI_TX_PHY_RNG_PWRDN);
 		break;
 	default:
@@ -946,6 +902,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
 
 static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
+	const struct vc4_hdmi_register *mai_data =
+		&vc4_hdmi->variant->registers[HDMI_MAI_DATA];
 	struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
 	struct snd_soc_card *card = &vc4_hdmi->audio.card;
 	struct device *dev = &vc4_hdmi->pdev->dev;
@@ -958,6 +916,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 		return 0;
 	}
 
+	if (mai_data->reg != VC4_HD) {
+		WARN_ONCE(true, "MAI isn't in the HD block\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve
 	 * the bus address specified in the DT, because the physical address
@@ -966,7 +929,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
 	addr = of_get_address(dev->of_node, 1, NULL, NULL);
-	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
+	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
 	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	vc4_hdmi->audio.dma_data.maxburst = 2;
 
@@ -1058,7 +1021,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 	msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
 					VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
 	for (i = 0; i < msg->len; i += 4) {
-		u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
+		u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i);
 
 		msg->msg[i] = val & 0xff;
 		msg->msg[i + 1] = (val >> 8) & 0xff;
@@ -1070,26 +1033,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
 static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 {
 	struct vc4_hdmi *vc4_hdmi = priv;
-	u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
+	u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
 	u32 cntrl1, cntrl5;
 
 	if (!(stat & VC4_HDMI_CPU_CEC))
 		return IRQ_NONE;
 	vc4_hdmi->cec_rx_msg.len = 0;
-	cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
-	cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
+	cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
+	cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
 	vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
 	if (vc4_hdmi->cec_irq_was_rx) {
 		vc4_cec_read_msg(vc4_hdmi, cntrl1);
 		cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
+		HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
 		cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
 	} else {
 		vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
 		cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
 	}
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
-	HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
+	HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
 
 	return IRQ_WAKE_THREAD;
 }
@@ -1099,7 +1062,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 	/* clock period in microseconds */
 	const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
-	u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
+	u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
 
 	val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
 		 VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
@@ -1108,30 +1071,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 	       ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
 
 	if (enable) {
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
 			   VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
-			 ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
-			 ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
-			 ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
-			 ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
-			 ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
-			 ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
-			 ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
-			 ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
-			 ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
-			 ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
-			 ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
-			 ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
-			 ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
-
-		HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
+		HDMI_WRITE(HDMI_CEC_CNTRL_2,
+			   ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
+			   ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
+			   ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
+			   ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
+			   ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
+		HDMI_WRITE(HDMI_CEC_CNTRL_3,
+			   ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
+			   ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
+			   ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
+			   ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
+		HDMI_WRITE(HDMI_CEC_CNTRL_4,
+			   ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
+			   ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
+			   ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
+			   ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
+
+		HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
 	} else {
-		HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
-		HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
+		HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
+		HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
 			   VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
 	}
 	return 0;
@@ -1141,8 +1104,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
 	struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
 
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
-		   (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
+	HDMI_WRITE(HDMI_CEC_CNTRL_1,
+		   (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
 		   (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
 	return 0;
 }
@@ -1155,20 +1118,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 	unsigned int i;
 
 	for (i = 0; i < msg->len; i += 4)
-		HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
+		HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i,
 			   (msg->msg[i]) |
 			   (msg->msg[i + 1] << 8) |
 			   (msg->msg[i + 2] << 16) |
 			   (msg->msg[i + 3] << 24));
 
-	val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
+	val = HDMI_READ(HDMI_CEC_CNTRL_1);
 	val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
 	val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
 	val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
 	val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
 
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
 	return 0;
 }
 
@@ -1179,6 +1142,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 };
 #endif
 
+static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
+				 struct debugfs_regset32 *regset,
+				 enum vc4_hdmi_regs reg)
+{
+	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+	struct debugfs_reg32 *regs, *new_regs;
+	unsigned int count = 0;
+	unsigned int i;
+
+	regs = kcalloc(variant->num_registers, sizeof(*regs),
+		       GFP_KERNEL);
+	if (!regs)
+		return -ENOMEM;
+
+	for (i = 0; i < variant->num_registers; i++) {
+		const struct vc4_hdmi_register *field =	&variant->registers[i];
+
+		if (field->reg != reg)
+			continue;
+
+		regs[count].name = field->name;
+		regs[count].offset = field->offset;
+		count++;
+	}
+
+	new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
+	if (!new_regs)
+		return -ENOMEM;
+
+	regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
+	regset->regs = new_regs;
+	regset->nregs = count;
+
+	return 0;
+}
+
 static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 {
 	struct platform_device *pdev = vc4_hdmi->pdev;
@@ -1193,13 +1192,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 	if (IS_ERR(vc4_hdmi->hd_regs))
 		return PTR_ERR(vc4_hdmi->hd_regs);
 
-	vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
-	vc4_hdmi->hdmi_regset.regs = hdmi_regs;
-	vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
+	ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
+	if (ret)
+		return ret;
 
-	vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
-	vc4_hdmi->hd_regset.regs = hd_regs;
-	vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
+	ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
+	if (ret)
+		return ret;
 
 	vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
 	if (IS_ERR(vc4_hdmi->pixel_clock)) {
@@ -1294,12 +1293,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	}
 
 	/* HDMI core must be enabled. */
-	if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
-		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
+	if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
+		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
 		udelay(1);
-		HD_WRITE(VC4_HD_M_CTL, 0);
+		HDMI_WRITE(HDMI_M_CTL, 0);
 
-		HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
+		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
 	}
 	pm_runtime_enable(dev);
 
@@ -1322,8 +1321,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
 	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
-	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
-	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
+	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
+	value = HDMI_READ(HDMI_CEC_CNTRL_1);
 	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
 	/*
 	 * Set the logical address to Unregistered and set the clock
@@ -1332,7 +1331,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	 */
 	value |= VC4_HDMI_CEC_ADDR_MASK |
 		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
-	HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
 	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
 					vc4_cec_irq_handler,
 					vc4_cec_irq_handler_thread, 0,
@@ -1395,6 +1394,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
 	vc4_hdmi = dev_get_drvdata(dev);
 
+	kfree(vc4_hdmi->hdmi_regset.regs);
+	kfree(vc4_hdmi->hd_regset.regs);
+
 	cec_unregister_adapter(vc4_hdmi->cec_adap);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
@@ -1422,6 +1424,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
+	.registers		= vc4_hdmi_fields,
+	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
+
 	.init_resources		= vc4_hdmi_init_resources,
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0eaf979fe811..b36e0210671f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_hdmi;
+struct vc4_hdmi_register;
 
 struct vc4_hdmi_variant {
+	/* List of the registers available on that variant */
+	const struct vc4_hdmi_register *registers;
+
+	/* Number of registers on that variant */
+	unsigned int num_registers;
+
 	/* Callback to get the resources (memory region, interrupts,
 	 * clocks, etc) for that variant.
 	 */
@@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
-#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
-#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
-#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
-#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
-
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
new file mode 100644
index 000000000000..bc47cc9bc883
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -0,0 +1,241 @@
+#ifndef _VC4_HDMI_REGS_H_
+#define _VC4_HDMI_REGS_H_
+
+#include "vc4_hdmi.h"
+
+#define VC4_HDMI_PACKET_STRIDE			0x24
+
+enum vc4_hdmi_regs {
+	VC4_INVALID = 0,
+	VC4_HDMI,
+	VC4_HD,
+};
+
+enum vc4_hdmi_field {
+	HDMI_AUDIO_PACKET_CONFIG,
+	HDMI_CEC_CNTRL_1,
+	HDMI_CEC_CNTRL_2,
+	HDMI_CEC_CNTRL_3,
+	HDMI_CEC_CNTRL_4,
+	HDMI_CEC_CNTRL_5,
+	HDMI_CEC_CPU_CLEAR,
+	HDMI_CEC_CPU_MASK_CLEAR,
+	HDMI_CEC_CPU_MASK_SET,
+	HDMI_CEC_CPU_MASK_STATUS,
+	HDMI_CEC_CPU_STATUS,
+
+	/*
+	 * Transmit data, first byte is low byte of the 32-bit reg.
+	 * MSB of each byte transmitted first.
+	 */
+	HDMI_CEC_RX_DATA_1,
+	HDMI_CEC_RX_DATA_2,
+	HDMI_CEC_RX_DATA_3,
+	HDMI_CEC_RX_DATA_4,
+	HDMI_CEC_TX_DATA_1,
+	HDMI_CEC_TX_DATA_2,
+	HDMI_CEC_TX_DATA_3,
+	HDMI_CEC_TX_DATA_4,
+	HDMI_CORE_REV,
+	HDMI_CRP_CFG,
+	HDMI_CSC_12_11,
+	HDMI_CSC_14_13,
+	HDMI_CSC_22_21,
+	HDMI_CSC_24_23,
+	HDMI_CSC_32_31,
+	HDMI_CSC_34_33,
+	HDMI_CSC_CTL,
+
+	/*
+	 * 20-bit fields containing CTS values to be transmitted if
+	 * !EXTERNAL_CTS_EN
+	 */
+	HDMI_CTS_0,
+	HDMI_CTS_1,
+	HDMI_FIFO_CTL,
+	HDMI_FRAME_COUNT,
+	HDMI_HORZA,
+	HDMI_HORZB,
+	HDMI_HOTPLUG,
+	HDMI_HOTPLUG_INT,
+
+	/*
+	 * 3 bits per field, where each field maps from that
+	 * corresponding MAI bus channel to the given HDMI channel.
+	 */
+	HDMI_MAI_CHANNEL_MAP,
+	HDMI_MAI_CONFIG,
+	HDMI_MAI_CTL,
+
+	/*
+	 * Register for DMAing in audio data to be transported over
+	 * the MAI bus to the Falcon core.
+	 */
+	HDMI_MAI_DATA,
+
+	/* Format header to be placed on the MAI data. Unused. */
+	HDMI_MAI_FMT,
+
+	/* Last received format word on the MAI bus. */
+	HDMI_MAI_FORMAT,
+	HDMI_MAI_SMP,
+	HDMI_MAI_THR,
+	HDMI_M_CTL,
+	HDMI_RAM_PACKET_CONFIG,
+	HDMI_RAM_PACKET_START,
+	HDMI_RAM_PACKET_STATUS,
+	HDMI_SCHEDULER_CONTROL,
+	HDMI_SW_RESET_CONTROL,
+	HDMI_TX_PHY_CTL_0,
+	HDMI_TX_PHY_RESET_CTL,
+	HDMI_VERTA0,
+	HDMI_VERTA1,
+	HDMI_VERTB0,
+	HDMI_VERTB1,
+	HDMI_VID_CTL,
+};
+
+struct vc4_hdmi_register {
+	char *name;
+	enum vc4_hdmi_regs reg;
+	unsigned int offset;
+};
+
+#define _VC4_REG(_base, _reg, _offset)	\
+	[_reg] = {				\
+		.name = #_reg,			\
+		.reg = _base,			\
+		.offset = _offset,		\
+	}
+
+#define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
+#define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
+
+static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
+	VC4_HD_REG(HDMI_M_CTL, 0x000c),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0018),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x001c),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x0020),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x002c),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0038),
+	VC4_HD_REG(HDMI_CSC_CTL, 0x0040),
+	VC4_HD_REG(HDMI_CSC_12_11, 0x0044),
+	VC4_HD_REG(HDMI_CSC_14_13, 0x0048),
+	VC4_HD_REG(HDMI_CSC_22_21, 0x004c),
+	VC4_HD_REG(HDMI_CSC_24_23, 0x0050),
+	VC4_HD_REG(HDMI_CSC_32_31, 0x0054),
+	VC4_HD_REG(HDMI_CSC_34_33, 0x0058),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068),
+
+	VC4_HDMI_REG(HDMI_CORE_REV, 0x0000),
+	VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004),
+	VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c),
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094),
+	VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x00ac),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x00b0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x00c4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x00c8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x00cc),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x00d0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x00d4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x00d8),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4),
+	VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104),
+	VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114),
+	VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118),
+	VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0),
+	VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4),
+	VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340),
+	VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c),
+	VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
+};
+
+static inline
+void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
+					enum vc4_hdmi_regs reg)
+{
+	switch (reg) {
+	case VC4_HD:
+		return hdmi->hd_regs;
+
+	case VC4_HDMI:
+		return hdmi->hdmicore_regs;
+
+	default:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
+				enum vc4_hdmi_regs reg)
+{
+	const struct vc4_hdmi_register *field;
+	const struct vc4_hdmi_variant *variant = hdmi->variant;
+	void __iomem *base;
+
+	if (reg > variant->num_registers) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Invalid register ID %u\n", reg);
+		return 0;
+	}
+
+	field = &variant->registers[reg];
+	base = __vc4_hdmi_get_field_base(hdmi, field->reg);
+	if (!base) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Unknown register ID %u\n", reg);
+		return 0;
+	}
+
+	return readl(base + field->offset);
+}
+#define HDMI_READ(reg)		vc4_hdmi_read(vc4_hdmi, reg)
+
+static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
+				  enum vc4_hdmi_regs reg,
+				  u32 value)
+{
+	const struct vc4_hdmi_register *field;
+	const struct vc4_hdmi_variant *variant = hdmi->variant;
+	void __iomem *base;
+
+	if (reg > variant->num_registers) {
+		dev_warn(&hdmi->pdev->dev,
+			 "Invalid register ID %u\n", reg);
+		return;
+	}
+
+	field = &variant->registers[reg];
+	base = __vc4_hdmi_get_field_base(hdmi, field->reg);
+	if (!base)
+		return;
+
+	writel(value, base + field->offset);
+}
+#define HDMI_WRITE(reg, val)	vc4_hdmi_write(vc4_hdmi, reg, val)
+
+#endif /* _VC4_HDMI_REGS_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index c0031ab19689..d1e8961edaa0 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -493,32 +493,16 @@
 
 #define SCALER5_DLIST_START			0x00004000
 
-#define VC4_HDMI_CORE_REV			0x000
-
-#define VC4_HDMI_SW_RESET_CONTROL		0x004
 # define VC4_HDMI_SW_RESET_FORMAT_DETECT	BIT(1)
 # define VC4_HDMI_SW_RESET_HDMI			BIT(0)
 
-#define VC4_HDMI_HOTPLUG_INT			0x008
-
-#define VC4_HDMI_HOTPLUG			0x00c
 # define VC4_HDMI_HOTPLUG_CONNECTED		BIT(0)
 
-/* 3 bits per field, where each field maps from that corresponding MAI
- * bus channel to the given HDMI channel.
- */
-#define VC4_HDMI_MAI_CHANNEL_MAP		0x090
-
-#define VC4_HDMI_MAI_CONFIG			0x094
 # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE		BIT(27)
 # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE		BIT(26)
 # define VC4_HDMI_MAI_CHANNEL_MASK_MASK			VC4_MASK(15, 0)
 # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT		0
 
-/* Last received format word on the MAI bus. */
-#define VC4_HDMI_MAI_FORMAT			0x098
-
-#define VC4_HDMI_AUDIO_PACKET_CONFIG		0x09c
 # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT		BIT(29)
 # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS	BIT(24)
 # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT		BIT(19)
@@ -532,12 +516,8 @@
 # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK			VC4_MASK(7, 0)
 # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT			0
 
-#define VC4_HDMI_RAM_PACKET_CONFIG		0x0a0
 # define VC4_HDMI_RAM_PACKET_ENABLE		BIT(16)
 
-#define VC4_HDMI_RAM_PACKET_STATUS		0x0a4
-
-#define VC4_HDMI_CRP_CFG			0x0a8
 /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
  * of pixel clock.
  */
@@ -551,23 +531,12 @@
 # define VC4_HDMI_CRP_CFG_N_MASK		VC4_MASK(19, 0)
 # define VC4_HDMI_CRP_CFG_N_SHIFT		0
 
-/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */
-#define VC4_HDMI_CTS_0				0x0ac
-#define VC4_HDMI_CTS_1				0x0b0
-/* 20-bit fields containing number of clocks to send CTS0/1 before
- * switching to the other one.
- */
-#define VC4_HDMI_CTS_PERIOD_0			0x0b4
-#define VC4_HDMI_CTS_PERIOD_1			0x0b8
-
-#define VC4_HDMI_HORZA				0x0c4
 # define VC4_HDMI_HORZA_VPOS			BIT(14)
 # define VC4_HDMI_HORZA_HPOS			BIT(13)
 /* Horizontal active pixels (hdisplay). */
 # define VC4_HDMI_HORZA_HAP_MASK		VC4_MASK(12, 0)
 # define VC4_HDMI_HORZA_HAP_SHIFT		0
 
-#define VC4_HDMI_HORZB				0x0c8
 /* Horizontal pack porch (htotal - hsync_end). */
 # define VC4_HDMI_HORZB_HBP_MASK		VC4_MASK(29, 20)
 # define VC4_HDMI_HORZB_HBP_SHIFT		20
@@ -578,7 +547,6 @@
 # define VC4_HDMI_HORZB_HFP_MASK		VC4_MASK(9, 0)
 # define VC4_HDMI_HORZB_HFP_SHIFT		0
 
-#define VC4_HDMI_FIFO_CTL			0x05c
 # define VC4_HDMI_FIFO_CTL_RECENTER_DONE	BIT(14)
 # define VC4_HDMI_FIFO_CTL_USE_EMPTY		BIT(13)
 # define VC4_HDMI_FIFO_CTL_ON_VB		BIT(7)
@@ -591,15 +559,12 @@
 # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N	BIT(0)
 # define VC4_HDMI_FIFO_VALID_WRITE_MASK		0xefff
 
-#define VC4_HDMI_SCHEDULER_CONTROL		0x0c0
 # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
 # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
 # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT	BIT(3)
 # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE	BIT(1)
 # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI	BIT(0)
 
-#define VC4_HDMI_VERTA0				0x0cc
-#define VC4_HDMI_VERTA1				0x0d4
 /* Vertical sync pulse (vsync_end - vsync_start). */
 # define VC4_HDMI_VERTA_VSP_MASK		VC4_MASK(24, 20)
 # define VC4_HDMI_VERTA_VSP_SHIFT		20
@@ -610,8 +575,6 @@
 # define VC4_HDMI_VERTA_VAL_MASK		VC4_MASK(12, 0)
 # define VC4_HDMI_VERTA_VAL_SHIFT		0
 
-#define VC4_HDMI_VERTB0				0x0d0
-#define VC4_HDMI_VERTB1				0x0d8
 /* Vertical sync pulse offset (for interlaced) */
 # define VC4_HDMI_VERTB_VSPO_MASK		VC4_MASK(21, 9)
 # define VC4_HDMI_VERTB_VSPO_SHIFT		9
@@ -619,7 +582,6 @@
 # define VC4_HDMI_VERTB_VBP_MASK		VC4_MASK(8, 0)
 # define VC4_HDMI_VERTB_VBP_SHIFT		0
 
-#define VC4_HDMI_CEC_CNTRL_1			0x0e8
 /* Set when the transmission has ended. */
 # define VC4_HDMI_CEC_TX_EOM			BIT(31)
 /* If set, transmission was acked on the 1st or 2nd attempt (only one
@@ -660,7 +622,6 @@
 /* Set these fields to how many bit clock cycles get to that many
  * microseconds.
  */
-#define VC4_HDMI_CEC_CNTRL_2			0x0ec
 # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK	VC4_MASK(30, 24)
 # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK	VC4_MASK(23, 17)
@@ -672,7 +633,6 @@
 # define VC4_HDMI_CEC_CNT_TO_400_US_MASK	VC4_MASK(4, 0)
 # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_3			0x0f0
 # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK	VC4_MASK(31, 24)
 # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK	VC4_MASK(23, 16)
@@ -682,7 +642,6 @@
 # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_4			0x0f4
 # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK	VC4_MASK(31, 24)
 # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT	24
 # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK	VC4_MASK(23, 16)
@@ -692,7 +651,6 @@
 # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT	0
 
-#define VC4_HDMI_CEC_CNTRL_5			0x0f8
 # define VC4_HDMI_CEC_TX_SW_RESET		BIT(27)
 # define VC4_HDMI_CEC_RX_SW_RESET		BIT(26)
 # define VC4_HDMI_CEC_PAD_SW_RESET		BIT(25)
@@ -705,39 +663,11 @@
 # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK	VC4_MASK(7, 0)
 # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT	0
 
-/* Transmit data, first byte is low byte of the 32-bit reg.  MSB of
- * each byte transmitted first.
- */
-#define VC4_HDMI_CEC_TX_DATA_1			0x0fc
-#define VC4_HDMI_CEC_TX_DATA_2			0x100
-#define VC4_HDMI_CEC_TX_DATA_3			0x104
-#define VC4_HDMI_CEC_TX_DATA_4			0x108
-#define VC4_HDMI_CEC_RX_DATA_1			0x10c
-#define VC4_HDMI_CEC_RX_DATA_2			0x110
-#define VC4_HDMI_CEC_RX_DATA_3			0x114
-#define VC4_HDMI_CEC_RX_DATA_4			0x118
-
-#define VC4_HDMI_TX_PHY_RESET_CTL		0x2c0
-
-#define VC4_HDMI_TX_PHY_CTL0			0x2c4
 # define VC4_HDMI_TX_PHY_RNG_PWRDN		BIT(25)
 
-/* Interrupt status bits */
-#define VC4_HDMI_CPU_STATUS			0x340
-#define VC4_HDMI_CPU_SET			0x344
-#define VC4_HDMI_CPU_CLEAR			0x348
 # define VC4_HDMI_CPU_CEC			BIT(6)
 # define VC4_HDMI_CPU_HOTPLUG			BIT(0)
 
-#define VC4_HDMI_CPU_MASK_STATUS		0x34c
-#define VC4_HDMI_CPU_MASK_SET			0x350
-#define VC4_HDMI_CPU_MASK_CLEAR			0x354
-
-#define VC4_HDMI_GCP(x)				(0x400 + ((x) * 0x4))
-#define VC4_HDMI_RAM_PACKET(x)			(0x400 + ((x) * 0x24))
-#define VC4_HDMI_PACKET_STRIDE			0x24
-
-#define VC4_HD_M_CTL				0x00c
 /* Debug: Current receive value on the CEC pad. */
 # define VC4_HD_CECRXD				BIT(9)
 /* Debug: Override CEC output to 0. */
@@ -747,7 +677,6 @@
 # define VC4_HD_M_SW_RST			BIT(2)
 # define VC4_HD_M_ENABLE			BIT(0)
 
-#define VC4_HD_MAI_CTL				0x014
 /* Set when audio stream is received at a slower rate than the
  * sampling period, so MAI fifo goes empty.  Write 1 to clear.
  */
@@ -772,7 +701,6 @@
 /* Single-shot reset bit.  Read value is undefined. */
 # define VC4_HD_MAI_CTL_RESET			BIT(0)
 
-#define VC4_HD_MAI_THR				0x018
 # define VC4_HD_MAI_THR_PANICHIGH_MASK		VC4_MASK(29, 24)
 # define VC4_HD_MAI_THR_PANICHIGH_SHIFT		24
 # define VC4_HD_MAI_THR_PANICLOW_MASK		VC4_MASK(21, 16)
@@ -782,31 +710,20 @@
 # define VC4_HD_MAI_THR_DREQLOW_MASK		VC4_MASK(5, 0)
 # define VC4_HD_MAI_THR_DREQLOW_SHIFT		0
 
-/* Format header to be placed on the MAI data. Unused. */
-#define VC4_HD_MAI_FMT				0x01c
-
-/* Register for DMAing in audio data to be transported over the MAI
- * bus to the Falcon core.
- */
-#define VC4_HD_MAI_DATA				0x020
-
 /* Divider from HDMI HSM clock to MAI serial clock.  Sampling period
  * converges to N / (M + 1) cycles.
  */
-#define VC4_HD_MAI_SMP				0x02c
 # define VC4_HD_MAI_SMP_N_MASK			VC4_MASK(31, 8)
 # define VC4_HD_MAI_SMP_N_SHIFT			8
 # define VC4_HD_MAI_SMP_M_MASK			VC4_MASK(7, 0)
 # define VC4_HD_MAI_SMP_M_SHIFT			0
 
-#define VC4_HD_VID_CTL				0x038
 # define VC4_HD_VID_CTL_ENABLE			BIT(31)
 # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE	BIT(30)
 # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET	BIT(29)
 # define VC4_HD_VID_CTL_VSYNC_LOW		BIT(28)
 # define VC4_HD_VID_CTL_HSYNC_LOW		BIT(27)
 
-#define VC4_HD_CSC_CTL				0x040
 # define VC4_HD_CSC_CTL_ORDER_MASK		VC4_MASK(7, 5)
 # define VC4_HD_CSC_CTL_ORDER_SHIFT		5
 # define VC4_HD_CSC_CTL_ORDER_RGB		0
@@ -824,15 +741,6 @@
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
 
-#define VC4_HD_CSC_12_11			0x044
-#define VC4_HD_CSC_14_13			0x048
-#define VC4_HD_CSC_22_21			0x04c
-#define VC4_HD_CSC_24_23			0x050
-#define VC4_HD_CSC_32_31			0x054
-#define VC4_HD_CSC_34_33			0x058
-
-#define VC4_HD_FRAME_COUNT			0x068
-
 /* HVS display list information. */
 #define HVS_BOOTLOADER_DLIST_END                32
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The BCM2711 and BCM283x HDMI controllers use a slightly different reset
sequence, so let's add a callback to reset the controller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++-------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a4fed1439bf3..80bc3dd9d4a8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
+	udelay(1);
+	HDMI_WRITE(HDMI_M_CTL, 0);
+
+	HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
+
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
+		   VC4_HDMI_SW_RESET_HDMI |
+		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
+
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
-		   VC4_HDMI_SW_RESET_HDMI |
-		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
-
-	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
+	if (vc4_hdmi->variant->reset)
+		vc4_hdmi->variant->reset(vc4_hdmi);
 
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
@@ -1292,14 +1304,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	/* HDMI core must be enabled. */
-	if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
-		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
-		udelay(1);
-		HDMI_WRITE(HDMI_M_CTL, 0);
-
-		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
-	}
 	pm_runtime_enable(dev);
 
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
@@ -1428,6 +1432,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
 	.init_resources		= vc4_hdmi_init_resources,
+	.reset			= vc4_hdmi_reset,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index b36e0210671f..17a30589f39c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -35,6 +35,9 @@ struct vc4_hdmi_variant {
 	 * clocks, etc) for that variant.
 	 */
 	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to reset the HDMI block */
+	void (*reset)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
-- 
git-series 0.9.1

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

* [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 and BCM283x HDMI controllers use a slightly different reset
sequence, so let's add a callback to reset the controller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++-------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a4fed1439bf3..80bc3dd9d4a8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
+	udelay(1);
+	HDMI_WRITE(HDMI_M_CTL, 0);
+
+	HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
+
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
+		   VC4_HDMI_SW_RESET_HDMI |
+		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
+
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
-		   VC4_HDMI_SW_RESET_HDMI |
-		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
-
-	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
+	if (vc4_hdmi->variant->reset)
+		vc4_hdmi->variant->reset(vc4_hdmi);
 
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
@@ -1292,14 +1304,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	/* HDMI core must be enabled. */
-	if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
-		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
-		udelay(1);
-		HDMI_WRITE(HDMI_M_CTL, 0);
-
-		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
-	}
 	pm_runtime_enable(dev);
 
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
@@ -1428,6 +1432,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
 	.init_resources		= vc4_hdmi_init_resources,
+	.reset			= vc4_hdmi_reset,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index b36e0210671f..17a30589f39c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -35,6 +35,9 @@ struct vc4_hdmi_variant {
 	 * clocks, etc) for that variant.
 	 */
 	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to reset the HDMI block */
+	void (*reset)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 and BCM283x HDMI controllers use a slightly different reset
sequence, so let's add a callback to reset the controller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++-------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a4fed1439bf3..80bc3dd9d4a8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
+	udelay(1);
+	HDMI_WRITE(HDMI_M_CTL, 0);
+
+	HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
+
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
+		   VC4_HDMI_SW_RESET_HDMI |
+		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
+
+	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	HDMI_WRITE(HDMI_SW_RESET_CONTROL,
-		   VC4_HDMI_SW_RESET_HDMI |
-		   VC4_HDMI_SW_RESET_FORMAT_DETECT);
-
-	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
+	if (vc4_hdmi->variant->reset)
+		vc4_hdmi->variant->reset(vc4_hdmi);
 
 	/* PHY should be in reset, like
 	 * vc4_hdmi_encoder_disable() does.
@@ -1292,14 +1304,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
 	}
 
-	/* HDMI core must be enabled. */
-	if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
-		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
-		udelay(1);
-		HDMI_WRITE(HDMI_M_CTL, 0);
-
-		HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
-	}
 	pm_runtime_enable(dev);
 
 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
@@ -1428,6 +1432,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
 	.init_resources		= vc4_hdmi_init_resources,
+	.reset			= vc4_hdmi_reset,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index b36e0210671f..17a30589f39c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -35,6 +35,9 @@ struct vc4_hdmi_variant {
 	 * clocks, etc) for that variant.
 	 */
 	int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to reset the HDMI block */
+	void (*reset)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HDMI PHY in the BCM2711 HDMI controller is significantly more
complicated to setup than in the older BCM283x SoCs.

Let's add hooks to enable and disable the PHY.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/Makefile       |  1 +
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++-------
 drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
 4 files changed, 46 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c

diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index b303703bc7f3..d0163e18e9ca 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -12,6 +12,7 @@ vc4-y := \
 	vc4_kms.o \
 	vc4_gem.o \
 	vc4_hdmi.o \
+	vc4_hdmi_phy.o \
 	vc4_vec.o \
 	vc4_hvs.o \
 	vc4_irq.o \
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 80bc3dd9d4a8..068041145d1c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	if (vc4_hdmi->variant->phy_disable)
+		vc4_hdmi->variant->phy_disable(vc4_hdmi);
+
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
@@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->reset)
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
-	/* PHY should be in reset, like
-	 * vc4_hdmi_encoder_disable() does.
-	 */
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+	if (vc4_hdmi->variant->phy_init)
+		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -1433,6 +1431,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 
 	.init_resources		= vc4_hdmi_init_resources,
 	.reset			= vc4_hdmi_reset,
+	.phy_init		= vc4_hdmi_phy_init,
+	.phy_disable		= vc4_hdmi_phy_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 17a30589f39c..32c80161c786 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct drm_display_mode;
+
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
@@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
 
 	/* Callback to reset the HDMI block */
 	void (*reset)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to initialize the PHY according to the mode */
+	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
+			 struct drm_display_mode *mode);
+
+	/* Callback to disable the PHY */
+	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct drm_display_mode *mode);
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
new file mode 100644
index 000000000000..5a1746877bb5
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015 Broadcom
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
+
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+	/* PHY should be in reset, like
+	 * vc4_hdmi_encoder_disable() does.
+	 */
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+}
+
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+}
-- 
git-series 0.9.1

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

* [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI PHY in the BCM2711 HDMI controller is significantly more
complicated to setup than in the older BCM283x SoCs.

Let's add hooks to enable and disable the PHY.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/Makefile       |  1 +
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++-------
 drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
 4 files changed, 46 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c

diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index b303703bc7f3..d0163e18e9ca 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -12,6 +12,7 @@ vc4-y := \
 	vc4_kms.o \
 	vc4_gem.o \
 	vc4_hdmi.o \
+	vc4_hdmi_phy.o \
 	vc4_vec.o \
 	vc4_hvs.o \
 	vc4_irq.o \
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 80bc3dd9d4a8..068041145d1c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	if (vc4_hdmi->variant->phy_disable)
+		vc4_hdmi->variant->phy_disable(vc4_hdmi);
+
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
@@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->reset)
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
-	/* PHY should be in reset, like
-	 * vc4_hdmi_encoder_disable() does.
-	 */
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+	if (vc4_hdmi->variant->phy_init)
+		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -1433,6 +1431,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 
 	.init_resources		= vc4_hdmi_init_resources,
 	.reset			= vc4_hdmi_reset,
+	.phy_init		= vc4_hdmi_phy_init,
+	.phy_disable		= vc4_hdmi_phy_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 17a30589f39c..32c80161c786 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct drm_display_mode;
+
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
@@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
 
 	/* Callback to reset the HDMI block */
 	void (*reset)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to initialize the PHY according to the mode */
+	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
+			 struct drm_display_mode *mode);
+
+	/* Callback to disable the PHY */
+	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct drm_display_mode *mode);
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
new file mode 100644
index 000000000000..5a1746877bb5
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015 Broadcom
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
+
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+	/* PHY should be in reset, like
+	 * vc4_hdmi_encoder_disable() does.
+	 */
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+}
+
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+}
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI PHY in the BCM2711 HDMI controller is significantly more
complicated to setup than in the older BCM283x SoCs.

Let's add hooks to enable and disable the PHY.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/Makefile       |  1 +
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++-------
 drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
 4 files changed, 46 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c

diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
index b303703bc7f3..d0163e18e9ca 100644
--- a/drivers/gpu/drm/vc4/Makefile
+++ b/drivers/gpu/drm/vc4/Makefile
@@ -12,6 +12,7 @@ vc4-y := \
 	vc4_kms.o \
 	vc4_gem.o \
 	vc4_hdmi.o \
+	vc4_hdmi_phy.o \
 	vc4_vec.o \
 	vc4_hvs.o \
 	vc4_irq.o \
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 80bc3dd9d4a8..068041145d1c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
 
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	if (vc4_hdmi->variant->phy_disable)
+		vc4_hdmi->variant->phy_disable(vc4_hdmi);
+
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
@@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->reset)
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
-	/* PHY should be in reset, like
-	 * vc4_hdmi_encoder_disable() does.
-	 */
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
-
-	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+	if (vc4_hdmi->variant->phy_init)
+		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
@@ -1433,6 +1431,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 
 	.init_resources		= vc4_hdmi_init_resources,
 	.reset			= vc4_hdmi_reset,
+	.phy_init		= vc4_hdmi_phy_init,
+	.phy_disable		= vc4_hdmi_phy_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 17a30589f39c..32c80161c786 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
 	return container_of(encoder, struct vc4_hdmi_encoder, base.base);
 }
 
+struct drm_display_mode;
+
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
@@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
 
 	/* Callback to reset the HDMI block */
 	void (*reset)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to initialize the PHY according to the mode */
+	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
+			 struct drm_display_mode *mode);
+
+	/* Callback to disable the PHY */
+	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 	return container_of(_encoder, struct vc4_hdmi, encoder);
 }
 
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct drm_display_mode *mode);
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
new file mode 100644
index 000000000000..5a1746877bb5
--- /dev/null
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2015 Broadcom
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2013 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ */
+
+#include "vc4_hdmi.h"
+#include "vc4_hdmi_regs.h"
+
+void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+	/* PHY should be in reset, like
+	 * vc4_hdmi_encoder_disable() does.
+	 */
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
+}
+
+void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
+}
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / disable function
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Let's continue the implementation of hooks for the parts that change in the
BCM2711 SoC with the PHY RNG setup.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 15 +++++++++------
 drivers/gpu/drm/vc4/vc4_hdmi.h     |  8 ++++++++
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++
 3 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 068041145d1c..19897d6525ac 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
-		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
-			   HDMI_READ(HDMI_TX_PHY_CTL_0) &
-			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
+
+		if (vc4_hdmi->variant->phy_rng_enable)
+			vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
 
 		HDMI_WRITE(HDMI_MAI_CTL,
 			   VC4_SET_FIELD(vc4_hdmi->audio.channels,
@@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 			   VC4_HD_MAI_CTL_DLATE |
 			   VC4_HD_MAI_CTL_ERRORE |
 			   VC4_HD_MAI_CTL_ERRORF);
-		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
-			   HDMI_READ(HDMI_TX_PHY_CTL_0) |
-			   VC4_HDMI_TX_PHY_RNG_PWRDN);
+
+		if (vc4_hdmi->variant->phy_rng_disable)
+			vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
+
 		break;
 	default:
 		break;
@@ -1433,6 +1434,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.reset			= vc4_hdmi_reset,
 	.phy_init		= vc4_hdmi_phy_init,
 	.phy_disable		= vc4_hdmi_phy_disable,
+	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 32c80161c786..950accbc44e4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -47,6 +47,12 @@ struct vc4_hdmi_variant {
 
 	/* Callback to disable the PHY */
 	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to enable the RNG in the PHY */
+	void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to disable the RNG in the PHY */
+	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
 		       struct drm_display_mode *mode);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
+void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 5a1746877bb5..93287e24d7d1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -7,6 +7,7 @@
  */
 
 #include "vc4_hdmi.h"
+#include "vc4_regs.h"
 #include "vc4_hdmi_regs.h"
 
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
@@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
 {
 	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
 }
+
+void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   HDMI_READ(HDMI_TX_PHY_CTL_0) &
+		   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
+}
+
+void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   HDMI_READ(HDMI_TX_PHY_CTL_0) |
+		   VC4_HDMI_TX_PHY_RNG_PWRDN);
+}
-- 
git-series 0.9.1

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

* [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / disable function
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Let's continue the implementation of hooks for the parts that change in the
BCM2711 SoC with the PHY RNG setup.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 15 +++++++++------
 drivers/gpu/drm/vc4/vc4_hdmi.h     |  8 ++++++++
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++
 3 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 068041145d1c..19897d6525ac 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
-		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
-			   HDMI_READ(HDMI_TX_PHY_CTL_0) &
-			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
+
+		if (vc4_hdmi->variant->phy_rng_enable)
+			vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
 
 		HDMI_WRITE(HDMI_MAI_CTL,
 			   VC4_SET_FIELD(vc4_hdmi->audio.channels,
@@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 			   VC4_HD_MAI_CTL_DLATE |
 			   VC4_HD_MAI_CTL_ERRORE |
 			   VC4_HD_MAI_CTL_ERRORF);
-		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
-			   HDMI_READ(HDMI_TX_PHY_CTL_0) |
-			   VC4_HDMI_TX_PHY_RNG_PWRDN);
+
+		if (vc4_hdmi->variant->phy_rng_disable)
+			vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
+
 		break;
 	default:
 		break;
@@ -1433,6 +1434,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.reset			= vc4_hdmi_reset,
 	.phy_init		= vc4_hdmi_phy_init,
 	.phy_disable		= vc4_hdmi_phy_disable,
+	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 32c80161c786..950accbc44e4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -47,6 +47,12 @@ struct vc4_hdmi_variant {
 
 	/* Callback to disable the PHY */
 	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to enable the RNG in the PHY */
+	void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to disable the RNG in the PHY */
+	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
 		       struct drm_display_mode *mode);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
+void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 5a1746877bb5..93287e24d7d1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -7,6 +7,7 @@
  */
 
 #include "vc4_hdmi.h"
+#include "vc4_regs.h"
 #include "vc4_hdmi_regs.h"
 
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
@@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
 {
 	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
 }
+
+void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   HDMI_READ(HDMI_TX_PHY_CTL_0) &
+		   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
+}
+
+void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   HDMI_READ(HDMI_TX_PHY_CTL_0) |
+		   VC4_HDMI_TX_PHY_RNG_PWRDN);
+}
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / disable function
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Let's continue the implementation of hooks for the parts that change in the
BCM2711 SoC with the PHY RNG setup.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c     | 15 +++++++++------
 drivers/gpu/drm/vc4/vc4_hdmi.h     |  8 ++++++++
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++
 3 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 068041145d1c..19897d6525ac 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
-		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
-			   HDMI_READ(HDMI_TX_PHY_CTL_0) &
-			   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
+
+		if (vc4_hdmi->variant->phy_rng_enable)
+			vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
 
 		HDMI_WRITE(HDMI_MAI_CTL,
 			   VC4_SET_FIELD(vc4_hdmi->audio.channels,
@@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 			   VC4_HD_MAI_CTL_DLATE |
 			   VC4_HD_MAI_CTL_ERRORE |
 			   VC4_HD_MAI_CTL_ERRORF);
-		HDMI_WRITE(HDMI_TX_PHY_CTL_0,
-			   HDMI_READ(HDMI_TX_PHY_CTL_0) |
-			   VC4_HDMI_TX_PHY_RNG_PWRDN);
+
+		if (vc4_hdmi->variant->phy_rng_disable)
+			vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
+
 		break;
 	default:
 		break;
@@ -1433,6 +1434,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.reset			= vc4_hdmi_reset,
 	.phy_init		= vc4_hdmi_phy_init,
 	.phy_disable		= vc4_hdmi_phy_disable,
+	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 32c80161c786..950accbc44e4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -47,6 +47,12 @@ struct vc4_hdmi_variant {
 
 	/* Callback to disable the PHY */
 	void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to enable the RNG in the PHY */
+	void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to disable the RNG in the PHY */
+	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
 };
 
 /* HDMI audio information */
@@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
 		       struct drm_display_mode *mode);
 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
+void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 5a1746877bb5..93287e24d7d1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -7,6 +7,7 @@
  */
 
 #include "vc4_hdmi.h"
+#include "vc4_regs.h"
 #include "vc4_hdmi_regs.h"
 
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
@@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
 {
 	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
 }
+
+void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   HDMI_READ(HDMI_TX_PHY_CTL_0) &
+		   ~VC4_HDMI_TX_PHY_RNG_PWRDN);
+}
+
+void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   HDMI_READ(HDMI_TX_PHY_CTL_0) |
+		   VC4_HDMI_TX_PHY_RNG_PWRDN);
+}
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Similarly to the previous patches, the CSC setup is slightly different in
the BCM2711 than in the previous generations. Let's add a callback for it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 142 +++++++++++++++++++---------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |   7 ++-
 2 files changed, 89 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 19897d6525ac..a50220bfd5dd 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -334,12 +334,44 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
 
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
+{
+	u32 csc_ctl;
+
+	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
+				VC4_HD_CSC_CTL_ORDER);
+
+	if (enable) {
+		/* CEA VICs other than #1 requre limited range RGB
+		 * output unless overridden by an AVI infoframe.
+		 * Apply a colorspace conversion to squash 0-255 down
+		 * to 16-235.  The matrix here is:
+		 *
+		 * [ 0      0      0.8594 16]
+		 * [ 0      0.8594 0      16]
+		 * [ 0.8594 0      0      16]
+		 * [ 0      0      0       1]
+		 */
+		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
+		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
+		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
+					 VC4_HD_CSC_CTL_MODE);
+
+		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
+	}
+
+	/* The RGB order applies even when CSC is disabled. */
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
+}
+
+static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_display_mode *mode)
 {
-	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
-	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
 	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -357,7 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 					mode->crtc_vsync_end -
 					interlaced,
 					VC4_HDMI_VERTB_VBP));
-	u32 csc_ctl;
+
+	HDMI_WRITE(HDMI_HORZA,
+		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
+		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+				 VC4_HDMI_HORZA_HAP));
+
+	HDMI_WRITE(HDMI_HORZB,
+		   VC4_SET_FIELD((mode->htotal -
+				  mode->hsync_end) * pixel_rep,
+				 VC4_HDMI_HORZB_HBP) |
+		   VC4_SET_FIELD((mode->hsync_end -
+				  mode->hsync_start) * pixel_rep,
+				 VC4_HDMI_HORZB_HSP) |
+		   VC4_SET_FIELD((mode->hsync_start -
+				  mode->hdisplay) * pixel_rep,
+				 VC4_HDMI_HORZB_HFP));
+
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
+
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
+
+	HDMI_WRITE(HDMI_VID_CTL,
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+}
+
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	bool debug_dump_regs = false;
 	int ret;
 
 	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -401,68 +467,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
-	HDMI_WRITE(HDMI_HORZA,
-		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
-		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
-		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
-				 VC4_HDMI_HORZA_HAP));
-
-	HDMI_WRITE(HDMI_HORZB,
-		   VC4_SET_FIELD((mode->htotal -
-				  mode->hsync_end) * pixel_rep,
-				 VC4_HDMI_HORZB_HBP) |
-		   VC4_SET_FIELD((mode->hsync_end -
-				  mode->hsync_start) * pixel_rep,
-				 VC4_HDMI_HORZB_HSP) |
-		   VC4_SET_FIELD((mode->hsync_start -
-				  mode->hdisplay) * pixel_rep,
-				 VC4_HDMI_HORZB_HFP));
-
-	HDMI_WRITE(HDMI_VERTA0, verta);
-	HDMI_WRITE(HDMI_VERTA1, verta);
-
-	HDMI_WRITE(HDMI_VERTB0, vertb_even);
-	HDMI_WRITE(HDMI_VERTB1, vertb);
-
-	HDMI_WRITE(HDMI_VID_CTL,
-		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
-
-	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
-				VC4_HD_CSC_CTL_ORDER);
+	if (vc4_hdmi->variant->set_timings)
+		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
 
 	if (vc4_encoder->hdmi_monitor &&
-	    drm_default_rgb_quant_range(mode) ==
-	    HDMI_QUANTIZATION_RANGE_LIMITED) {
-		/* CEA VICs other than #1 requre limited range RGB
-		 * output unless overridden by an AVI infoframe.
-		 * Apply a colorspace conversion to squash 0-255 down
-		 * to 16-235.  The matrix here is:
-		 *
-		 * [ 0      0      0.8594 16]
-		 * [ 0      0.8594 0      16]
-		 * [ 0.8594 0      0      16]
-		 * [ 0      0      0       1]
-		 */
-		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
-		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
-		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
-					 VC4_HD_CSC_CTL_MODE);
+	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
+		if (vc4_hdmi->variant->csc_setup)
+			vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
 
-		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
-		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
-		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
 		vc4_encoder->limited_rgb_range = true;
 	} else {
+		if (vc4_hdmi->variant->csc_setup)
+			vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
+
 		vc4_encoder->limited_rgb_range = false;
 	}
 
-	/* The RGB order applies even when CSC is disabled. */
-	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
-
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
@@ -1431,7 +1451,9 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
 	.init_resources		= vc4_hdmi_init_resources,
+	.csc_setup		= vc4_hdmi_csc_setup,
 	.reset			= vc4_hdmi_reset,
+	.set_timings		= vc4_hdmi_set_timings,
 	.phy_init		= vc4_hdmi_phy_init,
 	.phy_disable		= vc4_hdmi_phy_disable,
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 950accbc44e4..0c32dc46d289 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -41,6 +41,13 @@ struct vc4_hdmi_variant {
 	/* Callback to reset the HDMI block */
 	void (*reset)(struct vc4_hdmi *vc4_hdmi);
 
+	/* Callback to enable / disable the CSC */
+	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
+
+	/* Callback to configure the video timings in the HDMI block */
+	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
+			    struct drm_display_mode *mode);
+
 	/* Callback to initialize the PHY according to the mode */
 	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
 			 struct drm_display_mode *mode);
-- 
git-series 0.9.1

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

* [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Similarly to the previous patches, the CSC setup is slightly different in
the BCM2711 than in the previous generations. Let's add a callback for it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 142 +++++++++++++++++++---------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |   7 ++-
 2 files changed, 89 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 19897d6525ac..a50220bfd5dd 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -334,12 +334,44 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
 
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
+{
+	u32 csc_ctl;
+
+	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
+				VC4_HD_CSC_CTL_ORDER);
+
+	if (enable) {
+		/* CEA VICs other than #1 requre limited range RGB
+		 * output unless overridden by an AVI infoframe.
+		 * Apply a colorspace conversion to squash 0-255 down
+		 * to 16-235.  The matrix here is:
+		 *
+		 * [ 0      0      0.8594 16]
+		 * [ 0      0.8594 0      16]
+		 * [ 0.8594 0      0      16]
+		 * [ 0      0      0       1]
+		 */
+		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
+		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
+		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
+					 VC4_HD_CSC_CTL_MODE);
+
+		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
+	}
+
+	/* The RGB order applies even when CSC is disabled. */
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
+}
+
+static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_display_mode *mode)
 {
-	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
-	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
 	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -357,7 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 					mode->crtc_vsync_end -
 					interlaced,
 					VC4_HDMI_VERTB_VBP));
-	u32 csc_ctl;
+
+	HDMI_WRITE(HDMI_HORZA,
+		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
+		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+				 VC4_HDMI_HORZA_HAP));
+
+	HDMI_WRITE(HDMI_HORZB,
+		   VC4_SET_FIELD((mode->htotal -
+				  mode->hsync_end) * pixel_rep,
+				 VC4_HDMI_HORZB_HBP) |
+		   VC4_SET_FIELD((mode->hsync_end -
+				  mode->hsync_start) * pixel_rep,
+				 VC4_HDMI_HORZB_HSP) |
+		   VC4_SET_FIELD((mode->hsync_start -
+				  mode->hdisplay) * pixel_rep,
+				 VC4_HDMI_HORZB_HFP));
+
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
+
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
+
+	HDMI_WRITE(HDMI_VID_CTL,
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+}
+
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	bool debug_dump_regs = false;
 	int ret;
 
 	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -401,68 +467,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
-	HDMI_WRITE(HDMI_HORZA,
-		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
-		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
-		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
-				 VC4_HDMI_HORZA_HAP));
-
-	HDMI_WRITE(HDMI_HORZB,
-		   VC4_SET_FIELD((mode->htotal -
-				  mode->hsync_end) * pixel_rep,
-				 VC4_HDMI_HORZB_HBP) |
-		   VC4_SET_FIELD((mode->hsync_end -
-				  mode->hsync_start) * pixel_rep,
-				 VC4_HDMI_HORZB_HSP) |
-		   VC4_SET_FIELD((mode->hsync_start -
-				  mode->hdisplay) * pixel_rep,
-				 VC4_HDMI_HORZB_HFP));
-
-	HDMI_WRITE(HDMI_VERTA0, verta);
-	HDMI_WRITE(HDMI_VERTA1, verta);
-
-	HDMI_WRITE(HDMI_VERTB0, vertb_even);
-	HDMI_WRITE(HDMI_VERTB1, vertb);
-
-	HDMI_WRITE(HDMI_VID_CTL,
-		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
-
-	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
-				VC4_HD_CSC_CTL_ORDER);
+	if (vc4_hdmi->variant->set_timings)
+		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
 
 	if (vc4_encoder->hdmi_monitor &&
-	    drm_default_rgb_quant_range(mode) ==
-	    HDMI_QUANTIZATION_RANGE_LIMITED) {
-		/* CEA VICs other than #1 requre limited range RGB
-		 * output unless overridden by an AVI infoframe.
-		 * Apply a colorspace conversion to squash 0-255 down
-		 * to 16-235.  The matrix here is:
-		 *
-		 * [ 0      0      0.8594 16]
-		 * [ 0      0.8594 0      16]
-		 * [ 0.8594 0      0      16]
-		 * [ 0      0      0       1]
-		 */
-		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
-		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
-		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
-					 VC4_HD_CSC_CTL_MODE);
+	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
+		if (vc4_hdmi->variant->csc_setup)
+			vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
 
-		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
-		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
-		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
 		vc4_encoder->limited_rgb_range = true;
 	} else {
+		if (vc4_hdmi->variant->csc_setup)
+			vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
+
 		vc4_encoder->limited_rgb_range = false;
 	}
 
-	/* The RGB order applies even when CSC is disabled. */
-	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
-
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
@@ -1431,7 +1451,9 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
 	.init_resources		= vc4_hdmi_init_resources,
+	.csc_setup		= vc4_hdmi_csc_setup,
 	.reset			= vc4_hdmi_reset,
+	.set_timings		= vc4_hdmi_set_timings,
 	.phy_init		= vc4_hdmi_phy_init,
 	.phy_disable		= vc4_hdmi_phy_disable,
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 950accbc44e4..0c32dc46d289 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -41,6 +41,13 @@ struct vc4_hdmi_variant {
 	/* Callback to reset the HDMI block */
 	void (*reset)(struct vc4_hdmi *vc4_hdmi);
 
+	/* Callback to enable / disable the CSC */
+	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
+
+	/* Callback to configure the video timings in the HDMI block */
+	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
+			    struct drm_display_mode *mode);
+
 	/* Callback to initialize the PHY according to the mode */
 	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
 			 struct drm_display_mode *mode);
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Similarly to the previous patches, the CSC setup is slightly different in
the BCM2711 than in the previous generations. Let's add a callback for it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 142 +++++++++++++++++++---------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |   7 ++-
 2 files changed, 89 insertions(+), 60 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 19897d6525ac..a50220bfd5dd 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -334,12 +334,44 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
 
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
+{
+	u32 csc_ctl;
+
+	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
+				VC4_HD_CSC_CTL_ORDER);
+
+	if (enable) {
+		/* CEA VICs other than #1 requre limited range RGB
+		 * output unless overridden by an AVI infoframe.
+		 * Apply a colorspace conversion to squash 0-255 down
+		 * to 16-235.  The matrix here is:
+		 *
+		 * [ 0      0      0.8594 16]
+		 * [ 0      0.8594 0      16]
+		 * [ 0.8594 0      0      16]
+		 * [ 0      0      0       1]
+		 */
+		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
+		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
+		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
+					 VC4_HD_CSC_CTL_MODE);
+
+		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
+	}
+
+	/* The RGB order applies even when CSC is disabled. */
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
+}
+
+static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_display_mode *mode)
 {
-	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
-	bool debug_dump_regs = false;
 	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
 	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
 	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -357,7 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 					mode->crtc_vsync_end -
 					interlaced,
 					VC4_HDMI_VERTB_VBP));
-	u32 csc_ctl;
+
+	HDMI_WRITE(HDMI_HORZA,
+		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
+		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+				 VC4_HDMI_HORZA_HAP));
+
+	HDMI_WRITE(HDMI_HORZB,
+		   VC4_SET_FIELD((mode->htotal -
+				  mode->hsync_end) * pixel_rep,
+				 VC4_HDMI_HORZB_HBP) |
+		   VC4_SET_FIELD((mode->hsync_end -
+				  mode->hsync_start) * pixel_rep,
+				 VC4_HDMI_HORZB_HSP) |
+		   VC4_SET_FIELD((mode->hsync_start -
+				  mode->hdisplay) * pixel_rep,
+				 VC4_HDMI_HORZB_HFP));
+
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
+
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
+
+	HDMI_WRITE(HDMI_VID_CTL,
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
+}
+
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	bool debug_dump_regs = false;
 	int ret;
 
 	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -401,68 +467,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
 		   VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
 
-	HDMI_WRITE(HDMI_HORZA,
-		   (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
-		   (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
-		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
-				 VC4_HDMI_HORZA_HAP));
-
-	HDMI_WRITE(HDMI_HORZB,
-		   VC4_SET_FIELD((mode->htotal -
-				  mode->hsync_end) * pixel_rep,
-				 VC4_HDMI_HORZB_HBP) |
-		   VC4_SET_FIELD((mode->hsync_end -
-				  mode->hsync_start) * pixel_rep,
-				 VC4_HDMI_HORZB_HSP) |
-		   VC4_SET_FIELD((mode->hsync_start -
-				  mode->hdisplay) * pixel_rep,
-				 VC4_HDMI_HORZB_HFP));
-
-	HDMI_WRITE(HDMI_VERTA0, verta);
-	HDMI_WRITE(HDMI_VERTA1, verta);
-
-	HDMI_WRITE(HDMI_VERTB0, vertb_even);
-	HDMI_WRITE(HDMI_VERTB1, vertb);
-
-	HDMI_WRITE(HDMI_VID_CTL,
-		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
-
-	csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
-				VC4_HD_CSC_CTL_ORDER);
+	if (vc4_hdmi->variant->set_timings)
+		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
 
 	if (vc4_encoder->hdmi_monitor &&
-	    drm_default_rgb_quant_range(mode) ==
-	    HDMI_QUANTIZATION_RANGE_LIMITED) {
-		/* CEA VICs other than #1 requre limited range RGB
-		 * output unless overridden by an AVI infoframe.
-		 * Apply a colorspace conversion to squash 0-255 down
-		 * to 16-235.  The matrix here is:
-		 *
-		 * [ 0      0      0.8594 16]
-		 * [ 0      0.8594 0      16]
-		 * [ 0.8594 0      0      16]
-		 * [ 0      0      0       1]
-		 */
-		csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
-		csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
-		csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
-					 VC4_HD_CSC_CTL_MODE);
+	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
+		if (vc4_hdmi->variant->csc_setup)
+			vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
 
-		HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
-		HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
-		HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
-		HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
 		vc4_encoder->limited_rgb_range = true;
 	} else {
+		if (vc4_hdmi->variant->csc_setup)
+			vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
+
 		vc4_encoder->limited_rgb_range = false;
 	}
 
-	/* The RGB order applies even when CSC is disabled. */
-	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
-
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
 	if (debug_dump_regs) {
@@ -1431,7 +1451,9 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
 	.init_resources		= vc4_hdmi_init_resources,
+	.csc_setup		= vc4_hdmi_csc_setup,
 	.reset			= vc4_hdmi_reset,
+	.set_timings		= vc4_hdmi_set_timings,
 	.phy_init		= vc4_hdmi_phy_init,
 	.phy_disable		= vc4_hdmi_phy_disable,
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 950accbc44e4..0c32dc46d289 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -41,6 +41,13 @@ struct vc4_hdmi_variant {
 	/* Callback to reset the HDMI block */
 	void (*reset)(struct vc4_hdmi *vc4_hdmi);
 
+	/* Callback to enable / disable the CSC */
+	void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
+
+	/* Callback to configure the video timings in the HDMI block */
+	void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
+			    struct drm_display_mode *mode);
+
 	/* Callback to initialize the PHY according to the mode */
 	void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
 			 struct drm_display_mode *mode);
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The vc4 CRTC will use the encoder type to control its output clock
muxing. However, this will be different from HDMI0 to HDMI1, so let's
store our type in the variant structure so that we can support multiple
controllers later on.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a50220bfd5dd..c50241170d7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1268,7 +1268,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
-	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->encoder.base.type = variant->encoder_type;
 	vc4_hdmi->pdev = pdev;
 	vc4_hdmi->variant = variant;
 
@@ -1447,6 +1447,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0c32dc46d289..0d529db4b3ab 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -27,6 +27,9 @@ struct vc4_hdmi;
 struct vc4_hdmi_register;
 
 struct vc4_hdmi_variant {
+	/* Encoder Type for that controller */
+	enum vc4_encoder_type encoder_type;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

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

* [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4 CRTC will use the encoder type to control its output clock
muxing. However, this will be different from HDMI0 to HDMI1, so let's
store our type in the variant structure so that we can support multiple
controllers later on.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a50220bfd5dd..c50241170d7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1268,7 +1268,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
-	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->encoder.base.type = variant->encoder_type;
 	vc4_hdmi->pdev = pdev;
 	vc4_hdmi->variant = variant;
 
@@ -1447,6 +1447,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0c32dc46d289..0d529db4b3ab 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -27,6 +27,9 @@ struct vc4_hdmi;
 struct vc4_hdmi_register;
 
 struct vc4_hdmi_variant {
+	/* Encoder Type for that controller */
+	enum vc4_encoder_type encoder_type;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The vc4 CRTC will use the encoder type to control its output clock
muxing. However, this will be different from HDMI0 to HDMI1, so let's
store our type in the variant structure so that we can support multiple
controllers later on.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a50220bfd5dd..c50241170d7e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1268,7 +1268,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
-	vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
+	vc4_hdmi->encoder.base.type = variant->encoder_type;
 	vc4_hdmi->pdev = pdev;
 	vc4_hdmi->variant = variant;
 
@@ -1447,6 +1447,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 }
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0c32dc46d289..0d529db4b3ab 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -27,6 +27,9 @@ struct vc4_hdmi;
 struct vc4_hdmi_register;
 
 struct vc4_hdmi_variant {
+	/* Encoder Type for that controller */
+	enum vc4_encoder_type encoder_type;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HDMI driver was registering a single debugfs file so far with the name
hdmi_regs.

Obviously, this is not going to work anymore when will have multiple HDMI
controllers since we will end up trying to register two files with the same
name.

Let's use the variant to avoid that name conflict.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c50241170d7e..ef51eedaf75a 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1370,7 +1370,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		goto err_destroy_encoder;
 
-	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
+	vc4_debugfs_add_file(drm, variant->debugfs_name,
+			     vc4_hdmi_debugfs_regs,
+			     vc4_hdmi);
 
 	return 0;
 
@@ -1448,6 +1450,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
+	.debugfs_name		= "hdmi_regs",
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0d529db4b3ab..794216f3228d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
 
+	/* Filename to expose the registers in debugfs */
+	const char *debugfs_name;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

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

* [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI driver was registering a single debugfs file so far with the name
hdmi_regs.

Obviously, this is not going to work anymore when will have multiple HDMI
controllers since we will end up trying to register two files with the same
name.

Let's use the variant to avoid that name conflict.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c50241170d7e..ef51eedaf75a 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1370,7 +1370,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		goto err_destroy_encoder;
 
-	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
+	vc4_debugfs_add_file(drm, variant->debugfs_name,
+			     vc4_hdmi_debugfs_regs,
+			     vc4_hdmi);
 
 	return 0;
 
@@ -1448,6 +1450,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
+	.debugfs_name		= "hdmi_regs",
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0d529db4b3ab..794216f3228d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
 
+	/* Filename to expose the registers in debugfs */
+	const char *debugfs_name;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI driver was registering a single debugfs file so far with the name
hdmi_regs.

Obviously, this is not going to work anymore when will have multiple HDMI
controllers since we will end up trying to register two files with the same
name.

Let's use the variant to avoid that name conflict.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c50241170d7e..ef51eedaf75a 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1370,7 +1370,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		goto err_destroy_encoder;
 
-	vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
+	vc4_debugfs_add_file(drm, variant->debugfs_name,
+			     vc4_hdmi_debugfs_regs,
+			     vc4_hdmi);
 
 	return 0;
 
@@ -1448,6 +1450,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
+	.debugfs_name		= "hdmi_regs",
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 0d529db4b3ab..794216f3228d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
 
+	/* Filename to expose the registers in debugfs */
+	const char *debugfs_name;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The CEC init code was put directly into the bind function, which was quite
inconsistent with how the audio support was done, and would prevent us from
further changes to skip that initialisation entirely.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 108 +++++++++++++++++++++-------------
 1 file changed, 67 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ef51eedaf75a..8cd08b541c14 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1171,6 +1171,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 	.adap_log_addr = vc4_hdmi_cec_adap_log_addr,
 	.adap_transmit = vc4_hdmi_cec_adap_transmit,
 };
+
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
+{
+	struct cec_connector_info conn_info;
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	u32 value;
+	int ret;
+
+	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+						  vc4_hdmi, "vc4",
+						  CEC_CAP_DEFAULTS |
+						  CEC_CAP_CONNECTOR_INFO, 1);
+	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
+	if (ret < 0)
+		return ret;
+
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
+	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
+
+	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
+	value = HDMI_READ(HDMI_CEC_CNTRL_1);
+	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
+	/*
+	 * Set the logical address to Unregistered and set the clock
+	 * divider: the hsm_clock rate and this divider setting will
+	 * give a 40 kHz CEC clock.
+	 */
+	value |= VC4_HDMI_CEC_ADDR_MASK |
+		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
+	ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
+					vc4_cec_irq_handler,
+					vc4_cec_irq_handler_thread, 0,
+					"vc4 hdmi cec", vc4_hdmi);
+	if (ret)
+		goto err_delete_cec_adap;
+
+	ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
+	if (ret < 0)
+		goto err_delete_cec_adap;
+
+	return 0;
+
+err_delete_cec_adap:
+	cec_delete_adapter(vc4_hdmi->cec_adap);
+
+	return ret;
+}
+
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
+{
+	cec_unregister_adapter(vc4_hdmi->cec_adap);
+}
+#else
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
+{
+	return 0;
+}
+
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
+
 #endif
 
 static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
@@ -1250,9 +1311,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	struct cec_connector_info conn_info;
-#endif
 	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
@@ -1332,43 +1390,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		goto err_destroy_encoder;
 
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-						  vc4_hdmi, "vc4",
-						  CEC_CAP_DEFAULTS |
-						  CEC_CAP_CONNECTOR_INFO, 1);
-	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
-	if (ret < 0)
-		goto err_destroy_conn;
-
-	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
-	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
-
-	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
-	value = HDMI_READ(HDMI_CEC_CNTRL_1);
-	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
-	/*
-	 * Set the logical address to Unregistered and set the clock
-	 * divider: the hsm_clock rate and this divider setting will
-	 * give a 40 kHz CEC clock.
-	 */
-	value |= VC4_HDMI_CEC_ADDR_MASK |
-		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
-	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
-	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
-					vc4_cec_irq_handler,
-					vc4_cec_irq_handler_thread, 0,
-					"vc4 hdmi cec", vc4_hdmi);
+	ret = vc4_hdmi_cec_init(vc4_hdmi);
 	if (ret)
-		goto err_delete_cec_adap;
-	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
-	if (ret < 0)
-		goto err_delete_cec_adap;
-#endif
+		goto err_destroy_conn;
 
 	ret = vc4_hdmi_audio_init(vc4_hdmi);
 	if (ret)
-		goto err_destroy_encoder;
+		goto err_free_cec;
 
 	vc4_debugfs_add_file(drm, variant->debugfs_name,
 			     vc4_hdmi_debugfs_regs,
@@ -1376,12 +1404,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	return 0;
 
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-err_delete_cec_adap:
-	cec_delete_adapter(vc4_hdmi->cec_adap);
+err_free_cec:
+	vc4_hdmi_cec_exit(vc4_hdmi);
 err_destroy_conn:
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
-#endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
@@ -1422,7 +1448,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	kfree(vc4_hdmi->hdmi_regset.regs);
 	kfree(vc4_hdmi->hd_regset.regs);
 
-	cec_unregister_adapter(vc4_hdmi->cec_adap);
+	vc4_hdmi_cec_exit(vc4_hdmi);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-- 
git-series 0.9.1

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

* [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The CEC init code was put directly into the bind function, which was quite
inconsistent with how the audio support was done, and would prevent us from
further changes to skip that initialisation entirely.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 108 +++++++++++++++++++++-------------
 1 file changed, 67 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ef51eedaf75a..8cd08b541c14 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1171,6 +1171,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 	.adap_log_addr = vc4_hdmi_cec_adap_log_addr,
 	.adap_transmit = vc4_hdmi_cec_adap_transmit,
 };
+
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
+{
+	struct cec_connector_info conn_info;
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	u32 value;
+	int ret;
+
+	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+						  vc4_hdmi, "vc4",
+						  CEC_CAP_DEFAULTS |
+						  CEC_CAP_CONNECTOR_INFO, 1);
+	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
+	if (ret < 0)
+		return ret;
+
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
+	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
+
+	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
+	value = HDMI_READ(HDMI_CEC_CNTRL_1);
+	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
+	/*
+	 * Set the logical address to Unregistered and set the clock
+	 * divider: the hsm_clock rate and this divider setting will
+	 * give a 40 kHz CEC clock.
+	 */
+	value |= VC4_HDMI_CEC_ADDR_MASK |
+		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
+	ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
+					vc4_cec_irq_handler,
+					vc4_cec_irq_handler_thread, 0,
+					"vc4 hdmi cec", vc4_hdmi);
+	if (ret)
+		goto err_delete_cec_adap;
+
+	ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
+	if (ret < 0)
+		goto err_delete_cec_adap;
+
+	return 0;
+
+err_delete_cec_adap:
+	cec_delete_adapter(vc4_hdmi->cec_adap);
+
+	return ret;
+}
+
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
+{
+	cec_unregister_adapter(vc4_hdmi->cec_adap);
+}
+#else
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
+{
+	return 0;
+}
+
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
+
 #endif
 
 static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
@@ -1250,9 +1311,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	struct cec_connector_info conn_info;
-#endif
 	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
@@ -1332,43 +1390,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		goto err_destroy_encoder;
 
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-						  vc4_hdmi, "vc4",
-						  CEC_CAP_DEFAULTS |
-						  CEC_CAP_CONNECTOR_INFO, 1);
-	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
-	if (ret < 0)
-		goto err_destroy_conn;
-
-	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
-	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
-
-	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
-	value = HDMI_READ(HDMI_CEC_CNTRL_1);
-	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
-	/*
-	 * Set the logical address to Unregistered and set the clock
-	 * divider: the hsm_clock rate and this divider setting will
-	 * give a 40 kHz CEC clock.
-	 */
-	value |= VC4_HDMI_CEC_ADDR_MASK |
-		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
-	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
-	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
-					vc4_cec_irq_handler,
-					vc4_cec_irq_handler_thread, 0,
-					"vc4 hdmi cec", vc4_hdmi);
+	ret = vc4_hdmi_cec_init(vc4_hdmi);
 	if (ret)
-		goto err_delete_cec_adap;
-	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
-	if (ret < 0)
-		goto err_delete_cec_adap;
-#endif
+		goto err_destroy_conn;
 
 	ret = vc4_hdmi_audio_init(vc4_hdmi);
 	if (ret)
-		goto err_destroy_encoder;
+		goto err_free_cec;
 
 	vc4_debugfs_add_file(drm, variant->debugfs_name,
 			     vc4_hdmi_debugfs_regs,
@@ -1376,12 +1404,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	return 0;
 
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-err_delete_cec_adap:
-	cec_delete_adapter(vc4_hdmi->cec_adap);
+err_free_cec:
+	vc4_hdmi_cec_exit(vc4_hdmi);
 err_destroy_conn:
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
-#endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
@@ -1422,7 +1448,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	kfree(vc4_hdmi->hdmi_regset.regs);
 	kfree(vc4_hdmi->hd_regset.regs);
 
-	cec_unregister_adapter(vc4_hdmi->cec_adap);
+	vc4_hdmi_cec_exit(vc4_hdmi);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The CEC init code was put directly into the bind function, which was quite
inconsistent with how the audio support was done, and would prevent us from
further changes to skip that initialisation entirely.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 108 +++++++++++++++++++++-------------
 1 file changed, 67 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ef51eedaf75a..8cd08b541c14 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1171,6 +1171,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
 	.adap_log_addr = vc4_hdmi_cec_adap_log_addr,
 	.adap_transmit = vc4_hdmi_cec_adap_transmit,
 };
+
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
+{
+	struct cec_connector_info conn_info;
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	u32 value;
+	int ret;
+
+	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+						  vc4_hdmi, "vc4",
+						  CEC_CAP_DEFAULTS |
+						  CEC_CAP_CONNECTOR_INFO, 1);
+	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
+	if (ret < 0)
+		return ret;
+
+	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
+	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
+
+	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
+	value = HDMI_READ(HDMI_CEC_CNTRL_1);
+	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
+	/*
+	 * Set the logical address to Unregistered and set the clock
+	 * divider: the hsm_clock rate and this divider setting will
+	 * give a 40 kHz CEC clock.
+	 */
+	value |= VC4_HDMI_CEC_ADDR_MASK |
+		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
+	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
+	ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
+					vc4_cec_irq_handler,
+					vc4_cec_irq_handler_thread, 0,
+					"vc4 hdmi cec", vc4_hdmi);
+	if (ret)
+		goto err_delete_cec_adap;
+
+	ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
+	if (ret < 0)
+		goto err_delete_cec_adap;
+
+	return 0;
+
+err_delete_cec_adap:
+	cec_delete_adapter(vc4_hdmi->cec_adap);
+
+	return ret;
+}
+
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
+{
+	cec_unregister_adapter(vc4_hdmi->cec_adap);
+}
+#else
+static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
+{
+	return 0;
+}
+
+static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
+
 #endif
 
 static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
@@ -1250,9 +1311,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	struct cec_connector_info conn_info;
-#endif
 	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
@@ -1332,43 +1390,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	if (ret)
 		goto err_destroy_encoder;
 
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
-						  vc4_hdmi, "vc4",
-						  CEC_CAP_DEFAULTS |
-						  CEC_CAP_CONNECTOR_INFO, 1);
-	ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
-	if (ret < 0)
-		goto err_destroy_conn;
-
-	cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
-	cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
-
-	HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
-	value = HDMI_READ(HDMI_CEC_CNTRL_1);
-	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
-	/*
-	 * Set the logical address to Unregistered and set the clock
-	 * divider: the hsm_clock rate and this divider setting will
-	 * give a 40 kHz CEC clock.
-	 */
-	value |= VC4_HDMI_CEC_ADDR_MASK |
-		 (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
-	HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
-	ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
-					vc4_cec_irq_handler,
-					vc4_cec_irq_handler_thread, 0,
-					"vc4 hdmi cec", vc4_hdmi);
+	ret = vc4_hdmi_cec_init(vc4_hdmi);
 	if (ret)
-		goto err_delete_cec_adap;
-	ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
-	if (ret < 0)
-		goto err_delete_cec_adap;
-#endif
+		goto err_destroy_conn;
 
 	ret = vc4_hdmi_audio_init(vc4_hdmi);
 	if (ret)
-		goto err_destroy_encoder;
+		goto err_free_cec;
 
 	vc4_debugfs_add_file(drm, variant->debugfs_name,
 			     vc4_hdmi_debugfs_regs,
@@ -1376,12 +1404,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 
 	return 0;
 
-#ifdef CONFIG_DRM_VC4_HDMI_CEC
-err_delete_cec_adap:
-	cec_delete_adapter(vc4_hdmi->cec_adap);
+err_free_cec:
+	vc4_hdmi_cec_exit(vc4_hdmi);
 err_destroy_conn:
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
-#endif
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
@@ -1422,7 +1448,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	kfree(vc4_hdmi->hdmi_regset.regs);
 	kfree(vc4_hdmi->hd_regset.regs);
 
-	cec_unregister_adapter(vc4_hdmi->cec_adap);
+	vc4_hdmi_cec_exit(vc4_hdmi);
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Similarly to the audio support, CEC support is not there yet for the
BCM2711, so let's skip entirely the CEC initialization through a variant
flag.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8cd08b541c14..86e21de6c578 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1179,6 +1179,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
 	u32 value;
 	int ret;
 
+	if (!vc4_hdmi->variant->cec_available)
+		return 0;
+
 	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 						  vc4_hdmi, "vc4",
 						  CEC_CAP_DEFAULTS |
@@ -1477,6 +1480,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 794216f3228d..3f07aebe89f1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -33,6 +33,9 @@ struct vc4_hdmi_variant {
 	/* Filename to expose the registers in debugfs */
 	const char *debugfs_name;
 
+	/* Set to true when the CEC support is available */
+	bool cec_available;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

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

* [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Similarly to the audio support, CEC support is not there yet for the
BCM2711, so let's skip entirely the CEC initialization through a variant
flag.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8cd08b541c14..86e21de6c578 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1179,6 +1179,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
 	u32 value;
 	int ret;
 
+	if (!vc4_hdmi->variant->cec_available)
+		return 0;
+
 	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 						  vc4_hdmi, "vc4",
 						  CEC_CAP_DEFAULTS |
@@ -1477,6 +1480,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 794216f3228d..3f07aebe89f1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -33,6 +33,9 @@ struct vc4_hdmi_variant {
 	/* Filename to expose the registers in debugfs */
 	const char *debugfs_name;
 
+	/* Set to true when the CEC support is available */
+	bool cec_available;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Similarly to the audio support, CEC support is not there yet for the
BCM2711, so let's skip entirely the CEC initialization through a variant
flag.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8cd08b541c14..86e21de6c578 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1179,6 +1179,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
 	u32 value;
 	int ret;
 
+	if (!vc4_hdmi->variant->cec_available)
+		return 0;
+
 	vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 						  vc4_hdmi, "vc4",
 						  CEC_CAP_DEFAULTS |
@@ -1477,6 +1480,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 794216f3228d..3f07aebe89f1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -33,6 +33,9 @@ struct vc4_hdmi_variant {
 	/* Filename to expose the registers in debugfs */
 	const char *debugfs_name;
 
+	/* Set to true when the CEC support is available */
+	bool cec_available;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove
it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 86e21de6c578..a01562a49bf0 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -55,7 +55,6 @@
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
-#define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
-- 
git-series 0.9.1

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

* [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove
it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 86e21de6c578..a01562a49bf0 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -55,7 +55,6 @@
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
-#define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove
it.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 86e21de6c578..a01562a49bf0 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -55,7 +55,6 @@
 
 #define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
-#define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The mode_valid hook on the encoder uses a pointer to a drm_encoder called
crtc, which is pretty confusing. Let's rename it to encoder to make it
clear what it is.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a01562a49bf0..17797b14cde4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 }
 
 static enum drm_mode_status
-vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
+vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
 {
 	/*
-- 
git-series 0.9.1

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

* [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The mode_valid hook on the encoder uses a pointer to a drm_encoder called
crtc, which is pretty confusing. Let's rename it to encoder to make it
clear what it is.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a01562a49bf0..17797b14cde4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 }
 
 static enum drm_mode_status
-vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
+vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
 {
 	/*
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The mode_valid hook on the encoder uses a pointer to a drm_encoder called
crtc, which is pretty confusing. Let's rename it to encoder to make it
clear what it is.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index a01562a49bf0..17797b14cde4 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 }
 
 static enum drm_mode_status
-vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
+vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
 {
 	/*
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HSM clock needs to be setup at around 101% of the pixel rate. This
was done previously by setting the clock rate to 163.7MHz at probe time and
only check in mode_valid whether the mode pixel clock was under the pixel
clock +1% or not.

However, with 4k we need to change that frequency to a higher frequency
than 163.7MHz, and yet want to have the lowest clock as possible to have a
decent power saving.

Let's change that logic a bit by setting the clock rate of the HSM clock
to the pixel rate at encoder_enable time. This would work for the
BCM2711 that support 4k resolutions and has a clock that can provide it,
but we still have to take care of a 4k panel plugged on a BCM283x SoCs
that wouldn't be able to use those modes, so let's define the limit in
the variant.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 17797b14cde4..9f30fab744f2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -53,7 +53,6 @@
 #include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
-#define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
@@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
 	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
@@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	bool debug_dump_regs = false;
+	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
 	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	ret = clk_set_rate(vc4_hdmi->pixel_clock,
-			   mode->clock * 1000 *
-			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
+	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
+	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
 		return;
@@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
+	/*
+	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
+	 * be faster than pixel clock, infinitesimally faster, tested in
+	 * simulation. Otherwise, exact value is unimportant for HDMI
+	 * operation." This conflicts with bcm2835's vc4 documentation, which
+	 * states HSM's clock has to be at least 108% of the pixel clock.
+	 *
+	 * Real life tests reveal that vc4's firmware statement holds up, and
+	 * users are able to use pixel clocks closer to HSM's, namely for
+	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
+	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
+	 * 162MHz.
+	 *
+	 * Additionally, the AXI clock needs to be at least 25% of
+	 * pixel clock, but HSM ends up being the limiting factor.
+	 */
+	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
+	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
+	if (ret) {
+		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
+	if (ret) {
+		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
+		clk_disable_unprepare(vc4_hdmi->pixel_clock);
+		return;
+	}
+
 	if (vc4_hdmi->variant->reset)
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
@@ -559,23 +589,9 @@ static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
 {
-	/*
-	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
-	 * be faster than pixel clock, infinitesimally faster, tested in
-	 * simulation. Otherwise, exact value is unimportant for HDMI
-	 * operation." This conflicts with bcm2835's vc4 documentation, which
-	 * states HSM's clock has to be at least 108% of the pixel clock.
-	 *
-	 * Real life tests reveal that vc4's firmware statement holds up, and
-	 * users are able to use pixel clocks closer to HSM's, namely for
-	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
-	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
-	 * 162MHz.
-	 *
-	 * Additionally, the AXI clock needs to be at least 25% of
-	 * pixel clock, but HSM ends up being the limiting factor.
-	 */
-	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+
+	if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
 		return MODE_CLOCK_HIGH;
 
 	return MODE_OK;
@@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		return -EPROBE_DEFER;
 	}
 
-	/* This is the rate that is set by the firmware.  The number
-	 * needs to be a bit higher than the pixel clock rate
-	 * (generally 148.5Mhz).
-	 */
-	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
-	if (ret) {
-		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
-		goto err_put_i2c;
-	}
-
-	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
-	if (ret) {
-		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
-			  ret);
-		goto err_put_i2c;
-	}
-
 	/* Only use the GPIO HPD pin if present in the DT, otherwise
 	 * we'll use the HDMI core's register.
 	 */
@@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
-	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
-err_put_i2c:
 	put_device(&vc4_hdmi->ddc->dev);
 
 	return ret;
@@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 
 	put_device(&vc4_hdmi->ddc->dev);
@@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.max_pixel_clock	= 162000000,
 	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 3f07aebe89f1..342f6e0227a2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
 	/* Set to true when the CEC support is available */
 	bool cec_available;
 
+	/* Maximum pixel clock supported by the controller (in Hz) */
+	unsigned long long max_pixel_clock;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

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

* [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HSM clock needs to be setup at around 101% of the pixel rate. This
was done previously by setting the clock rate to 163.7MHz at probe time and
only check in mode_valid whether the mode pixel clock was under the pixel
clock +1% or not.

However, with 4k we need to change that frequency to a higher frequency
than 163.7MHz, and yet want to have the lowest clock as possible to have a
decent power saving.

Let's change that logic a bit by setting the clock rate of the HSM clock
to the pixel rate at encoder_enable time. This would work for the
BCM2711 that support 4k resolutions and has a clock that can provide it,
but we still have to take care of a 4k panel plugged on a BCM283x SoCs
that wouldn't be able to use those modes, so let's define the limit in
the variant.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 17797b14cde4..9f30fab744f2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -53,7 +53,6 @@
 #include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
-#define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
@@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
 	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
@@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	bool debug_dump_regs = false;
+	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
 	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	ret = clk_set_rate(vc4_hdmi->pixel_clock,
-			   mode->clock * 1000 *
-			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
+	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
+	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
 		return;
@@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
+	/*
+	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
+	 * be faster than pixel clock, infinitesimally faster, tested in
+	 * simulation. Otherwise, exact value is unimportant for HDMI
+	 * operation." This conflicts with bcm2835's vc4 documentation, which
+	 * states HSM's clock has to be at least 108% of the pixel clock.
+	 *
+	 * Real life tests reveal that vc4's firmware statement holds up, and
+	 * users are able to use pixel clocks closer to HSM's, namely for
+	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
+	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
+	 * 162MHz.
+	 *
+	 * Additionally, the AXI clock needs to be at least 25% of
+	 * pixel clock, but HSM ends up being the limiting factor.
+	 */
+	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
+	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
+	if (ret) {
+		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
+	if (ret) {
+		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
+		clk_disable_unprepare(vc4_hdmi->pixel_clock);
+		return;
+	}
+
 	if (vc4_hdmi->variant->reset)
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
@@ -559,23 +589,9 @@ static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
 {
-	/*
-	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
-	 * be faster than pixel clock, infinitesimally faster, tested in
-	 * simulation. Otherwise, exact value is unimportant for HDMI
-	 * operation." This conflicts with bcm2835's vc4 documentation, which
-	 * states HSM's clock has to be at least 108% of the pixel clock.
-	 *
-	 * Real life tests reveal that vc4's firmware statement holds up, and
-	 * users are able to use pixel clocks closer to HSM's, namely for
-	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
-	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
-	 * 162MHz.
-	 *
-	 * Additionally, the AXI clock needs to be at least 25% of
-	 * pixel clock, but HSM ends up being the limiting factor.
-	 */
-	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+
+	if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
 		return MODE_CLOCK_HIGH;
 
 	return MODE_OK;
@@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		return -EPROBE_DEFER;
 	}
 
-	/* This is the rate that is set by the firmware.  The number
-	 * needs to be a bit higher than the pixel clock rate
-	 * (generally 148.5Mhz).
-	 */
-	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
-	if (ret) {
-		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
-		goto err_put_i2c;
-	}
-
-	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
-	if (ret) {
-		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
-			  ret);
-		goto err_put_i2c;
-	}
-
 	/* Only use the GPIO HPD pin if present in the DT, otherwise
 	 * we'll use the HDMI core's register.
 	 */
@@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
-	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
-err_put_i2c:
 	put_device(&vc4_hdmi->ddc->dev);
 
 	return ret;
@@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 
 	put_device(&vc4_hdmi->ddc->dev);
@@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.max_pixel_clock	= 162000000,
 	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 3f07aebe89f1..342f6e0227a2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
 	/* Set to true when the CEC support is available */
 	bool cec_available;
 
+	/* Maximum pixel clock supported by the controller (in Hz) */
+	unsigned long long max_pixel_clock;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HSM clock needs to be setup at around 101% of the pixel rate. This
was done previously by setting the clock rate to 163.7MHz at probe time and
only check in mode_valid whether the mode pixel clock was under the pixel
clock +1% or not.

However, with 4k we need to change that frequency to a higher frequency
than 163.7MHz, and yet want to have the lowest clock as possible to have a
decent power saving.

Let's change that logic a bit by setting the clock rate of the HSM clock
to the pixel rate at encoder_enable time. This would work for the
BCM2711 that support 4k resolutions and has a clock that can provide it,
but we still have to take care of a 4k panel plugged on a BCM283x SoCs
that wouldn't be able to use those modes, so let's define the limit in
the variant.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 17797b14cde4..9f30fab744f2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -53,7 +53,6 @@
 #include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
-#define HSM_CLOCK_FREQ 163682864
 #define CEC_CLOCK_FREQ 40000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
@@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
 
+	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	clk_disable_unprepare(vc4_hdmi->pixel_clock);
 
 	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
@@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	bool debug_dump_regs = false;
+	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
 	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
@@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
-	ret = clk_set_rate(vc4_hdmi->pixel_clock,
-			   mode->clock * 1000 *
-			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
+	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
+	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
 		return;
@@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 		return;
 	}
 
+	/*
+	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
+	 * be faster than pixel clock, infinitesimally faster, tested in
+	 * simulation. Otherwise, exact value is unimportant for HDMI
+	 * operation." This conflicts with bcm2835's vc4 documentation, which
+	 * states HSM's clock has to be at least 108% of the pixel clock.
+	 *
+	 * Real life tests reveal that vc4's firmware statement holds up, and
+	 * users are able to use pixel clocks closer to HSM's, namely for
+	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
+	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
+	 * 162MHz.
+	 *
+	 * Additionally, the AXI clock needs to be at least 25% of
+	 * pixel clock, but HSM ends up being the limiting factor.
+	 */
+	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
+	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
+	if (ret) {
+		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
+	if (ret) {
+		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
+		clk_disable_unprepare(vc4_hdmi->pixel_clock);
+		return;
+	}
+
 	if (vc4_hdmi->variant->reset)
 		vc4_hdmi->variant->reset(vc4_hdmi);
 
@@ -559,23 +589,9 @@ static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
 {
-	/*
-	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
-	 * be faster than pixel clock, infinitesimally faster, tested in
-	 * simulation. Otherwise, exact value is unimportant for HDMI
-	 * operation." This conflicts with bcm2835's vc4 documentation, which
-	 * states HSM's clock has to be at least 108% of the pixel clock.
-	 *
-	 * Real life tests reveal that vc4's firmware statement holds up, and
-	 * users are able to use pixel clocks closer to HSM's, namely for
-	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
-	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
-	 * 162MHz.
-	 *
-	 * Additionally, the AXI clock needs to be at least 25% of
-	 * pixel clock, but HSM ends up being the limiting factor.
-	 */
-	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+
+	if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
 		return MODE_CLOCK_HIGH;
 
 	return MODE_OK;
@@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 		return -EPROBE_DEFER;
 	}
 
-	/* This is the rate that is set by the firmware.  The number
-	 * needs to be a bit higher than the pixel clock rate
-	 * (generally 148.5Mhz).
-	 */
-	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
-	if (ret) {
-		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
-		goto err_put_i2c;
-	}
-
-	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
-	if (ret) {
-		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
-			  ret);
-		goto err_put_i2c;
-	}
-
 	/* Only use the GPIO HPD pin if present in the DT, otherwise
 	 * we'll use the HDMI core's register.
 	 */
@@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 err_destroy_encoder:
 	drm_encoder_cleanup(encoder);
 err_unprepare_hsm:
-	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
-err_put_i2c:
 	put_device(&vc4_hdmi->ddc->dev);
 
 	return ret;
@@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
 	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
 	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
 
-	clk_disable_unprepare(vc4_hdmi->hsm_clock);
 	pm_runtime_disable(dev);
 
 	put_device(&vc4_hdmi->ddc->dev);
@@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.max_pixel_clock	= 162000000,
 	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
 	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 3f07aebe89f1..342f6e0227a2 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
 	/* Set to true when the CEC support is available */
 	bool cec_available;
 
+	/* Maximum pixel clock supported by the controller (in Hz) */
+	unsigned long long max_pixel_clock;
+
 	/* List of the registers available on that variant */
 	const struct vc4_hdmi_register *registers;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HSM clock needs to be running at 101% the pixel clock of the HDMI
controller, however it's shared between the two HDMI controllers, which
means that if the resolutions are different between the two HDMI
controllers, and the lowest resolution is on the second (in enable order)
controller, the first HDMI controller will end up with a smaller than
expected clock rate.

Since we don't really need an exact frequency there, we can simply change
the minimum rate we expect instead.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9f30fab744f2..d99188c90ff9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	 * pixel clock, but HSM ends up being the limiting factor.
 	 */
 	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
-	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
+	ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
 		return;
-- 
git-series 0.9.1

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

* [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HSM clock needs to be running at 101% the pixel clock of the HDMI
controller, however it's shared between the two HDMI controllers, which
means that if the resolutions are different between the two HDMI
controllers, and the lowest resolution is on the second (in enable order)
controller, the first HDMI controller will end up with a smaller than
expected clock rate.

Since we don't really need an exact frequency there, we can simply change
the minimum rate we expect instead.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9f30fab744f2..d99188c90ff9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	 * pixel clock, but HSM ends up being the limiting factor.
 	 */
 	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
-	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
+	ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
 		return;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HSM clock needs to be running at 101% the pixel clock of the HDMI
controller, however it's shared between the two HDMI controllers, which
means that if the resolutions are different between the two HDMI
controllers, and the lowest resolution is on the second (in enable order)
controller, the first HDMI controller will end up with a smaller than
expected clock rate.

Since we don't really need an exact frequency there, we can simply change
the minimum rate we expect instead.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 9f30fab744f2..d99188c90ff9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	 * pixel clock, but HSM ends up being the limiting factor.
 	 */
 	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
-	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
+	ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
 	if (ret) {
 		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
 		return;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 64/78] drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The register range used for audio setup in the previous generations of
SoC were always the second range in the device tree. However, now that
the BCM2711 has way more register ranges, it makes sense to retrieve it
by names for it, while preserving the id-based lookup as a fallback.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |  9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d99188c90ff9..8b94b920be43 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -954,6 +954,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	struct snd_soc_card *card = &vc4_hdmi->audio.card;
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	const __be32 *addr;
+	int index;
 	int ret;
 
 	if (!of_find_property(dev->of_node, "dmas", NULL)) {
@@ -974,7 +975,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	 * for DMA transfers.
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
-	addr = of_get_address(dev->of_node, 1, NULL, NULL);
+	index = of_property_match_string(dev->of_node, "reg-names", "hd");
+	/* Before BCM2711, we don't have a named register range */
+	if (index < 0)
+		index = 1;
+
+	addr = of_get_address(dev->of_node, index, NULL, NULL);
+
 	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
 	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	vc4_hdmi->audio.dma_data.maxburst = 2;
-- 
git-series 0.9.1

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

* [PATCH v4 64/78] drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The register range used for audio setup in the previous generations of
SoC were always the second range in the device tree. However, now that
the BCM2711 has way more register ranges, it makes sense to retrieve it
by names for it, while preserving the id-based lookup as a fallback.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |  9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d99188c90ff9..8b94b920be43 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -954,6 +954,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	struct snd_soc_card *card = &vc4_hdmi->audio.card;
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	const __be32 *addr;
+	int index;
 	int ret;
 
 	if (!of_find_property(dev->of_node, "dmas", NULL)) {
@@ -974,7 +975,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	 * for DMA transfers.
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
-	addr = of_get_address(dev->of_node, 1, NULL, NULL);
+	index = of_property_match_string(dev->of_node, "reg-names", "hd");
+	/* Before BCM2711, we don't have a named register range */
+	if (index < 0)
+		index = 1;
+
+	addr = of_get_address(dev->of_node, index, NULL, NULL);
+
 	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
 	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	vc4_hdmi->audio.dma_data.maxburst = 2;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 64/78] drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The register range used for audio setup in the previous generations of
SoC were always the second range in the device tree. However, now that
the BCM2711 has way more register ranges, it makes sense to retrieve it
by names for it, while preserving the id-based lookup as a fallback.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |  9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index d99188c90ff9..8b94b920be43 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -954,6 +954,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	struct snd_soc_card *card = &vc4_hdmi->audio.card;
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	const __be32 *addr;
+	int index;
 	int ret;
 
 	if (!of_find_property(dev->of_node, "dmas", NULL)) {
@@ -974,7 +975,13 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 	 * for DMA transfers.
 	 * This VC/MMU should probably be exposed to avoid this kind of hacks.
 	 */
-	addr = of_get_address(dev->of_node, 1, NULL, NULL);
+	index = of_property_match_string(dev->of_node, "reg-names", "hd");
+	/* Before BCM2711, we don't have a named register range */
+	if (index < 0)
+		index = 1;
+
+	addr = of_get_address(dev->of_node, index, NULL, NULL);
+
 	vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
 	vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	vc4_hdmi->audio.dma_data.maxburst = 2;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 65/78] drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

If the encoder is disabled and re-enabled (eg mode change) all infoframes
are reset, whilst the audio subsystem know nothing about this change.
The driver therefore needs to reinstate the audio infoframe for
itself.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++++++
 drivers/gpu/drm/vc4/vc4_hdmi.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8b94b920be43..c96d9f2af2bf 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -308,8 +308,16 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 
 static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 {
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+
 	vc4_hdmi_set_avi_infoframe(encoder);
 	vc4_hdmi_set_spd_infoframe(encoder);
+	/*
+	 * If audio was streaming, then we need to reenabled the audio
+	 * infoframe here during encoder_enable.
+	 */
+	if (vc4_hdmi->audio.streaming)
+		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
 static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
@@ -694,6 +702,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	int ret;
 
+	vc4_hdmi->audio.streaming = false;
 	ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
 	if (ret)
 		dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
@@ -797,6 +806,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
+		vc4_hdmi->audio.streaming = true;
 
 		if (vc4_hdmi->variant->phy_rng_enable)
 			vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
@@ -815,6 +825,8 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (vc4_hdmi->variant->phy_rng_disable)
 			vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
 
+		vc4_hdmi->audio.streaming = false;
+
 		break;
 	default:
 		break;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 342f6e0227a2..77d47d1707ce 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -85,6 +85,8 @@ struct vc4_hdmi_audio {
 	int channels;
 	struct snd_dmaengine_dai_dma_data dma_data;
 	struct snd_pcm_substream *substream;
+
+	bool streaming;
 };
 
 /* General HDMI hardware state. */
-- 
git-series 0.9.1

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

* [PATCH v4 65/78] drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

If the encoder is disabled and re-enabled (eg mode change) all infoframes
are reset, whilst the audio subsystem know nothing about this change.
The driver therefore needs to reinstate the audio infoframe for
itself.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++++++
 drivers/gpu/drm/vc4/vc4_hdmi.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8b94b920be43..c96d9f2af2bf 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -308,8 +308,16 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 
 static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 {
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+
 	vc4_hdmi_set_avi_infoframe(encoder);
 	vc4_hdmi_set_spd_infoframe(encoder);
+	/*
+	 * If audio was streaming, then we need to reenabled the audio
+	 * infoframe here during encoder_enable.
+	 */
+	if (vc4_hdmi->audio.streaming)
+		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
 static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
@@ -694,6 +702,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	int ret;
 
+	vc4_hdmi->audio.streaming = false;
 	ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
 	if (ret)
 		dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
@@ -797,6 +806,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
+		vc4_hdmi->audio.streaming = true;
 
 		if (vc4_hdmi->variant->phy_rng_enable)
 			vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
@@ -815,6 +825,8 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (vc4_hdmi->variant->phy_rng_disable)
 			vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
 
+		vc4_hdmi->audio.streaming = false;
+
 		break;
 	default:
 		break;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 342f6e0227a2..77d47d1707ce 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -85,6 +85,8 @@ struct vc4_hdmi_audio {
 	int channels;
 	struct snd_dmaengine_dai_dma_data dma_data;
 	struct snd_pcm_substream *substream;
+
+	bool streaming;
 };
 
 /* General HDMI hardware state. */
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 65/78] drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

If the encoder is disabled and re-enabled (eg mode change) all infoframes
are reset, whilst the audio subsystem know nothing about this change.
The driver therefore needs to reinstate the audio infoframe for
itself.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 12 ++++++++++++
 drivers/gpu/drm/vc4/vc4_hdmi.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 8b94b920be43..c96d9f2af2bf 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -308,8 +308,16 @@ static void vc4_hdmi_set_audio_infoframe(struct drm_encoder *encoder)
 
 static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 {
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+
 	vc4_hdmi_set_avi_infoframe(encoder);
 	vc4_hdmi_set_spd_infoframe(encoder);
+	/*
+	 * If audio was streaming, then we need to reenabled the audio
+	 * infoframe here during encoder_enable.
+	 */
+	if (vc4_hdmi->audio.streaming)
+		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
 static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
@@ -694,6 +702,7 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	int ret;
 
+	vc4_hdmi->audio.streaming = false;
 	ret = vc4_hdmi_stop_packet(encoder, HDMI_INFOFRAME_TYPE_AUDIO);
 	if (ret)
 		dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
@@ -797,6 +806,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		vc4_hdmi_set_audio_infoframe(encoder);
+		vc4_hdmi->audio.streaming = true;
 
 		if (vc4_hdmi->variant->phy_rng_enable)
 			vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
@@ -815,6 +825,8 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (vc4_hdmi->variant->phy_rng_disable)
 			vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
 
+		vc4_hdmi->audio.streaming = false;
+
 		break;
 	default:
 		break;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 342f6e0227a2..77d47d1707ce 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -85,6 +85,8 @@ struct vc4_hdmi_audio {
 	int channels;
 	struct snd_dmaengine_dai_dma_data dma_data;
 	struct snd_pcm_substream *substream;
+
+	bool streaming;
 };
 
 /* General HDMI hardware state. */
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 66/78] drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

ALSA's iec958 plugin by default sets the block start preamble
to 8, whilst this driver was programming the hardware to expect
0xF.
Amend the hardware config to match ALSA.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c96d9f2af2bf..e1ef0907a827 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -754,10 +754,11 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
+	/* The B frame identifier should match the value used by alsa-lib (8) */
 	audio_packet_config =
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
-		VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
+		VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
 
 	channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
 	audio_packet_config |= VC4_SET_FIELD(channel_mask,
-- 
git-series 0.9.1

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

* [PATCH v4 66/78] drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

ALSA's iec958 plugin by default sets the block start preamble
to 8, whilst this driver was programming the hardware to expect
0xF.
Amend the hardware config to match ALSA.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c96d9f2af2bf..e1ef0907a827 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -754,10 +754,11 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
+	/* The B frame identifier should match the value used by alsa-lib (8) */
 	audio_packet_config =
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
-		VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
+		VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
 
 	channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
 	audio_packet_config |= VC4_SET_FIELD(channel_mask,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 66/78] drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

ALSA's iec958 plugin by default sets the block start preamble
to 8, whilst this driver was programming the hardware to expect
0xF.
Amend the hardware config to match ALSA.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index c96d9f2af2bf..e1ef0907a827 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -754,10 +754,11 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 
 	vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
 
+	/* The B frame identifier should match the value used by alsa-lib (8) */
 	audio_packet_config =
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT |
 		VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
-		VC4_SET_FIELD(0xf, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
+		VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
 
 	channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
 	audio_packet_config |= VC4_SET_FIELD(channel_mask,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 67/78] drm/vc4: hdmi: Add audio-related callbacks
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The audio configuration has changed for the BCM2711, with notably a
different parent clock and a different channel configuration.

Make that modular to be able to support the BCM2711.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++--------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++++
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index e1ef0907a827..1b6f51849d6c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -611,10 +611,22 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 	.enable = vc4_hdmi_encoder_enable,
 };
 
+static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
+{
+	int i;
+	u32 channel_map = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (channel_mask & BIT(i))
+			channel_map |= i << (3 * i);
+	}
+	return channel_map;
+}
+
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
+	u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
 	unsigned long n, m;
 
 	rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
@@ -733,7 +745,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	u32 audio_packet_config, channel_mask;
-	u32 channel_map, i;
+	u32 channel_map;
 
 	if (substream != vc4_hdmi->audio.substream)
 		return -EINVAL;
@@ -785,12 +797,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 		   VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
 		   VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
 
-	channel_map = 0;
-	for (i = 0; i < 8; i++) {
-		if (channel_mask & BIT(i))
-			channel_map |= i << (3 * i);
-	}
-
+	channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
 	HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
 	HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
 	vc4_hdmi_set_n_cts(vc4_hdmi);
@@ -1343,6 +1350,7 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
 		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
+	vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
 
 	return 0;
 }
@@ -1508,6 +1516,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.phy_disable		= vc4_hdmi_phy_disable,
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
 	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
+	.channel_map		= vc4_hdmi_channel_map,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 77d47d1707ce..4aea5ee8a91d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -72,6 +72,9 @@ struct vc4_hdmi_variant {
 
 	/* Callback to disable the RNG in the PHY */
 	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to get channel map */
+	u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
 };
 
 /* HDMI audio information */
@@ -112,6 +115,7 @@ struct vc4_hdmi {
 
 	struct clk *pixel_clock;
 	struct clk *hsm_clock;
+	struct clk *audio_clock;
 
 	struct debugfs_regset32 hdmi_regset;
 	struct debugfs_regset32 hd_regset;
-- 
git-series 0.9.1

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

* [PATCH v4 67/78] drm/vc4: hdmi: Add audio-related callbacks
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The audio configuration has changed for the BCM2711, with notably a
different parent clock and a different channel configuration.

Make that modular to be able to support the BCM2711.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++--------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++++
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index e1ef0907a827..1b6f51849d6c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -611,10 +611,22 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 	.enable = vc4_hdmi_encoder_enable,
 };
 
+static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
+{
+	int i;
+	u32 channel_map = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (channel_mask & BIT(i))
+			channel_map |= i << (3 * i);
+	}
+	return channel_map;
+}
+
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
+	u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
 	unsigned long n, m;
 
 	rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
@@ -733,7 +745,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	u32 audio_packet_config, channel_mask;
-	u32 channel_map, i;
+	u32 channel_map;
 
 	if (substream != vc4_hdmi->audio.substream)
 		return -EINVAL;
@@ -785,12 +797,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 		   VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
 		   VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
 
-	channel_map = 0;
-	for (i = 0; i < 8; i++) {
-		if (channel_mask & BIT(i))
-			channel_map |= i << (3 * i);
-	}
-
+	channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
 	HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
 	HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
 	vc4_hdmi_set_n_cts(vc4_hdmi);
@@ -1343,6 +1350,7 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
 		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
+	vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
 
 	return 0;
 }
@@ -1508,6 +1516,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.phy_disable		= vc4_hdmi_phy_disable,
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
 	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
+	.channel_map		= vc4_hdmi_channel_map,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 77d47d1707ce..4aea5ee8a91d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -72,6 +72,9 @@ struct vc4_hdmi_variant {
 
 	/* Callback to disable the RNG in the PHY */
 	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to get channel map */
+	u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
 };
 
 /* HDMI audio information */
@@ -112,6 +115,7 @@ struct vc4_hdmi {
 
 	struct clk *pixel_clock;
 	struct clk *hsm_clock;
+	struct clk *audio_clock;
 
 	struct debugfs_regset32 hdmi_regset;
 	struct debugfs_regset32 hd_regset;
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 67/78] drm/vc4: hdmi: Add audio-related callbacks
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

From: Dave Stevenson <dave.stevenson@raspberrypi.com>

The audio configuration has changed for the BCM2711, with notably a
different parent clock and a different channel configuration.

Make that modular to be able to support the BCM2711.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 25 +++++++++++++++++--------
 drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++++
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index e1ef0907a827..1b6f51849d6c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -611,10 +611,22 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
 	.enable = vc4_hdmi_encoder_enable,
 };
 
+static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
+{
+	int i;
+	u32 channel_map = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (channel_mask & BIT(i))
+			channel_map |= i << (3 * i);
+	}
+	return channel_map;
+}
+
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
-	u32 hsm_clock = clk_get_rate(vc4_hdmi->hsm_clock);
+	u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
 	unsigned long n, m;
 
 	rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
@@ -733,7 +745,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 	struct vc4_hdmi *vc4_hdmi = dai_to_hdmi(dai);
 	struct device *dev = &vc4_hdmi->pdev->dev;
 	u32 audio_packet_config, channel_mask;
-	u32 channel_map, i;
+	u32 channel_map;
 
 	if (substream != vc4_hdmi->audio.substream)
 		return -EINVAL;
@@ -785,12 +797,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
 		   VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
 		   VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
 
-	channel_map = 0;
-	for (i = 0; i < 8; i++) {
-		if (channel_mask & BIT(i))
-			channel_map |= i << (3 * i);
-	}
-
+	channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
 	HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
 	HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
 	vc4_hdmi_set_n_cts(vc4_hdmi);
@@ -1343,6 +1350,7 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 		DRM_ERROR("Failed to get HDMI state machine clock\n");
 		return PTR_ERR(vc4_hdmi->hsm_clock);
 	}
+	vc4_hdmi->audio_clock = vc4_hdmi->hsm_clock;
 
 	return 0;
 }
@@ -1508,6 +1516,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.phy_disable		= vc4_hdmi_phy_disable,
 	.phy_rng_enable		= vc4_hdmi_phy_rng_enable,
 	.phy_rng_disable	= vc4_hdmi_phy_rng_disable,
+	.channel_map		= vc4_hdmi_channel_map,
 };
 
 static const struct of_device_id vc4_hdmi_dt_match[] = {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 77d47d1707ce..4aea5ee8a91d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -72,6 +72,9 @@ struct vc4_hdmi_variant {
 
 	/* Callback to disable the RNG in the PHY */
 	void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
+
+	/* Callback to get channel map */
+	u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);
 };
 
 /* HDMI audio information */
@@ -112,6 +115,7 @@ struct vc4_hdmi {
 
 	struct clk *pixel_clock;
 	struct clk *hsm_clock;
+	struct clk *audio_clock;
 
 	struct debugfs_regset32 hdmi_regset;
 	struct debugfs_regset32 hd_regset;
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The HDMI driver was registering a single ALSA card so far with the name
vc4-hdmi.

Obviously, this is not going to work anymore when will have multiple HDMI
controllers since we will end up trying to register two files with the same
name.

Let's use the variant to avoid that name conflict.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1b6f51849d6c..0a9a323e03d8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1044,7 +1044,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 
 	card->dai_link = dai_link;
 	card->num_links = 1;
-	card->name = "vc4-hdmi";
+	card->name = vc4_hdmi->variant->card_name;
 	card->dev = dev;
 
 	/*
@@ -1503,6 +1503,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.card_name		= "vc4-hdmi",
 	.max_pixel_clock	= 162000000,
 	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 4aea5ee8a91d..34138e0dd4a6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
 
+	/* ALSA card name */
+	const char *card_name;
+
 	/* Filename to expose the registers in debugfs */
 	const char *debugfs_name;
 
-- 
git-series 0.9.1

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

* [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI driver was registering a single ALSA card so far with the name
vc4-hdmi.

Obviously, this is not going to work anymore when will have multiple HDMI
controllers since we will end up trying to register two files with the same
name.

Let's use the variant to avoid that name conflict.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1b6f51849d6c..0a9a323e03d8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1044,7 +1044,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 
 	card->dai_link = dai_link;
 	card->num_links = 1;
-	card->name = "vc4-hdmi";
+	card->name = vc4_hdmi->variant->card_name;
 	card->dev = dev;
 
 	/*
@@ -1503,6 +1503,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.card_name		= "vc4-hdmi",
 	.max_pixel_clock	= 162000000,
 	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 4aea5ee8a91d..34138e0dd4a6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
 
+	/* ALSA card name */
+	const char *card_name;
+
 	/* Filename to expose the registers in debugfs */
 	const char *debugfs_name;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI driver was registering a single ALSA card so far with the name
vc4-hdmi.

Obviously, this is not going to work anymore when will have multiple HDMI
controllers since we will end up trying to register two files with the same
name.

Let's use the variant to avoid that name conflict.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
 drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1b6f51849d6c..0a9a323e03d8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1044,7 +1044,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 
 	card->dai_link = dai_link;
 	card->num_links = 1;
-	card->name = "vc4-hdmi";
+	card->name = vc4_hdmi->variant->card_name;
 	card->dev = dev;
 
 	/*
@@ -1503,6 +1503,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
 static const struct vc4_hdmi_variant bcm2835_variant = {
 	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
 	.debugfs_name		= "hdmi_regs",
+	.card_name		= "vc4-hdmi",
 	.max_pixel_clock	= 162000000,
 	.cec_available		= true,
 	.registers		= vc4_hdmi_fields,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 4aea5ee8a91d..34138e0dd4a6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
 
+	/* ALSA card name */
+	const char *card_name;
+
 	/* Filename to expose the registers in debugfs */
 	const char *debugfs_name;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The current code has some logic, disabled by default, to dump the register
setup in the HDMI controller.

However, since we're going to split those functions in multiple, shorter,
functions that only make sense where they are called in sequence, keeping
the register dump makes little sense.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 0a9a323e03d8..4058985940e6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	bool debug_dump_regs = false;
 	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
@@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->phy_init)
 		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
-
-		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
-		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
-		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
-	}
-
 	HDMI_WRITE(HDMI_VID_CTL, 0);
 
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
@@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
-
-		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
-		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
-		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
-	}
-
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) |
 		   VC4_HD_VID_CTL_ENABLE |
-- 
git-series 0.9.1

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

* [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The current code has some logic, disabled by default, to dump the register
setup in the HDMI controller.

However, since we're going to split those functions in multiple, shorter,
functions that only make sense where they are called in sequence, keeping
the register dump makes little sense.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 0a9a323e03d8..4058985940e6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	bool debug_dump_regs = false;
 	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
@@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->phy_init)
 		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
-
-		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
-		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
-		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
-	}
-
 	HDMI_WRITE(HDMI_VID_CTL, 0);
 
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
@@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
-
-		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
-		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
-		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
-	}
-
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) |
 		   VC4_HD_VID_CTL_ENABLE |
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The current code has some logic, disabled by default, to dump the register
setup in the HDMI controller.

However, since we're going to split those functions in multiple, shorter,
functions that only make sense where they are called in sequence, keeping
the register dump makes little sense.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 0a9a323e03d8..4058985940e6 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
-	bool debug_dump_regs = false;
 	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
@@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->phy_init)
 		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
-
-		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
-		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
-		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
-	}
-
 	HDMI_WRITE(HDMI_VID_CTL, 0);
 
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
@@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
 
-	if (debug_dump_regs) {
-		struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
-
-		dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
-		drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
-		drm_print_regset32(&p, &vc4_hdmi->hd_regset);
-	}
-
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) |
 		   VC4_HD_VID_CTL_ENABLE |
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to avoid a pixel getting stuck in an unflushable FIFO, we need to
recenter the FIFO every time we're doing a modeset and not only if we're
connected to an HDMI monitor.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4058985940e6..00592c1ada73 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 }
 
+static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
+{
+	u32 drift;
+	int ret;
+
+	drift = HDMI_READ(HDMI_FIFO_CTL);
+	drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
+
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift | VC4_HDMI_FIFO_CTL_RECENTER);
+	usleep_range(1000, 1100);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift | VC4_HDMI_FIFO_CTL_RECENTER);
+
+	ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
+		       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
+	WARN_ONCE(ret, "Timeout waiting for "
+		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
+}
+
 static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
@@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	if (vc4_encoder->hdmi_monitor) {
-		u32 drift;
-
 		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
@@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 			   VC4_HDMI_RAM_PACKET_ENABLE);
 
 		vc4_hdmi_set_infoframes(encoder);
-
-		drift = HDMI_READ(HDMI_FIFO_CTL);
-		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
-
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
-		usleep_range(1000, 1100);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
-
-		ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
-			       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
-		WARN_ONCE(ret, "Timeout waiting for "
-			  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 	}
+
+	vc4_hdmi_recenter_fifo(vc4_hdmi);
 }
 
 static enum drm_mode_status
-- 
git-series 0.9.1

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

* [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid a pixel getting stuck in an unflushable FIFO, we need to
recenter the FIFO every time we're doing a modeset and not only if we're
connected to an HDMI monitor.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4058985940e6..00592c1ada73 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 }
 
+static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
+{
+	u32 drift;
+	int ret;
+
+	drift = HDMI_READ(HDMI_FIFO_CTL);
+	drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
+
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift | VC4_HDMI_FIFO_CTL_RECENTER);
+	usleep_range(1000, 1100);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift | VC4_HDMI_FIFO_CTL_RECENTER);
+
+	ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
+		       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
+	WARN_ONCE(ret, "Timeout waiting for "
+		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
+}
+
 static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
@@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	if (vc4_encoder->hdmi_monitor) {
-		u32 drift;
-
 		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
@@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 			   VC4_HDMI_RAM_PACKET_ENABLE);
 
 		vc4_hdmi_set_infoframes(encoder);
-
-		drift = HDMI_READ(HDMI_FIFO_CTL);
-		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
-
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
-		usleep_range(1000, 1100);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
-
-		ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
-			       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
-		WARN_ONCE(ret, "Timeout waiting for "
-			  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 	}
+
+	vc4_hdmi_recenter_fifo(vc4_hdmi);
 }
 
 static enum drm_mode_status
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid a pixel getting stuck in an unflushable FIFO, we need to
recenter the FIFO every time we're doing a modeset and not only if we're
connected to an HDMI monitor.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4058985940e6..00592c1ada73 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 }
 
+static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
+{
+	u32 drift;
+	int ret;
+
+	drift = HDMI_READ(HDMI_FIFO_CTL);
+	drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
+
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift | VC4_HDMI_FIFO_CTL_RECENTER);
+	usleep_range(1000, 1100);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
+	HDMI_WRITE(HDMI_FIFO_CTL,
+		   drift | VC4_HDMI_FIFO_CTL_RECENTER);
+
+	ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
+		       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
+	WARN_ONCE(ret, "Timeout waiting for "
+		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
+}
+
 static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
@@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	if (vc4_encoder->hdmi_monitor) {
-		u32 drift;
-
 		WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
 			  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
@@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 			   VC4_HDMI_RAM_PACKET_ENABLE);
 
 		vc4_hdmi_set_infoframes(encoder);
-
-		drift = HDMI_READ(HDMI_FIFO_CTL);
-		drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
-
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
-		usleep_range(1000, 1100);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
-		HDMI_WRITE(HDMI_FIFO_CTL,
-			   drift | VC4_HDMI_FIFO_CTL_RECENTER);
-
-		ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
-			       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
-		WARN_ONCE(ret, "Timeout waiting for "
-			  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 	}
+
+	vc4_hdmi_recenter_fifo(vc4_hdmi);
 }
 
 static enum drm_mode_status
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to prevent some pixels getting stuck in an unflushable FIFO on
bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI
controller (the encoder) in an intertwined way, and with tight delays.

However, the atomic callbacks don't really provide a way to work with
either constraints, so we need to roll our own callbacks so that we can
provide those guarantees.

Since those callbacks have been implemented and called in the CRTC code, we
can just implement them in the HDMI driver now.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 00592c1ada73..bbe521ab000b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
-static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	int ret;
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+}
+
+static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	int ret;
 
 	if (vc4_hdmi->variant->phy_disable)
 		vc4_hdmi->variant->phy_disable(vc4_hdmi);
@@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
 
+static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
 static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 {
 	u32 csc_ctl;
@@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
@@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 
 	if (vc4_hdmi->variant->set_timings)
 		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
+}
+
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
 	if (vc4_encoder->hdmi_monitor &&
 	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
@@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+}
+
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	int ret;
 
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) |
@@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	vc4_hdmi_recenter_fifo(vc4_hdmi);
 }
 
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
 static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
@@ -1362,6 +1388,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
 	vc4_hdmi->encoder.base.type = variant->encoder_type;
+	vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
+	vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
+	vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
+	vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
+	vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
 	vc4_hdmi->pdev = pdev;
 	vc4_hdmi->variant = variant;
 
-- 
git-series 0.9.1

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

* [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to prevent some pixels getting stuck in an unflushable FIFO on
bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI
controller (the encoder) in an intertwined way, and with tight delays.

However, the atomic callbacks don't really provide a way to work with
either constraints, so we need to roll our own callbacks so that we can
provide those guarantees.

Since those callbacks have been implemented and called in the CRTC code, we
can just implement them in the HDMI driver now.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 00592c1ada73..bbe521ab000b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
-static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	int ret;
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+}
+
+static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	int ret;
 
 	if (vc4_hdmi->variant->phy_disable)
 		vc4_hdmi->variant->phy_disable(vc4_hdmi);
@@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
 
+static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
 static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 {
 	u32 csc_ctl;
@@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
@@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 
 	if (vc4_hdmi->variant->set_timings)
 		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
+}
+
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
 	if (vc4_encoder->hdmi_monitor &&
 	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
@@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+}
+
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	int ret;
 
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) |
@@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	vc4_hdmi_recenter_fifo(vc4_hdmi);
 }
 
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
 static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
@@ -1362,6 +1388,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
 	vc4_hdmi->encoder.base.type = variant->encoder_type;
+	vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
+	vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
+	vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
+	vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
+	vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
 	vc4_hdmi->pdev = pdev;
 	vc4_hdmi->variant = variant;
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to prevent some pixels getting stuck in an unflushable FIFO on
bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI
controller (the encoder) in an intertwined way, and with tight delays.

However, the atomic callbacks don't really provide a way to work with
either constraints, so we need to roll our own callbacks so that we can
provide those guarantees.

Since those callbacks have been implemented and called in the CRTC code, we
can just implement them in the HDMI driver now.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 00592c1ada73..bbe521ab000b 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
 		vc4_hdmi_set_audio_infoframe(encoder);
 }
 
-static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 {
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	int ret;
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+}
+
+static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	int ret;
 
 	if (vc4_hdmi->variant->phy_disable)
 		vc4_hdmi->variant->phy_disable(vc4_hdmi);
@@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
 		DRM_ERROR("Failed to release power domain: %d\n", ret);
 }
 
+static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
 static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 {
 	u32 csc_ctl;
@@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 		  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
 }
 
-static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 {
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
-	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
 	unsigned long pixel_rate, hsm_rate;
 	int ret;
 
@@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 
 	if (vc4_hdmi->variant->set_timings)
 		vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
+}
+
+static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
 	if (vc4_encoder->hdmi_monitor &&
 	    drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
@@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	}
 
 	HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
+}
+
+static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
+{
+	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	int ret;
 
 	HDMI_WRITE(HDMI_VID_CTL,
 		   HDMI_READ(HDMI_VID_CTL) |
@@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
 	vc4_hdmi_recenter_fifo(vc4_hdmi);
 }
 
+static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
 static enum drm_mode_status
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
 			    const struct drm_display_mode *mode)
@@ -1362,6 +1388,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 	dev_set_drvdata(dev, vc4_hdmi);
 	encoder = &vc4_hdmi->encoder.base.base;
 	vc4_hdmi->encoder.base.type = variant->encoder_type;
+	vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
+	vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
+	vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
+	vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
+	vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
 	vc4_hdmi->pdev = pdev;
 	vc4_hdmi->variant = variant;
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The VID_CTL setup is done in several places in the driver even though it's
not really required. Let's simplify it a bit to do the configuration in one
go.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index bbe521ab000b..f56a718a3643 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
-
-	HDMI_WRITE(HDMI_VID_CTL,
-		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 }
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
@@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->phy_init)
 		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
-	HDMI_WRITE(HDMI_VID_CTL, 0);
-
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
@@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
 
 static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
 {
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
 	int ret;
 
 	HDMI_WRITE(HDMI_VID_CTL,
-		   HDMI_READ(HDMI_VID_CTL) |
 		   VC4_HD_VID_CTL_ENABLE |
 		   VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
-		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
 	if (vc4_encoder->hdmi_monitor) {
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
-- 
git-series 0.9.1

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

* [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The VID_CTL setup is done in several places in the driver even though it's
not really required. Let's simplify it a bit to do the configuration in one
go.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index bbe521ab000b..f56a718a3643 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
-
-	HDMI_WRITE(HDMI_VID_CTL,
-		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 }
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
@@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->phy_init)
 		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
-	HDMI_WRITE(HDMI_VID_CTL, 0);
-
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
@@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
 
 static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
 {
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
 	int ret;
 
 	HDMI_WRITE(HDMI_VID_CTL,
-		   HDMI_READ(HDMI_VID_CTL) |
 		   VC4_HD_VID_CTL_ENABLE |
 		   VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
-		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
 	if (vc4_encoder->hdmi_monitor) {
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The VID_CTL setup is done in several places in the driver even though it's
not really required. Let's simplify it a bit to do the configuration in one
go.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index bbe521ab000b..f56a718a3643 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
-
-	HDMI_WRITE(HDMI_VID_CTL,
-		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
-		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 }
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
@@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
 	if (vc4_hdmi->variant->phy_init)
 		vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
 
-	HDMI_WRITE(HDMI_VID_CTL, 0);
-
 	HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 		   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
 		   VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
@@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
 
 static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
 {
+	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
+	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
 	int ret;
 
 	HDMI_WRITE(HDMI_VID_CTL,
-		   HDMI_READ(HDMI_VID_CTL) |
 		   VC4_HD_VID_CTL_ENABLE |
 		   VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
-		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
+		   VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
+		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
+		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
 	if (vc4_encoder->hdmi_monitor) {
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

In order to avoid pixels getting stuck in an unflushable FIFO, we need when
we disable the HDMI controller to switch away from getting our pixels from
the pixelvalve and instead use blank pixels, and switch back to the
pixelvalve when we enable the HDMI controller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |  9 +++++++++
 drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f56a718a3643..37463b016b47 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+
+	HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
+		   VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
+
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
 }
 
 static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
@@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
 		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
 		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
+
 	if (vc4_encoder->hdmi_monitor) {
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index d1e8961edaa0..30af52b406f1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -723,6 +723,9 @@
 # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET	BIT(29)
 # define VC4_HD_VID_CTL_VSYNC_LOW		BIT(28)
 # define VC4_HD_VID_CTL_HSYNC_LOW		BIT(27)
+# define VC4_HD_VID_CTL_CLRSYNC			BIT(24)
+# define VC4_HD_VID_CTL_CLRRGB			BIT(23)
+# define VC4_HD_VID_CTL_BLANKPIX		BIT(18)
 
 # define VC4_HD_CSC_CTL_ORDER_MASK		VC4_MASK(7, 5)
 # define VC4_HD_CSC_CTL_ORDER_SHIFT		5
-- 
git-series 0.9.1

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

* [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid pixels getting stuck in an unflushable FIFO, we need when
we disable the HDMI controller to switch away from getting our pixels from
the pixelvalve and instead use blank pixels, and switch back to the
pixelvalve when we enable the HDMI controller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |  9 +++++++++
 drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f56a718a3643..37463b016b47 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+
+	HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
+		   VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
+
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
 }
 
 static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
@@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
 		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
 		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
+
 	if (vc4_encoder->hdmi_monitor) {
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index d1e8961edaa0..30af52b406f1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -723,6 +723,9 @@
 # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET	BIT(29)
 # define VC4_HD_VID_CTL_VSYNC_LOW		BIT(28)
 # define VC4_HD_VID_CTL_HSYNC_LOW		BIT(27)
+# define VC4_HD_VID_CTL_CLRSYNC			BIT(24)
+# define VC4_HD_VID_CTL_CLRRGB			BIT(23)
+# define VC4_HD_VID_CTL_BLANKPIX		BIT(18)
 
 # define VC4_HD_CSC_CTL_ORDER_MASK		VC4_MASK(7, 5)
 # define VC4_HD_CSC_CTL_ORDER_SHIFT		5
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

In order to avoid pixels getting stuck in an unflushable FIFO, we need when
we disable the HDMI controller to switch away from getting our pixels from
the pixelvalve and instead use blank pixels, and switch back to the
pixelvalve when we enable the HDMI controller.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |  9 +++++++++
 drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index f56a718a3643..37463b016b47 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
 	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
 
 	HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
+
+	HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
+		   VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
+
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
 }
 
 static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
@@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
 		   (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
 		   (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
 
+	HDMI_WRITE(HDMI_VID_CTL,
+		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
+
 	if (vc4_encoder->hdmi_monitor) {
 		HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
 			   HDMI_READ(HDMI_SCHEDULER_CONTROL) |
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index d1e8961edaa0..30af52b406f1 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -723,6 +723,9 @@
 # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET	BIT(29)
 # define VC4_HD_VID_CTL_VSYNC_LOW		BIT(28)
 # define VC4_HD_VID_CTL_HSYNC_LOW		BIT(27)
+# define VC4_HD_VID_CTL_CLRSYNC			BIT(24)
+# define VC4_HD_VID_CTL_CLRRGB			BIT(23)
+# define VC4_HD_VID_CTL_BLANKPIX		BIT(18)
 
 # define VC4_HD_CSC_CTL_ORDER_MASK		VC4_MASK(7, 5)
 # define VC4_HD_CSC_CTL_ORDER_SHIFT		5
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Now that the driver is ready for it, let's bring in the HDMI controllers
variants for the BCM2711.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 278 +++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  36 ++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c  | 480 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h      |   2 +-
 5 files changed, 997 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 37463b016b47..d5ba0b1b73a9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -43,6 +43,7 @@
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/rational.h>
+#include <linux/reset.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm_drm_eld.h>
 #include <sound/pcm_params.h>
@@ -53,6 +54,31 @@
 #include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
+#define VC5_HDMI_HORZA_HFP_SHIFT		16
+#define VC5_HDMI_HORZA_HFP_MASK			VC4_MASK(28, 16)
+#define VC5_HDMI_HORZA_VPOS			BIT(15)
+#define VC5_HDMI_HORZA_HPOS			BIT(14)
+#define VC5_HDMI_HORZA_HAP_SHIFT		0
+#define VC5_HDMI_HORZA_HAP_MASK			VC4_MASK(13, 0)
+
+#define VC5_HDMI_HORZB_HBP_SHIFT		16
+#define VC5_HDMI_HORZB_HBP_MASK			VC4_MASK(26, 16)
+#define VC5_HDMI_HORZB_HSP_SHIFT		0
+#define VC5_HDMI_HORZB_HSP_MASK			VC4_MASK(10, 0)
+
+#define VC5_HDMI_VERTA_VSP_SHIFT		24
+#define VC5_HDMI_VERTA_VSP_MASK			VC4_MASK(28, 24)
+#define VC5_HDMI_VERTA_VFP_SHIFT		16
+#define VC5_HDMI_VERTA_VFP_MASK			VC4_MASK(22, 16)
+#define VC5_HDMI_VERTA_VAL_SHIFT		0
+#define VC5_HDMI_VERTA_VAL_MASK			VC4_MASK(12, 0)
+
+#define VC5_HDMI_VERTB_VSPO_SHIFT		16
+#define VC5_HDMI_VERTB_VSPO_MASK		VC4_MASK(29, 16)
+
+# define VC4_HD_M_SW_RST			BIT(2)
+# define VC4_HD_M_ENABLE			BIT(0)
+
 #define CEC_CLOCK_FREQ 40000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
@@ -82,6 +108,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
 	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 }
 
+static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
+{
+	reset_control_reset(vc4_hdmi->reset);
+
+	HDMI_WRITE(HDMI_DVP_CTL, 0);
+
+	HDMI_WRITE(HDMI_CLOCK_STOP,
+		   HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -391,6 +427,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 }
 
+static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
+{
+	u32 csc_ctl;
+
+	csc_ctl = 0x07;	/* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
+
+	if (enable) {
+		/* CEA VICs other than #1 requre limited range RGB
+		 * output unless overridden by an AVI infoframe.
+		 * Apply a colorspace conversion to squash 0-255 down
+		 * to 16-235.  The matrix here is:
+		 *
+		 * [ 0.8594 0      0      16]
+		 * [ 0      0.8594 0      16]
+		 * [ 0      0      0.8594 16]
+		 * [ 0      0      0       1]
+		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+		 */
+		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
+	} else {
+		/* Still use the matrix for full range, but make it unity.
+		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+		 */
+		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
+	}
+
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
+}
+
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 				 struct drm_display_mode *mode)
 {
@@ -435,6 +510,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 }
+static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_display_mode *mode)
+{
+	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
+	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
+	u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
+				   VC5_HDMI_VERTA_VSP) |
+		     VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
+				   VC5_HDMI_VERTA_VFP) |
+		     VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
+	u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
+		     VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
+				   VC4_HDMI_VERTB_VBP));
+	u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
+			  VC4_SET_FIELD(mode->crtc_vtotal -
+					mode->crtc_vsync_end -
+					interlaced,
+					VC4_HDMI_VERTB_VBP));
+
+	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
+	HDMI_WRITE(HDMI_HORZA,
+		   (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
+		   (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+				 VC5_HDMI_HORZA_HAP) |
+		   VC4_SET_FIELD((mode->hsync_start -
+				  mode->hdisplay) * pixel_rep,
+				 VC5_HDMI_HORZA_HFP));
+
+	HDMI_WRITE(HDMI_HORZB,
+		   VC4_SET_FIELD((mode->htotal -
+				  mode->hsync_end) * pixel_rep,
+				 VC5_HDMI_HORZB_HBP) |
+		   VC4_SET_FIELD((mode->hsync_end -
+				  mode->hsync_start) * pixel_rep,
+				 VC5_HDMI_HORZB_HSP));
+
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
+
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
+
+	HDMI_WRITE(HDMI_CLOCK_STOP, 0);
+}
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 {
@@ -645,6 +767,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
 	return channel_map;
 }
 
+static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
+{
+	int i;
+	u32 channel_map = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (channel_mask & BIT(i))
+			channel_map |= i << (4 * i);
+	}
+	return channel_map;
+}
+
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
@@ -1377,6 +1511,98 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 	return 0;
 }
 
+static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
+{
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
+					       resource_size(res));
+	if (IS_ERR(vc4_hdmi->hdmicore_regs))
+		return PTR_ERR(vc4_hdmi->hdmicore_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->hd_regs))
+		return PTR_ERR(vc4_hdmi->hd_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->cec_regs))
+		return PTR_ERR(vc4_hdmi->cec_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->csc_regs))
+		return PTR_ERR(vc4_hdmi->csc_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->dvp_regs))
+		return PTR_ERR(vc4_hdmi->dvp_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->phy_regs))
+		return PTR_ERR(vc4_hdmi->phy_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->ram_regs))
+		return PTR_ERR(vc4_hdmi->ram_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->rm_regs))
+		return PTR_ERR(vc4_hdmi->rm_regs);
+
+	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+	if (IS_ERR(vc4_hdmi->hsm_clock)) {
+		DRM_ERROR("Failed to get HDMI state machine clock\n");
+		return PTR_ERR(vc4_hdmi->hsm_clock);
+	}
+
+	vc4_hdmi->audio_clock = devm_clk_get(dev, "clk-108M");
+	if (IS_ERR(vc4_hdmi->audio_clock)) {
+		DRM_ERROR("Failed to get 108MHz clock\n");
+		return PTR_ERR(vc4_hdmi->audio_clock);
+	}
+
+	vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(vc4_hdmi->reset)) {
+		DRM_ERROR("Failed to get HDMI reset line\n");
+		return PTR_ERR(vc4_hdmi->reset);
+	}
+
+	return 0;
+}
+
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
 	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -1547,8 +1773,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.channel_map		= vc4_hdmi_channel_map,
 };
 
+static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
+	.debugfs_name		= "hdmi0_regs",
+	.card_name		= "vc4-hdmi-0",
+	.max_pixel_clock	= 297000000,
+	.registers		= vc5_hdmi_hdmi0_fields,
+	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
+	.phy_lane_mapping	= {
+		PHY_LANE_0,
+		PHY_LANE_1,
+		PHY_LANE_2,
+		PHY_LANE_CK,
+	},
+
+	.init_resources		= vc5_hdmi_init_resources,
+	.csc_setup		= vc5_hdmi_csc_setup,
+	.reset			= vc5_hdmi_reset,
+	.set_timings		= vc5_hdmi_set_timings,
+	.phy_init		= vc5_hdmi_phy_init,
+	.phy_disable		= vc5_hdmi_phy_disable,
+	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
+	.channel_map		= vc5_hdmi_channel_map,
+};
+
+static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI1,
+	.debugfs_name		= "hdmi1_regs",
+	.card_name		= "vc4-hdmi-1",
+	.max_pixel_clock	= 297000000,
+	.registers		= vc5_hdmi_hdmi1_fields,
+	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
+	.phy_lane_mapping	= {
+		PHY_LANE_1,
+		PHY_LANE_0,
+		PHY_LANE_CK,
+		PHY_LANE_2,
+	},
+
+	.init_resources		= vc5_hdmi_init_resources,
+	.csc_setup		= vc5_hdmi_csc_setup,
+	.reset			= vc5_hdmi_reset,
+	.set_timings		= vc5_hdmi_set_timings,
+	.phy_init		= vc5_hdmi_phy_init,
+	.phy_disable		= vc5_hdmi_phy_disable,
+	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
+	.channel_map		= vc5_hdmi_channel_map,
+};
+
 static const struct of_device_id vc4_hdmi_dt_match[] = {
 	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
+	{ .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
+	{ .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 34138e0dd4a6..0806c6d9f24e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -26,6 +26,13 @@ struct drm_display_mode;
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
+enum vc4_hdmi_phy_channel {
+	PHY_LANE_0 = 0,
+	PHY_LANE_1,
+	PHY_LANE_2,
+	PHY_LANE_CK,
+};
+
 struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
@@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
 	/* Number of registers on that variant */
 	unsigned int num_registers;
 
+	/* BCM2711 Only.
+	 * The variants don't map the lane in the same order in the
+	 * PHY, so this is an array mapping the HDMI channel (index)
+	 * to the PHY lane (value).
+	 */
+	enum vc4_hdmi_phy_channel phy_lane_mapping[4];
+
 	/* Callback to get the resources (memory region, interrupts,
 	 * clocks, etc) for that variant.
 	 */
@@ -108,6 +122,20 @@ struct vc4_hdmi {
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
 	void __iomem *hd_regs;
+
+	/* VC5 Only */
+	void __iomem *cec_regs;
+	/* VC5 Only */
+	void __iomem *csc_regs;
+	/* VC5 Only */
+	void __iomem *dvp_regs;
+	/* VC5 Only */
+	void __iomem *phy_regs;
+	/* VC5 Only */
+	void __iomem *ram_regs;
+	/* VC5 Only */
+	void __iomem *rm_regs;
+
 	int hpd_gpio;
 	bool hpd_active_low;
 
@@ -120,6 +148,8 @@ struct vc4_hdmi {
 	struct clk *hsm_clock;
 	struct clk *audio_clock;
 
+	struct reset_control *reset;
+
 	struct debugfs_regset32 hdmi_regset;
 	struct debugfs_regset32 hd_regset;
 };
@@ -144,4 +174,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct drm_display_mode *mode);
+void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
+void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 93287e24d7d1..4d36f8c33401 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -10,6 +10,123 @@
 #include "vc4_regs.h"
 #include "vc4_hdmi_regs.h"
 
+#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB	BIT(5)
+#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB	BIT(4)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET	BIT(3)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET	BIT(2)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET	BIT(1)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET	BIT(0)
+
+#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN	BIT(4)
+
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT	29
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK	VC4_MASK(31, 29)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT	24
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK	VC4_MASK(28, 24)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT	21
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK	VC4_MASK(23, 21)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT	16
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK	VC4_MASK(20, 16)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT	13
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK	VC4_MASK(15, 13)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT	8
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK	VC4_MASK(12, 8)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT	5
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK	VC4_MASK(7, 5)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT	0
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK	VC4_MASK(4, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT	15
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK	VC4_MASK(19, 15)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT	10
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK	VC4_MASK(14, 10)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT	5
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK	VC4_MASK(9, 5)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT		0
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK		VC4_MASK(4, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT		16
+#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK		VC4_MASK(19, 16)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT	12
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK	VC4_MASK(15, 12)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT	8
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK	VC4_MASK(11, 8)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT	4
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK	VC4_MASK(7, 4)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT	0
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK	VC4_MASK(3, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT			17
+#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK			VC4_MASK(19, 17)
+#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT			12
+#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK			VC4_MASK(16, 12)
+#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT			10
+#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK			VC4_MASK(11, 10)
+#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT			8
+#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK			VC4_MASK(9, 8)
+#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT			6
+#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK			VC4_MASK(7, 6)
+#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT			0
+#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK			VC4_MASK(5, 0)
+
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE		BIT(13)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN		BIT(12)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW	BIT(11)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH	BIT(10)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT		9
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK		VC4_MASK(9, 9)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2		BIT(8)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2		BIT(7)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN		BIT(6)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK		BIT(5)
+
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT			16
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK			VC4_MASK(27, 16)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT	14
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK	VC4_MASK(15, 14)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE		BIT(13)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT		11
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK		VC4_MASK(12, 11)
+
+#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT		8
+#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK		VC4_MASK(15, 8)
+
+#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT		0
+#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK		VC4_MASK(3, 0)
+
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK	VC4_MASK(13, 12)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT	12
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK	VC4_MASK(9, 8)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT	8
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK	VC4_MASK(5, 4)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT	4
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK	VC4_MASK(1, 0)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK		VC4_MASK(27, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK		VC4_MASK(27, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK	VC4_MASK(31, 16)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT	16
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK	VC4_MASK(15, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT	0
+
+#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS		BIT(19)
+#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR		BIT(17)
+#define VC4_HDMI_RM_CONTROL_FREE_RUN			BIT(4)
+
+#define VC4_HDMI_RM_OFFSET_ONLY				BIT(31)
+#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT			0
+#define VC4_HDMI_RM_OFFSET_OFFSET_MASK			VC4_MASK(30, 0)
+
+#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT			24
+#define VC4_HDMI_RM_FORMAT_SHIFT_MASK			VC4_MASK(25, 24)
+
+#define OSCILLATOR_FREQUENCY	54000000
+
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
 {
 	/* PHY should be in reset, like
@@ -38,3 +155,366 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
 		   HDMI_READ(HDMI_TX_PHY_CTL_0) |
 		   VC4_HDMI_TX_PHY_RNG_PWRDN);
 }
+
+static unsigned long long
+phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
+{
+	unsigned long long vco_freq = clock;
+	unsigned int _vco_div = 0;
+	unsigned int _vco_sel = 0;
+
+	while (vco_freq < 3000000000ULL) {
+		_vco_div++;
+		vco_freq = clock * _vco_div * 10;
+	}
+
+	if (vco_freq > 4500000000ULL)
+		_vco_sel = 1;
+
+	*vco_sel = _vco_sel;
+	*vco_div = _vco_div;
+
+	return vco_freq;
+}
+
+static u8 phy_get_cp_current(unsigned long vco_freq)
+{
+	if (vco_freq < 3700000000ULL)
+		return 0x1c;
+
+	return 0x18;
+}
+
+static u32 phy_get_rm_offset(unsigned long long vco_freq)
+{
+	unsigned long long fref = OSCILLATOR_FREQUENCY;
+	u64 offset = 0;
+
+	/* RM offset is stored as 9.22 format */
+	offset = vco_freq * 2;
+	offset = offset << 22;
+	do_div(offset, fref);
+	offset >>= 2;
+
+	return offset;
+}
+
+static u8 phy_get_vco_gain(unsigned long long vco_freq)
+{
+	if (vco_freq < 3350000000ULL)
+		return 0xf;
+
+	if (vco_freq < 3700000000ULL)
+		return 0xc;
+
+	if (vco_freq < 4050000000ULL)
+		return 0x6;
+
+	if (vco_freq < 4800000000ULL)
+		return 0x5;
+
+	if (vco_freq < 5200000000ULL)
+		return 0x7;
+
+	return 0x2;
+}
+
+struct phy_lane_settings {
+	struct {
+		u8 preemphasis;
+		u8 main_driver;
+	} amplitude;
+
+	u8 res_sel_data;
+	u8 term_res_sel_data;
+};
+
+struct phy_settings {
+	unsigned long long min_rate;
+	unsigned long long max_rate;
+	struct phy_lane_settings channel[3];
+	struct phy_lane_settings clock;
+};
+
+static const struct phy_settings vc5_hdmi_phy_settings[] = {
+	{
+		0, 50000000,
+		{
+			{{0x0, 0x0A}, 0x12, 0x0},
+			{{0x0, 0x0A}, 0x12, 0x0},
+			{{0x0, 0x0A}, 0x12, 0x0}
+		},
+		{{0x0, 0x0A}, 0x18, 0x0},
+	},
+	{
+		50000001, 75000000,
+		{
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		75000001,   165000000,
+		{
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		165000001,  250000000,
+		{
+			{{0x0, 0x0F}, 0x12, 0x1},
+			{{0x0, 0x0F}, 0x12, 0x1},
+			{{0x0, 0x0F}, 0x12, 0x1}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		250000001,  340000000,
+		{
+			{{0x2, 0x0D}, 0x12, 0x1},
+			{{0x2, 0x0D}, 0x12, 0x1},
+			{{0x2, 0x0D}, 0x12, 0x1}
+		},
+		{{0x0, 0x0C}, 0x18, 0xF},
+	},
+	{
+		340000001,  450000000,
+		{
+			{{0x0, 0x1B}, 0x12, 0xF},
+			{{0x0, 0x1B}, 0x12, 0xF},
+			{{0x0, 0x1B}, 0x12, 0xF}
+		},
+		{{0x0, 0x0A}, 0x12, 0xF},
+	},
+	{
+		450000001,  600000000,
+		{
+			{{0x0, 0x1C}, 0x12, 0xF},
+			{{0x0, 0x1C}, 0x12, 0xF},
+			{{0x0, 0x1C}, 0x12, 0xF}
+		},
+		{{0x0, 0x0B}, 0x13, 0xF},
+	},
+};
+
+static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
+{
+	unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
+
+		if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
+			return s;
+	}
+
+	/*
+	 * If the pixel clock exceeds our max setting, try the max
+	 * setting anyway.
+	 */
+	return &vc5_hdmi_phy_settings[count - 1];
+}
+
+static const struct phy_lane_settings *
+phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
+			 unsigned long long tmds_rate)
+{
+	const struct phy_settings *settings = phy_get_settings(tmds_rate);
+
+	if (chan == PHY_LANE_CK)
+		return &settings->clock;
+
+	return &settings->channel[chan];
+}
+
+static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
+}
+
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
+	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+	unsigned long long pixel_freq = mode->clock * 1000;
+	unsigned long long vco_freq;
+	unsigned char word_sel;
+	u8 vco_sel, vco_div;
+
+	vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
+
+	vc5_hdmi_reset_phy(vc4_hdmi);
+
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
+
+	HDMI_WRITE(HDMI_RM_CONTROL,
+		   HDMI_READ(HDMI_RM_CONTROL) |
+		   VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
+		   VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
+		   VC4_HDMI_RM_CONTROL_FREE_RUN);
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
+		   (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
+		    ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
+		   VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
+		   (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
+		    ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
+		   VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
+
+	HDMI_WRITE(HDMI_RM_OFFSET,
+		   VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
+				 VC4_HDMI_RM_OFFSET_OFFSET) |
+		   VC4_HDMI_RM_OFFSET_ONLY);
+
+	HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
+		   VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
+		   VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
+		   VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
+		   VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
+		   HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
+		   VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
+		   VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
+		   VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
+
+	HDMI_WRITE(HDMI_RM_FORMAT,
+		   HDMI_READ(HDMI_RM_FORMAT) |
+		   VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
+		   HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
+
+	if (pixel_freq >= 340000000)
+		word_sel = 3;
+	else
+		word_sel = 0;
+	HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_3,
+		   VC4_SET_FIELD(phy_get_cp_current(vco_freq),
+				 VC4_HDMI_TX_PHY_CTL_3_ICP) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
+		   VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
+		   VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
+		   VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
+
+	chan0_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
+					 pixel_freq);
+	chan1_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
+					 pixel_freq);
+	chan2_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
+					 pixel_freq);
+	clock_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
+					 pixel_freq);
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
+		   VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
+		   VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
+		   VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
+		   VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
+		   VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
+		   VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
+		   VC4_SET_FIELD(clock_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_1,
+		   HDMI_READ(HDMI_TX_PHY_CTL_1) |
+		   VC4_SET_FIELD(chan0_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
+		   VC4_SET_FIELD(chan1_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
+		   VC4_SET_FIELD(chan2_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
+		   VC4_SET_FIELD(clock_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_2,
+		   VC4_SET_FIELD(chan0_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
+		   VC4_SET_FIELD(chan1_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
+		   VC4_SET_FIELD(chan2_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
+		   VC4_SET_FIELD(clock_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
+		   VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
+				 VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
+
+	HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
+		   ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
+		     VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
+		   VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
+		   VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
+}
+
+void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) {
+	vc5_hdmi_reset_phy(vc4_hdmi);
+}
+
+void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
+		   ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+}
+
+void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
+		   VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
index bc47cc9bc883..a5f1354e3e06 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
 	VC4_INVALID = 0,
 	VC4_HDMI,
 	VC4_HD,
+	VC5_CEC,
+	VC5_CSC,
+	VC5_DVP,
+	VC5_PHY,
+	VC5_RAM,
+	VC5_RM,
 };
 
 enum vc4_hdmi_field {
@@ -36,6 +42,7 @@ enum vc4_hdmi_field {
 	HDMI_CEC_TX_DATA_2,
 	HDMI_CEC_TX_DATA_3,
 	HDMI_CEC_TX_DATA_4,
+	HDMI_CLOCK_STOP,
 	HDMI_CORE_REV,
 	HDMI_CRP_CFG,
 	HDMI_CSC_12_11,
@@ -52,6 +59,7 @@ enum vc4_hdmi_field {
 	 */
 	HDMI_CTS_0,
 	HDMI_CTS_1,
+	HDMI_DVP_CTL,
 	HDMI_FIFO_CTL,
 	HDMI_FRAME_COUNT,
 	HDMI_HORZA,
@@ -84,10 +92,27 @@ enum vc4_hdmi_field {
 	HDMI_RAM_PACKET_CONFIG,
 	HDMI_RAM_PACKET_START,
 	HDMI_RAM_PACKET_STATUS,
+	HDMI_RM_CONTROL,
+	HDMI_RM_FORMAT,
+	HDMI_RM_OFFSET,
 	HDMI_SCHEDULER_CONTROL,
 	HDMI_SW_RESET_CONTROL,
+	HDMI_TX_PHY_CHANNEL_SWAP,
+	HDMI_TX_PHY_CLK_DIV,
 	HDMI_TX_PHY_CTL_0,
+	HDMI_TX_PHY_CTL_1,
+	HDMI_TX_PHY_CTL_2,
+	HDMI_TX_PHY_CTL_3,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
+	HDMI_TX_PHY_PLL_CFG,
+	HDMI_TX_PHY_PLL_CTL_0,
+	HDMI_TX_PHY_PLL_CTL_1,
+	HDMI_TX_PHY_POWERDOWN_CTL,
 	HDMI_TX_PHY_RESET_CTL,
+	HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
+	HDMI_VEC_INTERFACE_XBAR,
 	HDMI_VERTA0,
 	HDMI_VERTA1,
 	HDMI_VERTB0,
@@ -110,6 +135,12 @@ struct vc4_hdmi_register {
 
 #define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
 #define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
+#define VC5_CEC_REG(reg, offset)	_VC4_REG(VC5_CEC, reg, offset)
+#define VC5_CSC_REG(reg, offset)	_VC4_REG(VC5_CSC, reg, offset)
+#define VC5_DVP_REG(reg, offset)	_VC4_REG(VC5_DVP, reg, offset)
+#define VC5_PHY_REG(reg, offset)	_VC4_REG(VC5_PHY, reg, offset)
+#define VC5_RAM_REG(reg, offset)	_VC4_REG(VC5_RAM, reg, offset)
+#define VC5_RM_REG(reg, offset)		_VC4_REG(VC5_RM, reg, offset)
 
 static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
 	VC4_HD_REG(HDMI_M_CTL, 0x000c),
@@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
 	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
 };
 
+static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
+	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0014),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0044),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),
+
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
+
+	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
+	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
+
+	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
+	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
+	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
+	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
+	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
+
+	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
+	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
+	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
+
+	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
+
+	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
+
+	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
+	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
+	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
+	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
+	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
+	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
+	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
+};
+
+static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
+	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0034),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0048),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),
+
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
+
+	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
+	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
+
+	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
+	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
+	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
+	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
+	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
+
+	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
+	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
+	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
+
+	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
+
+	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
+
+	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
+	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
+	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
+	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
+	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
+	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
+	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
+};
+
 static inline
 void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
 					enum vc4_hdmi_regs reg)
@@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
 	case VC4_HDMI:
 		return hdmi->hdmicore_regs;
 
+	case VC5_CSC:
+		return hdmi->csc_regs;
+
+	case VC5_CEC:
+		return hdmi->cec_regs;
+
+	case VC5_DVP:
+		return hdmi->dvp_regs;
+
+	case VC5_PHY:
+		return hdmi->phy_regs;
+
+	case VC5_RAM:
+		return hdmi->ram_regs;
+
+	case VC5_RM:
+		return hdmi->rm_regs;
+
 	default:
 		return NULL;
 	}
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 30af52b406f1..be2c32a519b3 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -744,6 +744,8 @@
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
 
+# define VC4_DVP_HT_CLOCK_STOP_PIXEL		BIT(1)
+
 /* HVS display list information. */
 #define HVS_BOOTLOADER_DLIST_END                32
 
-- 
git-series 0.9.1

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

* [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that the driver is ready for it, let's bring in the HDMI controllers
variants for the BCM2711.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 278 +++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  36 ++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c  | 480 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h      |   2 +-
 5 files changed, 997 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 37463b016b47..d5ba0b1b73a9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -43,6 +43,7 @@
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/rational.h>
+#include <linux/reset.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm_drm_eld.h>
 #include <sound/pcm_params.h>
@@ -53,6 +54,31 @@
 #include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
+#define VC5_HDMI_HORZA_HFP_SHIFT		16
+#define VC5_HDMI_HORZA_HFP_MASK			VC4_MASK(28, 16)
+#define VC5_HDMI_HORZA_VPOS			BIT(15)
+#define VC5_HDMI_HORZA_HPOS			BIT(14)
+#define VC5_HDMI_HORZA_HAP_SHIFT		0
+#define VC5_HDMI_HORZA_HAP_MASK			VC4_MASK(13, 0)
+
+#define VC5_HDMI_HORZB_HBP_SHIFT		16
+#define VC5_HDMI_HORZB_HBP_MASK			VC4_MASK(26, 16)
+#define VC5_HDMI_HORZB_HSP_SHIFT		0
+#define VC5_HDMI_HORZB_HSP_MASK			VC4_MASK(10, 0)
+
+#define VC5_HDMI_VERTA_VSP_SHIFT		24
+#define VC5_HDMI_VERTA_VSP_MASK			VC4_MASK(28, 24)
+#define VC5_HDMI_VERTA_VFP_SHIFT		16
+#define VC5_HDMI_VERTA_VFP_MASK			VC4_MASK(22, 16)
+#define VC5_HDMI_VERTA_VAL_SHIFT		0
+#define VC5_HDMI_VERTA_VAL_MASK			VC4_MASK(12, 0)
+
+#define VC5_HDMI_VERTB_VSPO_SHIFT		16
+#define VC5_HDMI_VERTB_VSPO_MASK		VC4_MASK(29, 16)
+
+# define VC4_HD_M_SW_RST			BIT(2)
+# define VC4_HD_M_ENABLE			BIT(0)
+
 #define CEC_CLOCK_FREQ 40000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
@@ -82,6 +108,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
 	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 }
 
+static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
+{
+	reset_control_reset(vc4_hdmi->reset);
+
+	HDMI_WRITE(HDMI_DVP_CTL, 0);
+
+	HDMI_WRITE(HDMI_CLOCK_STOP,
+		   HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -391,6 +427,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 }
 
+static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
+{
+	u32 csc_ctl;
+
+	csc_ctl = 0x07;	/* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
+
+	if (enable) {
+		/* CEA VICs other than #1 requre limited range RGB
+		 * output unless overridden by an AVI infoframe.
+		 * Apply a colorspace conversion to squash 0-255 down
+		 * to 16-235.  The matrix here is:
+		 *
+		 * [ 0.8594 0      0      16]
+		 * [ 0      0.8594 0      16]
+		 * [ 0      0      0.8594 16]
+		 * [ 0      0      0       1]
+		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+		 */
+		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
+	} else {
+		/* Still use the matrix for full range, but make it unity.
+		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+		 */
+		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
+	}
+
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
+}
+
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 				 struct drm_display_mode *mode)
 {
@@ -435,6 +510,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 }
+static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_display_mode *mode)
+{
+	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
+	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
+	u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
+				   VC5_HDMI_VERTA_VSP) |
+		     VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
+				   VC5_HDMI_VERTA_VFP) |
+		     VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
+	u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
+		     VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
+				   VC4_HDMI_VERTB_VBP));
+	u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
+			  VC4_SET_FIELD(mode->crtc_vtotal -
+					mode->crtc_vsync_end -
+					interlaced,
+					VC4_HDMI_VERTB_VBP));
+
+	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
+	HDMI_WRITE(HDMI_HORZA,
+		   (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
+		   (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+				 VC5_HDMI_HORZA_HAP) |
+		   VC4_SET_FIELD((mode->hsync_start -
+				  mode->hdisplay) * pixel_rep,
+				 VC5_HDMI_HORZA_HFP));
+
+	HDMI_WRITE(HDMI_HORZB,
+		   VC4_SET_FIELD((mode->htotal -
+				  mode->hsync_end) * pixel_rep,
+				 VC5_HDMI_HORZB_HBP) |
+		   VC4_SET_FIELD((mode->hsync_end -
+				  mode->hsync_start) * pixel_rep,
+				 VC5_HDMI_HORZB_HSP));
+
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
+
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
+
+	HDMI_WRITE(HDMI_CLOCK_STOP, 0);
+}
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 {
@@ -645,6 +767,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
 	return channel_map;
 }
 
+static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
+{
+	int i;
+	u32 channel_map = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (channel_mask & BIT(i))
+			channel_map |= i << (4 * i);
+	}
+	return channel_map;
+}
+
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
@@ -1377,6 +1511,98 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 	return 0;
 }
 
+static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
+{
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
+					       resource_size(res));
+	if (IS_ERR(vc4_hdmi->hdmicore_regs))
+		return PTR_ERR(vc4_hdmi->hdmicore_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->hd_regs))
+		return PTR_ERR(vc4_hdmi->hd_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->cec_regs))
+		return PTR_ERR(vc4_hdmi->cec_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->csc_regs))
+		return PTR_ERR(vc4_hdmi->csc_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->dvp_regs))
+		return PTR_ERR(vc4_hdmi->dvp_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->phy_regs))
+		return PTR_ERR(vc4_hdmi->phy_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->ram_regs))
+		return PTR_ERR(vc4_hdmi->ram_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->rm_regs))
+		return PTR_ERR(vc4_hdmi->rm_regs);
+
+	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+	if (IS_ERR(vc4_hdmi->hsm_clock)) {
+		DRM_ERROR("Failed to get HDMI state machine clock\n");
+		return PTR_ERR(vc4_hdmi->hsm_clock);
+	}
+
+	vc4_hdmi->audio_clock = devm_clk_get(dev, "clk-108M");
+	if (IS_ERR(vc4_hdmi->audio_clock)) {
+		DRM_ERROR("Failed to get 108MHz clock\n");
+		return PTR_ERR(vc4_hdmi->audio_clock);
+	}
+
+	vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(vc4_hdmi->reset)) {
+		DRM_ERROR("Failed to get HDMI reset line\n");
+		return PTR_ERR(vc4_hdmi->reset);
+	}
+
+	return 0;
+}
+
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
 	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -1547,8 +1773,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.channel_map		= vc4_hdmi_channel_map,
 };
 
+static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
+	.debugfs_name		= "hdmi0_regs",
+	.card_name		= "vc4-hdmi-0",
+	.max_pixel_clock	= 297000000,
+	.registers		= vc5_hdmi_hdmi0_fields,
+	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
+	.phy_lane_mapping	= {
+		PHY_LANE_0,
+		PHY_LANE_1,
+		PHY_LANE_2,
+		PHY_LANE_CK,
+	},
+
+	.init_resources		= vc5_hdmi_init_resources,
+	.csc_setup		= vc5_hdmi_csc_setup,
+	.reset			= vc5_hdmi_reset,
+	.set_timings		= vc5_hdmi_set_timings,
+	.phy_init		= vc5_hdmi_phy_init,
+	.phy_disable		= vc5_hdmi_phy_disable,
+	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
+	.channel_map		= vc5_hdmi_channel_map,
+};
+
+static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI1,
+	.debugfs_name		= "hdmi1_regs",
+	.card_name		= "vc4-hdmi-1",
+	.max_pixel_clock	= 297000000,
+	.registers		= vc5_hdmi_hdmi1_fields,
+	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
+	.phy_lane_mapping	= {
+		PHY_LANE_1,
+		PHY_LANE_0,
+		PHY_LANE_CK,
+		PHY_LANE_2,
+	},
+
+	.init_resources		= vc5_hdmi_init_resources,
+	.csc_setup		= vc5_hdmi_csc_setup,
+	.reset			= vc5_hdmi_reset,
+	.set_timings		= vc5_hdmi_set_timings,
+	.phy_init		= vc5_hdmi_phy_init,
+	.phy_disable		= vc5_hdmi_phy_disable,
+	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
+	.channel_map		= vc5_hdmi_channel_map,
+};
+
 static const struct of_device_id vc4_hdmi_dt_match[] = {
 	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
+	{ .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
+	{ .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 34138e0dd4a6..0806c6d9f24e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -26,6 +26,13 @@ struct drm_display_mode;
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
+enum vc4_hdmi_phy_channel {
+	PHY_LANE_0 = 0,
+	PHY_LANE_1,
+	PHY_LANE_2,
+	PHY_LANE_CK,
+};
+
 struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
@@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
 	/* Number of registers on that variant */
 	unsigned int num_registers;
 
+	/* BCM2711 Only.
+	 * The variants don't map the lane in the same order in the
+	 * PHY, so this is an array mapping the HDMI channel (index)
+	 * to the PHY lane (value).
+	 */
+	enum vc4_hdmi_phy_channel phy_lane_mapping[4];
+
 	/* Callback to get the resources (memory region, interrupts,
 	 * clocks, etc) for that variant.
 	 */
@@ -108,6 +122,20 @@ struct vc4_hdmi {
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
 	void __iomem *hd_regs;
+
+	/* VC5 Only */
+	void __iomem *cec_regs;
+	/* VC5 Only */
+	void __iomem *csc_regs;
+	/* VC5 Only */
+	void __iomem *dvp_regs;
+	/* VC5 Only */
+	void __iomem *phy_regs;
+	/* VC5 Only */
+	void __iomem *ram_regs;
+	/* VC5 Only */
+	void __iomem *rm_regs;
+
 	int hpd_gpio;
 	bool hpd_active_low;
 
@@ -120,6 +148,8 @@ struct vc4_hdmi {
 	struct clk *hsm_clock;
 	struct clk *audio_clock;
 
+	struct reset_control *reset;
+
 	struct debugfs_regset32 hdmi_regset;
 	struct debugfs_regset32 hd_regset;
 };
@@ -144,4 +174,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct drm_display_mode *mode);
+void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
+void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 93287e24d7d1..4d36f8c33401 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -10,6 +10,123 @@
 #include "vc4_regs.h"
 #include "vc4_hdmi_regs.h"
 
+#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB	BIT(5)
+#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB	BIT(4)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET	BIT(3)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET	BIT(2)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET	BIT(1)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET	BIT(0)
+
+#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN	BIT(4)
+
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT	29
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK	VC4_MASK(31, 29)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT	24
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK	VC4_MASK(28, 24)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT	21
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK	VC4_MASK(23, 21)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT	16
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK	VC4_MASK(20, 16)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT	13
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK	VC4_MASK(15, 13)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT	8
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK	VC4_MASK(12, 8)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT	5
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK	VC4_MASK(7, 5)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT	0
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK	VC4_MASK(4, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT	15
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK	VC4_MASK(19, 15)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT	10
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK	VC4_MASK(14, 10)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT	5
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK	VC4_MASK(9, 5)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT		0
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK		VC4_MASK(4, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT		16
+#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK		VC4_MASK(19, 16)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT	12
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK	VC4_MASK(15, 12)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT	8
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK	VC4_MASK(11, 8)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT	4
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK	VC4_MASK(7, 4)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT	0
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK	VC4_MASK(3, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT			17
+#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK			VC4_MASK(19, 17)
+#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT			12
+#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK			VC4_MASK(16, 12)
+#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT			10
+#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK			VC4_MASK(11, 10)
+#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT			8
+#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK			VC4_MASK(9, 8)
+#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT			6
+#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK			VC4_MASK(7, 6)
+#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT			0
+#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK			VC4_MASK(5, 0)
+
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE		BIT(13)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN		BIT(12)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW	BIT(11)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH	BIT(10)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT		9
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK		VC4_MASK(9, 9)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2		BIT(8)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2		BIT(7)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN		BIT(6)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK		BIT(5)
+
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT			16
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK			VC4_MASK(27, 16)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT	14
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK	VC4_MASK(15, 14)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE		BIT(13)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT		11
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK		VC4_MASK(12, 11)
+
+#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT		8
+#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK		VC4_MASK(15, 8)
+
+#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT		0
+#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK		VC4_MASK(3, 0)
+
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK	VC4_MASK(13, 12)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT	12
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK	VC4_MASK(9, 8)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT	8
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK	VC4_MASK(5, 4)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT	4
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK	VC4_MASK(1, 0)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK		VC4_MASK(27, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK		VC4_MASK(27, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK	VC4_MASK(31, 16)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT	16
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK	VC4_MASK(15, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT	0
+
+#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS		BIT(19)
+#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR		BIT(17)
+#define VC4_HDMI_RM_CONTROL_FREE_RUN			BIT(4)
+
+#define VC4_HDMI_RM_OFFSET_ONLY				BIT(31)
+#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT			0
+#define VC4_HDMI_RM_OFFSET_OFFSET_MASK			VC4_MASK(30, 0)
+
+#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT			24
+#define VC4_HDMI_RM_FORMAT_SHIFT_MASK			VC4_MASK(25, 24)
+
+#define OSCILLATOR_FREQUENCY	54000000
+
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
 {
 	/* PHY should be in reset, like
@@ -38,3 +155,366 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
 		   HDMI_READ(HDMI_TX_PHY_CTL_0) |
 		   VC4_HDMI_TX_PHY_RNG_PWRDN);
 }
+
+static unsigned long long
+phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
+{
+	unsigned long long vco_freq = clock;
+	unsigned int _vco_div = 0;
+	unsigned int _vco_sel = 0;
+
+	while (vco_freq < 3000000000ULL) {
+		_vco_div++;
+		vco_freq = clock * _vco_div * 10;
+	}
+
+	if (vco_freq > 4500000000ULL)
+		_vco_sel = 1;
+
+	*vco_sel = _vco_sel;
+	*vco_div = _vco_div;
+
+	return vco_freq;
+}
+
+static u8 phy_get_cp_current(unsigned long vco_freq)
+{
+	if (vco_freq < 3700000000ULL)
+		return 0x1c;
+
+	return 0x18;
+}
+
+static u32 phy_get_rm_offset(unsigned long long vco_freq)
+{
+	unsigned long long fref = OSCILLATOR_FREQUENCY;
+	u64 offset = 0;
+
+	/* RM offset is stored as 9.22 format */
+	offset = vco_freq * 2;
+	offset = offset << 22;
+	do_div(offset, fref);
+	offset >>= 2;
+
+	return offset;
+}
+
+static u8 phy_get_vco_gain(unsigned long long vco_freq)
+{
+	if (vco_freq < 3350000000ULL)
+		return 0xf;
+
+	if (vco_freq < 3700000000ULL)
+		return 0xc;
+
+	if (vco_freq < 4050000000ULL)
+		return 0x6;
+
+	if (vco_freq < 4800000000ULL)
+		return 0x5;
+
+	if (vco_freq < 5200000000ULL)
+		return 0x7;
+
+	return 0x2;
+}
+
+struct phy_lane_settings {
+	struct {
+		u8 preemphasis;
+		u8 main_driver;
+	} amplitude;
+
+	u8 res_sel_data;
+	u8 term_res_sel_data;
+};
+
+struct phy_settings {
+	unsigned long long min_rate;
+	unsigned long long max_rate;
+	struct phy_lane_settings channel[3];
+	struct phy_lane_settings clock;
+};
+
+static const struct phy_settings vc5_hdmi_phy_settings[] = {
+	{
+		0, 50000000,
+		{
+			{{0x0, 0x0A}, 0x12, 0x0},
+			{{0x0, 0x0A}, 0x12, 0x0},
+			{{0x0, 0x0A}, 0x12, 0x0}
+		},
+		{{0x0, 0x0A}, 0x18, 0x0},
+	},
+	{
+		50000001, 75000000,
+		{
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		75000001,   165000000,
+		{
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		165000001,  250000000,
+		{
+			{{0x0, 0x0F}, 0x12, 0x1},
+			{{0x0, 0x0F}, 0x12, 0x1},
+			{{0x0, 0x0F}, 0x12, 0x1}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		250000001,  340000000,
+		{
+			{{0x2, 0x0D}, 0x12, 0x1},
+			{{0x2, 0x0D}, 0x12, 0x1},
+			{{0x2, 0x0D}, 0x12, 0x1}
+		},
+		{{0x0, 0x0C}, 0x18, 0xF},
+	},
+	{
+		340000001,  450000000,
+		{
+			{{0x0, 0x1B}, 0x12, 0xF},
+			{{0x0, 0x1B}, 0x12, 0xF},
+			{{0x0, 0x1B}, 0x12, 0xF}
+		},
+		{{0x0, 0x0A}, 0x12, 0xF},
+	},
+	{
+		450000001,  600000000,
+		{
+			{{0x0, 0x1C}, 0x12, 0xF},
+			{{0x0, 0x1C}, 0x12, 0xF},
+			{{0x0, 0x1C}, 0x12, 0xF}
+		},
+		{{0x0, 0x0B}, 0x13, 0xF},
+	},
+};
+
+static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
+{
+	unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
+
+		if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
+			return s;
+	}
+
+	/*
+	 * If the pixel clock exceeds our max setting, try the max
+	 * setting anyway.
+	 */
+	return &vc5_hdmi_phy_settings[count - 1];
+}
+
+static const struct phy_lane_settings *
+phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
+			 unsigned long long tmds_rate)
+{
+	const struct phy_settings *settings = phy_get_settings(tmds_rate);
+
+	if (chan == PHY_LANE_CK)
+		return &settings->clock;
+
+	return &settings->channel[chan];
+}
+
+static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
+}
+
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
+	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+	unsigned long long pixel_freq = mode->clock * 1000;
+	unsigned long long vco_freq;
+	unsigned char word_sel;
+	u8 vco_sel, vco_div;
+
+	vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
+
+	vc5_hdmi_reset_phy(vc4_hdmi);
+
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
+
+	HDMI_WRITE(HDMI_RM_CONTROL,
+		   HDMI_READ(HDMI_RM_CONTROL) |
+		   VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
+		   VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
+		   VC4_HDMI_RM_CONTROL_FREE_RUN);
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
+		   (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
+		    ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
+		   VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
+		   (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
+		    ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
+		   VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
+
+	HDMI_WRITE(HDMI_RM_OFFSET,
+		   VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
+				 VC4_HDMI_RM_OFFSET_OFFSET) |
+		   VC4_HDMI_RM_OFFSET_ONLY);
+
+	HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
+		   VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
+		   VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
+		   VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
+		   VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
+		   HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
+		   VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
+		   VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
+		   VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
+
+	HDMI_WRITE(HDMI_RM_FORMAT,
+		   HDMI_READ(HDMI_RM_FORMAT) |
+		   VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
+		   HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
+
+	if (pixel_freq >= 340000000)
+		word_sel = 3;
+	else
+		word_sel = 0;
+	HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_3,
+		   VC4_SET_FIELD(phy_get_cp_current(vco_freq),
+				 VC4_HDMI_TX_PHY_CTL_3_ICP) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
+		   VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
+		   VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
+		   VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
+
+	chan0_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
+					 pixel_freq);
+	chan1_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
+					 pixel_freq);
+	chan2_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
+					 pixel_freq);
+	clock_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
+					 pixel_freq);
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
+		   VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
+		   VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
+		   VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
+		   VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
+		   VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
+		   VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
+		   VC4_SET_FIELD(clock_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_1,
+		   HDMI_READ(HDMI_TX_PHY_CTL_1) |
+		   VC4_SET_FIELD(chan0_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
+		   VC4_SET_FIELD(chan1_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
+		   VC4_SET_FIELD(chan2_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
+		   VC4_SET_FIELD(clock_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_2,
+		   VC4_SET_FIELD(chan0_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
+		   VC4_SET_FIELD(chan1_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
+		   VC4_SET_FIELD(chan2_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
+		   VC4_SET_FIELD(clock_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
+		   VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
+				 VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
+
+	HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
+		   ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
+		     VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
+		   VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
+		   VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
+}
+
+void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) {
+	vc5_hdmi_reset_phy(vc4_hdmi);
+}
+
+void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
+		   ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+}
+
+void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
+		   VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
index bc47cc9bc883..a5f1354e3e06 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
 	VC4_INVALID = 0,
 	VC4_HDMI,
 	VC4_HD,
+	VC5_CEC,
+	VC5_CSC,
+	VC5_DVP,
+	VC5_PHY,
+	VC5_RAM,
+	VC5_RM,
 };
 
 enum vc4_hdmi_field {
@@ -36,6 +42,7 @@ enum vc4_hdmi_field {
 	HDMI_CEC_TX_DATA_2,
 	HDMI_CEC_TX_DATA_3,
 	HDMI_CEC_TX_DATA_4,
+	HDMI_CLOCK_STOP,
 	HDMI_CORE_REV,
 	HDMI_CRP_CFG,
 	HDMI_CSC_12_11,
@@ -52,6 +59,7 @@ enum vc4_hdmi_field {
 	 */
 	HDMI_CTS_0,
 	HDMI_CTS_1,
+	HDMI_DVP_CTL,
 	HDMI_FIFO_CTL,
 	HDMI_FRAME_COUNT,
 	HDMI_HORZA,
@@ -84,10 +92,27 @@ enum vc4_hdmi_field {
 	HDMI_RAM_PACKET_CONFIG,
 	HDMI_RAM_PACKET_START,
 	HDMI_RAM_PACKET_STATUS,
+	HDMI_RM_CONTROL,
+	HDMI_RM_FORMAT,
+	HDMI_RM_OFFSET,
 	HDMI_SCHEDULER_CONTROL,
 	HDMI_SW_RESET_CONTROL,
+	HDMI_TX_PHY_CHANNEL_SWAP,
+	HDMI_TX_PHY_CLK_DIV,
 	HDMI_TX_PHY_CTL_0,
+	HDMI_TX_PHY_CTL_1,
+	HDMI_TX_PHY_CTL_2,
+	HDMI_TX_PHY_CTL_3,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
+	HDMI_TX_PHY_PLL_CFG,
+	HDMI_TX_PHY_PLL_CTL_0,
+	HDMI_TX_PHY_PLL_CTL_1,
+	HDMI_TX_PHY_POWERDOWN_CTL,
 	HDMI_TX_PHY_RESET_CTL,
+	HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
+	HDMI_VEC_INTERFACE_XBAR,
 	HDMI_VERTA0,
 	HDMI_VERTA1,
 	HDMI_VERTB0,
@@ -110,6 +135,12 @@ struct vc4_hdmi_register {
 
 #define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
 #define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
+#define VC5_CEC_REG(reg, offset)	_VC4_REG(VC5_CEC, reg, offset)
+#define VC5_CSC_REG(reg, offset)	_VC4_REG(VC5_CSC, reg, offset)
+#define VC5_DVP_REG(reg, offset)	_VC4_REG(VC5_DVP, reg, offset)
+#define VC5_PHY_REG(reg, offset)	_VC4_REG(VC5_PHY, reg, offset)
+#define VC5_RAM_REG(reg, offset)	_VC4_REG(VC5_RAM, reg, offset)
+#define VC5_RM_REG(reg, offset)		_VC4_REG(VC5_RM, reg, offset)
 
 static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
 	VC4_HD_REG(HDMI_M_CTL, 0x000c),
@@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
 	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
 };
 
+static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
+	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0014),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0044),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),
+
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
+
+	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
+	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
+
+	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
+	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
+	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
+	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
+	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
+
+	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
+	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
+	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
+
+	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
+
+	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
+
+	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
+	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
+	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
+	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
+	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
+	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
+	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
+};
+
+static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
+	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0034),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0048),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),
+
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
+
+	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
+	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
+
+	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
+	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
+	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
+	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
+	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
+
+	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
+	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
+	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
+
+	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
+
+	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
+
+	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
+	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
+	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
+	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
+	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
+	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
+	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
+};
+
 static inline
 void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
 					enum vc4_hdmi_regs reg)
@@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
 	case VC4_HDMI:
 		return hdmi->hdmicore_regs;
 
+	case VC5_CSC:
+		return hdmi->csc_regs;
+
+	case VC5_CEC:
+		return hdmi->cec_regs;
+
+	case VC5_DVP:
+		return hdmi->dvp_regs;
+
+	case VC5_PHY:
+		return hdmi->phy_regs;
+
+	case VC5_RAM:
+		return hdmi->ram_regs;
+
+	case VC5_RM:
+		return hdmi->rm_regs;
+
 	default:
 		return NULL;
 	}
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 30af52b406f1..be2c32a519b3 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -744,6 +744,8 @@
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
 
+# define VC4_DVP_HT_CLOCK_STOP_PIXEL		BIT(1)
+
 /* HVS display list information. */
 #define HVS_BOOTLOADER_DLIST_END                32
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that the driver is ready for it, let's bring in the HDMI controllers
variants for the BCM2711.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_hdmi.c      | 278 +++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi.h      |  36 ++-
 drivers/gpu/drm/vc4/vc4_hdmi_phy.c  | 480 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++-
 drivers/gpu/drm/vc4/vc4_regs.h      |   2 +-
 5 files changed, 997 insertions(+)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 37463b016b47..d5ba0b1b73a9 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -43,6 +43,7 @@
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/rational.h>
+#include <linux/reset.h>
 #include <sound/dmaengine_pcm.h>
 #include <sound/pcm_drm_eld.h>
 #include <sound/pcm_params.h>
@@ -53,6 +54,31 @@
 #include "vc4_hdmi_regs.h"
 #include "vc4_regs.h"
 
+#define VC5_HDMI_HORZA_HFP_SHIFT		16
+#define VC5_HDMI_HORZA_HFP_MASK			VC4_MASK(28, 16)
+#define VC5_HDMI_HORZA_VPOS			BIT(15)
+#define VC5_HDMI_HORZA_HPOS			BIT(14)
+#define VC5_HDMI_HORZA_HAP_SHIFT		0
+#define VC5_HDMI_HORZA_HAP_MASK			VC4_MASK(13, 0)
+
+#define VC5_HDMI_HORZB_HBP_SHIFT		16
+#define VC5_HDMI_HORZB_HBP_MASK			VC4_MASK(26, 16)
+#define VC5_HDMI_HORZB_HSP_SHIFT		0
+#define VC5_HDMI_HORZB_HSP_MASK			VC4_MASK(10, 0)
+
+#define VC5_HDMI_VERTA_VSP_SHIFT		24
+#define VC5_HDMI_VERTA_VSP_MASK			VC4_MASK(28, 24)
+#define VC5_HDMI_VERTA_VFP_SHIFT		16
+#define VC5_HDMI_VERTA_VFP_MASK			VC4_MASK(22, 16)
+#define VC5_HDMI_VERTA_VAL_SHIFT		0
+#define VC5_HDMI_VERTA_VAL_MASK			VC4_MASK(12, 0)
+
+#define VC5_HDMI_VERTB_VSPO_SHIFT		16
+#define VC5_HDMI_VERTB_VSPO_MASK		VC4_MASK(29, 16)
+
+# define VC4_HD_M_SW_RST			BIT(2)
+# define VC4_HD_M_ENABLE			BIT(0)
+
 #define CEC_CLOCK_FREQ 40000
 
 static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
@@ -82,6 +108,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
 	HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 }
 
+static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
+{
+	reset_control_reset(vc4_hdmi->reset);
+
+	HDMI_WRITE(HDMI_DVP_CTL, 0);
+
+	HDMI_WRITE(HDMI_CLOCK_STOP,
+		   HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
+}
+
 static enum drm_connector_status
 vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -391,6 +427,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
 	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 }
 
+static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
+{
+	u32 csc_ctl;
+
+	csc_ctl = 0x07;	/* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
+
+	if (enable) {
+		/* CEA VICs other than #1 requre limited range RGB
+		 * output unless overridden by an AVI infoframe.
+		 * Apply a colorspace conversion to squash 0-255 down
+		 * to 16-235.  The matrix here is:
+		 *
+		 * [ 0.8594 0      0      16]
+		 * [ 0      0.8594 0      16]
+		 * [ 0      0      0.8594 16]
+		 * [ 0      0      0       1]
+		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+		 */
+		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
+	} else {
+		/* Still use the matrix for full range, but make it unity.
+		 * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
+		 */
+		HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
+		HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
+		HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
+	}
+
+	HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
+}
+
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 				 struct drm_display_mode *mode)
 {
@@ -435,6 +510,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
 	HDMI_WRITE(HDMI_VERTB0, vertb_even);
 	HDMI_WRITE(HDMI_VERTB1, vertb);
 }
+static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
+				 struct drm_display_mode *mode)
+{
+	bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
+	bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
+	bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
+	u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
+	u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
+				   VC5_HDMI_VERTA_VSP) |
+		     VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
+				   VC5_HDMI_VERTA_VFP) |
+		     VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
+	u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
+		     VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
+				   VC4_HDMI_VERTB_VBP));
+	u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
+			  VC4_SET_FIELD(mode->crtc_vtotal -
+					mode->crtc_vsync_end -
+					interlaced,
+					VC4_HDMI_VERTB_VBP));
+
+	HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
+	HDMI_WRITE(HDMI_HORZA,
+		   (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
+		   (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
+		   VC4_SET_FIELD(mode->hdisplay * pixel_rep,
+				 VC5_HDMI_HORZA_HAP) |
+		   VC4_SET_FIELD((mode->hsync_start -
+				  mode->hdisplay) * pixel_rep,
+				 VC5_HDMI_HORZA_HFP));
+
+	HDMI_WRITE(HDMI_HORZB,
+		   VC4_SET_FIELD((mode->htotal -
+				  mode->hsync_end) * pixel_rep,
+				 VC5_HDMI_HORZB_HBP) |
+		   VC4_SET_FIELD((mode->hsync_end -
+				  mode->hsync_start) * pixel_rep,
+				 VC5_HDMI_HORZB_HSP));
+
+	HDMI_WRITE(HDMI_VERTA0, verta);
+	HDMI_WRITE(HDMI_VERTA1, verta);
+
+	HDMI_WRITE(HDMI_VERTB0, vertb_even);
+	HDMI_WRITE(HDMI_VERTB1, vertb);
+
+	HDMI_WRITE(HDMI_CLOCK_STOP, 0);
+}
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 {
@@ -645,6 +767,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
 	return channel_map;
 }
 
+static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
+{
+	int i;
+	u32 channel_map = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (channel_mask & BIT(i))
+			channel_map |= i << (4 * i);
+	}
+	return channel_map;
+}
+
 /* HDMI audio codec callbacks */
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
 {
@@ -1377,6 +1511,98 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
 	return 0;
 }
 
+static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
+{
+	struct platform_device *pdev = vc4_hdmi->pdev;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
+					       resource_size(res));
+	if (IS_ERR(vc4_hdmi->hdmicore_regs))
+		return PTR_ERR(vc4_hdmi->hdmicore_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->hd_regs))
+		return PTR_ERR(vc4_hdmi->hd_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->cec_regs))
+		return PTR_ERR(vc4_hdmi->cec_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->csc_regs))
+		return PTR_ERR(vc4_hdmi->csc_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->dvp_regs))
+		return PTR_ERR(vc4_hdmi->dvp_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->phy_regs))
+		return PTR_ERR(vc4_hdmi->phy_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->ram_regs))
+		return PTR_ERR(vc4_hdmi->ram_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
+	if (!res)
+		return -ENODEV;
+
+	vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (IS_ERR(vc4_hdmi->rm_regs))
+		return PTR_ERR(vc4_hdmi->rm_regs);
+
+	vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
+	if (IS_ERR(vc4_hdmi->hsm_clock)) {
+		DRM_ERROR("Failed to get HDMI state machine clock\n");
+		return PTR_ERR(vc4_hdmi->hsm_clock);
+	}
+
+	vc4_hdmi->audio_clock = devm_clk_get(dev, "clk-108M");
+	if (IS_ERR(vc4_hdmi->audio_clock)) {
+		DRM_ERROR("Failed to get 108MHz clock\n");
+		return PTR_ERR(vc4_hdmi->audio_clock);
+	}
+
+	vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(vc4_hdmi->reset)) {
+		DRM_ERROR("Failed to get HDMI reset line\n");
+		return PTR_ERR(vc4_hdmi->reset);
+	}
+
+	return 0;
+}
+
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
 	const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -1547,8 +1773,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
 	.channel_map		= vc4_hdmi_channel_map,
 };
 
+static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
+	.debugfs_name		= "hdmi0_regs",
+	.card_name		= "vc4-hdmi-0",
+	.max_pixel_clock	= 297000000,
+	.registers		= vc5_hdmi_hdmi0_fields,
+	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
+	.phy_lane_mapping	= {
+		PHY_LANE_0,
+		PHY_LANE_1,
+		PHY_LANE_2,
+		PHY_LANE_CK,
+	},
+
+	.init_resources		= vc5_hdmi_init_resources,
+	.csc_setup		= vc5_hdmi_csc_setup,
+	.reset			= vc5_hdmi_reset,
+	.set_timings		= vc5_hdmi_set_timings,
+	.phy_init		= vc5_hdmi_phy_init,
+	.phy_disable		= vc5_hdmi_phy_disable,
+	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
+	.channel_map		= vc5_hdmi_channel_map,
+};
+
+static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
+	.encoder_type		= VC4_ENCODER_TYPE_HDMI1,
+	.debugfs_name		= "hdmi1_regs",
+	.card_name		= "vc4-hdmi-1",
+	.max_pixel_clock	= 297000000,
+	.registers		= vc5_hdmi_hdmi1_fields,
+	.num_registers		= ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
+	.phy_lane_mapping	= {
+		PHY_LANE_1,
+		PHY_LANE_0,
+		PHY_LANE_CK,
+		PHY_LANE_2,
+	},
+
+	.init_resources		= vc5_hdmi_init_resources,
+	.csc_setup		= vc5_hdmi_csc_setup,
+	.reset			= vc5_hdmi_reset,
+	.set_timings		= vc5_hdmi_set_timings,
+	.phy_init		= vc5_hdmi_phy_init,
+	.phy_disable		= vc5_hdmi_phy_disable,
+	.phy_rng_enable		= vc5_hdmi_phy_rng_enable,
+	.phy_rng_disable	= vc5_hdmi_phy_rng_disable,
+	.channel_map		= vc5_hdmi_channel_map,
+};
+
 static const struct of_device_id vc4_hdmi_dt_match[] = {
 	{ .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
+	{ .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
+	{ .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
 	{}
 };
 
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 34138e0dd4a6..0806c6d9f24e 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -26,6 +26,13 @@ struct drm_display_mode;
 struct vc4_hdmi;
 struct vc4_hdmi_register;
 
+enum vc4_hdmi_phy_channel {
+	PHY_LANE_0 = 0,
+	PHY_LANE_1,
+	PHY_LANE_2,
+	PHY_LANE_CK,
+};
+
 struct vc4_hdmi_variant {
 	/* Encoder Type for that controller */
 	enum vc4_encoder_type encoder_type;
@@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
 	/* Number of registers on that variant */
 	unsigned int num_registers;
 
+	/* BCM2711 Only.
+	 * The variants don't map the lane in the same order in the
+	 * PHY, so this is an array mapping the HDMI channel (index)
+	 * to the PHY lane (value).
+	 */
+	enum vc4_hdmi_phy_channel phy_lane_mapping[4];
+
 	/* Callback to get the resources (memory region, interrupts,
 	 * clocks, etc) for that variant.
 	 */
@@ -108,6 +122,20 @@ struct vc4_hdmi {
 	struct i2c_adapter *ddc;
 	void __iomem *hdmicore_regs;
 	void __iomem *hd_regs;
+
+	/* VC5 Only */
+	void __iomem *cec_regs;
+	/* VC5 Only */
+	void __iomem *csc_regs;
+	/* VC5 Only */
+	void __iomem *dvp_regs;
+	/* VC5 Only */
+	void __iomem *phy_regs;
+	/* VC5 Only */
+	void __iomem *ram_regs;
+	/* VC5 Only */
+	void __iomem *rm_regs;
+
 	int hpd_gpio;
 	bool hpd_active_low;
 
@@ -120,6 +148,8 @@ struct vc4_hdmi {
 	struct clk *hsm_clock;
 	struct clk *audio_clock;
 
+	struct reset_control *reset;
+
 	struct debugfs_regset32 hdmi_regset;
 	struct debugfs_regset32 hd_regset;
 };
@@ -144,4 +174,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
 
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
+		       struct drm_display_mode *mode);
+void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
+void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
+void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
+
 #endif /* _VC4_HDMI_H_ */
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
index 93287e24d7d1..4d36f8c33401 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
@@ -10,6 +10,123 @@
 #include "vc4_regs.h"
 #include "vc4_hdmi_regs.h"
 
+#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB	BIT(5)
+#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB	BIT(4)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET	BIT(3)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET	BIT(2)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET	BIT(1)
+#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET	BIT(0)
+
+#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN	BIT(4)
+
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT	29
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK	VC4_MASK(31, 29)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT	24
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK	VC4_MASK(28, 24)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT	21
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK	VC4_MASK(23, 21)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT	16
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK	VC4_MASK(20, 16)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT	13
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK	VC4_MASK(15, 13)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT	8
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK	VC4_MASK(12, 8)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT	5
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK	VC4_MASK(7, 5)
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT	0
+#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK	VC4_MASK(4, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT	15
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK	VC4_MASK(19, 15)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT	10
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK	VC4_MASK(14, 10)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT	5
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK	VC4_MASK(9, 5)
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT		0
+#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK		VC4_MASK(4, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT		16
+#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK		VC4_MASK(19, 16)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT	12
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK	VC4_MASK(15, 12)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT	8
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK	VC4_MASK(11, 8)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT	4
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK	VC4_MASK(7, 4)
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT	0
+#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK	VC4_MASK(3, 0)
+
+#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT			17
+#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK			VC4_MASK(19, 17)
+#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT			12
+#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK			VC4_MASK(16, 12)
+#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT			10
+#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK			VC4_MASK(11, 10)
+#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT			8
+#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK			VC4_MASK(9, 8)
+#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT			6
+#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK			VC4_MASK(7, 6)
+#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT			0
+#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK			VC4_MASK(5, 0)
+
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE		BIT(13)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN		BIT(12)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW	BIT(11)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH	BIT(10)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT		9
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK		VC4_MASK(9, 9)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2		BIT(8)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2		BIT(7)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN		BIT(6)
+#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK		BIT(5)
+
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT			16
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK			VC4_MASK(27, 16)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT	14
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK	VC4_MASK(15, 14)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE		BIT(13)
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT		11
+#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK		VC4_MASK(12, 11)
+
+#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT		8
+#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK		VC4_MASK(15, 8)
+
+#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT		0
+#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK		VC4_MASK(3, 0)
+
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK	VC4_MASK(13, 12)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT	12
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK	VC4_MASK(9, 8)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT	8
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK	VC4_MASK(5, 4)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT	4
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK	VC4_MASK(1, 0)
+#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK		VC4_MASK(27, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK		VC4_MASK(27, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT	0
+
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK	VC4_MASK(31, 16)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT	16
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK	VC4_MASK(15, 0)
+#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT	0
+
+#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS		BIT(19)
+#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR		BIT(17)
+#define VC4_HDMI_RM_CONTROL_FREE_RUN			BIT(4)
+
+#define VC4_HDMI_RM_OFFSET_ONLY				BIT(31)
+#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT			0
+#define VC4_HDMI_RM_OFFSET_OFFSET_MASK			VC4_MASK(30, 0)
+
+#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT			24
+#define VC4_HDMI_RM_FORMAT_SHIFT_MASK			VC4_MASK(25, 24)
+
+#define OSCILLATOR_FREQUENCY	54000000
+
 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
 {
 	/* PHY should be in reset, like
@@ -38,3 +155,366 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
 		   HDMI_READ(HDMI_TX_PHY_CTL_0) |
 		   VC4_HDMI_TX_PHY_RNG_PWRDN);
 }
+
+static unsigned long long
+phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
+{
+	unsigned long long vco_freq = clock;
+	unsigned int _vco_div = 0;
+	unsigned int _vco_sel = 0;
+
+	while (vco_freq < 3000000000ULL) {
+		_vco_div++;
+		vco_freq = clock * _vco_div * 10;
+	}
+
+	if (vco_freq > 4500000000ULL)
+		_vco_sel = 1;
+
+	*vco_sel = _vco_sel;
+	*vco_div = _vco_div;
+
+	return vco_freq;
+}
+
+static u8 phy_get_cp_current(unsigned long vco_freq)
+{
+	if (vco_freq < 3700000000ULL)
+		return 0x1c;
+
+	return 0x18;
+}
+
+static u32 phy_get_rm_offset(unsigned long long vco_freq)
+{
+	unsigned long long fref = OSCILLATOR_FREQUENCY;
+	u64 offset = 0;
+
+	/* RM offset is stored as 9.22 format */
+	offset = vco_freq * 2;
+	offset = offset << 22;
+	do_div(offset, fref);
+	offset >>= 2;
+
+	return offset;
+}
+
+static u8 phy_get_vco_gain(unsigned long long vco_freq)
+{
+	if (vco_freq < 3350000000ULL)
+		return 0xf;
+
+	if (vco_freq < 3700000000ULL)
+		return 0xc;
+
+	if (vco_freq < 4050000000ULL)
+		return 0x6;
+
+	if (vco_freq < 4800000000ULL)
+		return 0x5;
+
+	if (vco_freq < 5200000000ULL)
+		return 0x7;
+
+	return 0x2;
+}
+
+struct phy_lane_settings {
+	struct {
+		u8 preemphasis;
+		u8 main_driver;
+	} amplitude;
+
+	u8 res_sel_data;
+	u8 term_res_sel_data;
+};
+
+struct phy_settings {
+	unsigned long long min_rate;
+	unsigned long long max_rate;
+	struct phy_lane_settings channel[3];
+	struct phy_lane_settings clock;
+};
+
+static const struct phy_settings vc5_hdmi_phy_settings[] = {
+	{
+		0, 50000000,
+		{
+			{{0x0, 0x0A}, 0x12, 0x0},
+			{{0x0, 0x0A}, 0x12, 0x0},
+			{{0x0, 0x0A}, 0x12, 0x0}
+		},
+		{{0x0, 0x0A}, 0x18, 0x0},
+	},
+	{
+		50000001, 75000000,
+		{
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		75000001,   165000000,
+		{
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0},
+			{{0x0, 0x09}, 0x12, 0x0}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		165000001,  250000000,
+		{
+			{{0x0, 0x0F}, 0x12, 0x1},
+			{{0x0, 0x0F}, 0x12, 0x1},
+			{{0x0, 0x0F}, 0x12, 0x1}
+		},
+		{{0x0, 0x0C}, 0x18, 0x3},
+	},
+	{
+		250000001,  340000000,
+		{
+			{{0x2, 0x0D}, 0x12, 0x1},
+			{{0x2, 0x0D}, 0x12, 0x1},
+			{{0x2, 0x0D}, 0x12, 0x1}
+		},
+		{{0x0, 0x0C}, 0x18, 0xF},
+	},
+	{
+		340000001,  450000000,
+		{
+			{{0x0, 0x1B}, 0x12, 0xF},
+			{{0x0, 0x1B}, 0x12, 0xF},
+			{{0x0, 0x1B}, 0x12, 0xF}
+		},
+		{{0x0, 0x0A}, 0x12, 0xF},
+	},
+	{
+		450000001,  600000000,
+		{
+			{{0x0, 0x1C}, 0x12, 0xF},
+			{{0x0, 0x1C}, 0x12, 0xF},
+			{{0x0, 0x1C}, 0x12, 0xF}
+		},
+		{{0x0, 0x0B}, 0x13, 0xF},
+	},
+};
+
+static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
+{
+	unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
+
+		if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
+			return s;
+	}
+
+	/*
+	 * If the pixel clock exceeds our max setting, try the max
+	 * setting anyway.
+	 */
+	return &vc5_hdmi_phy_settings[count - 1];
+}
+
+static const struct phy_lane_settings *
+phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
+			 unsigned long long tmds_rate)
+{
+	const struct phy_settings *settings = phy_get_settings(tmds_rate);
+
+	if (chan == PHY_LANE_CK)
+		return &settings->clock;
+
+	return &settings->channel[chan];
+}
+
+static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
+}
+
+void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
+{
+	const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
+	const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+	unsigned long long pixel_freq = mode->clock * 1000;
+	unsigned long long vco_freq;
+	unsigned char word_sel;
+	u8 vco_sel, vco_div;
+
+	vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
+
+	vc5_hdmi_reset_phy(vc4_hdmi);
+
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
+		   ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
+
+	HDMI_WRITE(HDMI_RM_CONTROL,
+		   HDMI_READ(HDMI_RM_CONTROL) |
+		   VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
+		   VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
+		   VC4_HDMI_RM_CONTROL_FREE_RUN);
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
+		   (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
+		    ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
+		   VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
+		   (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
+		    ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
+		   VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
+
+	HDMI_WRITE(HDMI_RM_OFFSET,
+		   VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
+				 VC4_HDMI_RM_OFFSET_OFFSET) |
+		   VC4_HDMI_RM_OFFSET_ONLY);
+
+	HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
+		   VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
+		   VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
+		   VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
+		   VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
+		   VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
+		   HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
+		   VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
+		   VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
+		   VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
+
+	HDMI_WRITE(HDMI_RM_FORMAT,
+		   HDMI_READ(HDMI_RM_FORMAT) |
+		   VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
+
+	HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
+		   HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
+
+	if (pixel_freq >= 340000000)
+		word_sel = 3;
+	else
+		word_sel = 0;
+	HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_3,
+		   VC4_SET_FIELD(phy_get_cp_current(vco_freq),
+				 VC4_HDMI_TX_PHY_CTL_3_ICP) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
+		   VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
+		   VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
+		   VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
+		   VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
+
+	chan0_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
+					 pixel_freq);
+	chan1_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
+					 pixel_freq);
+	chan2_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
+					 pixel_freq);
+	clock_settings =
+		phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
+					 pixel_freq);
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_0,
+		   VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
+		   VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
+		   VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
+		   VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
+		   VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
+		   VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
+		   VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
+		   VC4_SET_FIELD(clock_settings->amplitude.main_driver,
+				 VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_1,
+		   HDMI_READ(HDMI_TX_PHY_CTL_1) |
+		   VC4_SET_FIELD(chan0_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
+		   VC4_SET_FIELD(chan1_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
+		   VC4_SET_FIELD(chan2_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
+		   VC4_SET_FIELD(clock_settings->res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
+
+	HDMI_WRITE(HDMI_TX_PHY_CTL_2,
+		   VC4_SET_FIELD(chan0_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
+		   VC4_SET_FIELD(chan1_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
+		   VC4_SET_FIELD(chan2_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
+		   VC4_SET_FIELD(clock_settings->term_res_sel_data,
+				 VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
+		   VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
+				 VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
+
+	HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
+		   VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
+				 VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
+		   ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
+		     VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
+
+	HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
+		   HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
+		   VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
+		   VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
+}
+
+void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) {
+	vc5_hdmi_reset_phy(vc4_hdmi);
+}
+
+void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
+		   ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+}
+
+void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
+{
+	HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
+		   HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
+		   VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
+}
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
index bc47cc9bc883..a5f1354e3e06 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
@@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
 	VC4_INVALID = 0,
 	VC4_HDMI,
 	VC4_HD,
+	VC5_CEC,
+	VC5_CSC,
+	VC5_DVP,
+	VC5_PHY,
+	VC5_RAM,
+	VC5_RM,
 };
 
 enum vc4_hdmi_field {
@@ -36,6 +42,7 @@ enum vc4_hdmi_field {
 	HDMI_CEC_TX_DATA_2,
 	HDMI_CEC_TX_DATA_3,
 	HDMI_CEC_TX_DATA_4,
+	HDMI_CLOCK_STOP,
 	HDMI_CORE_REV,
 	HDMI_CRP_CFG,
 	HDMI_CSC_12_11,
@@ -52,6 +59,7 @@ enum vc4_hdmi_field {
 	 */
 	HDMI_CTS_0,
 	HDMI_CTS_1,
+	HDMI_DVP_CTL,
 	HDMI_FIFO_CTL,
 	HDMI_FRAME_COUNT,
 	HDMI_HORZA,
@@ -84,10 +92,27 @@ enum vc4_hdmi_field {
 	HDMI_RAM_PACKET_CONFIG,
 	HDMI_RAM_PACKET_START,
 	HDMI_RAM_PACKET_STATUS,
+	HDMI_RM_CONTROL,
+	HDMI_RM_FORMAT,
+	HDMI_RM_OFFSET,
 	HDMI_SCHEDULER_CONTROL,
 	HDMI_SW_RESET_CONTROL,
+	HDMI_TX_PHY_CHANNEL_SWAP,
+	HDMI_TX_PHY_CLK_DIV,
 	HDMI_TX_PHY_CTL_0,
+	HDMI_TX_PHY_CTL_1,
+	HDMI_TX_PHY_CTL_2,
+	HDMI_TX_PHY_CTL_3,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
+	HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
+	HDMI_TX_PHY_PLL_CFG,
+	HDMI_TX_PHY_PLL_CTL_0,
+	HDMI_TX_PHY_PLL_CTL_1,
+	HDMI_TX_PHY_POWERDOWN_CTL,
 	HDMI_TX_PHY_RESET_CTL,
+	HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
+	HDMI_VEC_INTERFACE_XBAR,
 	HDMI_VERTA0,
 	HDMI_VERTA1,
 	HDMI_VERTB0,
@@ -110,6 +135,12 @@ struct vc4_hdmi_register {
 
 #define VC4_HD_REG(reg, offset)		_VC4_REG(VC4_HD, reg, offset)
 #define VC4_HDMI_REG(reg, offset)	_VC4_REG(VC4_HDMI, reg, offset)
+#define VC5_CEC_REG(reg, offset)	_VC4_REG(VC5_CEC, reg, offset)
+#define VC5_CSC_REG(reg, offset)	_VC4_REG(VC5_CSC, reg, offset)
+#define VC5_DVP_REG(reg, offset)	_VC4_REG(VC5_DVP, reg, offset)
+#define VC5_PHY_REG(reg, offset)	_VC4_REG(VC5_PHY, reg, offset)
+#define VC5_RAM_REG(reg, offset)	_VC4_REG(VC5_RAM, reg, offset)
+#define VC5_RM_REG(reg, offset)		_VC4_REG(VC5_RM, reg, offset)
 
 static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
 	VC4_HD_REG(HDMI_M_CTL, 0x000c),
@@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
 	VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
 };
 
+static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
+	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0014),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0044),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),
+
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
+
+	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
+	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
+
+	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
+	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
+	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
+	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
+	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
+
+	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
+	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
+	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
+
+	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
+
+	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
+
+	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
+	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
+	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
+	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
+	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
+	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
+	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
+};
+
+static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
+	VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
+	VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
+	VC4_HD_REG(HDMI_MAI_THR, 0x0034),
+	VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
+	VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
+	VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
+	VC4_HD_REG(HDMI_VID_CTL, 0x0048),
+	VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),
+
+	VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
+	VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
+	VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
+	VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
+	VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
+	VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
+	VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
+	VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
+	VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
+	VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
+	VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
+	VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
+	VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
+	VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
+	VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
+	VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
+
+	VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
+	VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
+
+	VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
+	VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
+	VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
+	VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
+	VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
+	VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
+	VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
+
+	VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
+	VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
+	VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
+
+	VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
+
+	VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
+	VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
+	VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
+	VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
+
+	VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
+	VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
+	VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
+	VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
+	VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
+	VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
+	VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
+};
+
 static inline
 void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
 					enum vc4_hdmi_regs reg)
@@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
 	case VC4_HDMI:
 		return hdmi->hdmicore_regs;
 
+	case VC5_CSC:
+		return hdmi->csc_regs;
+
+	case VC5_CEC:
+		return hdmi->cec_regs;
+
+	case VC5_DVP:
+		return hdmi->dvp_regs;
+
+	case VC5_PHY:
+		return hdmi->phy_regs;
+
+	case VC5_RAM:
+		return hdmi->ram_regs;
+
+	case VC5_RM:
+		return hdmi->rm_regs;
+
 	default:
 		return NULL;
 	}
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
index 30af52b406f1..be2c32a519b3 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -744,6 +744,8 @@
 # define VC4_HD_CSC_CTL_RGB2YCC			BIT(1)
 # define VC4_HD_CSC_CTL_ENABLE			BIT(0)
 
+# define VC4_DVP_HT_CLOCK_STOP_PIXEL		BIT(1)
+
 /* HVS display list information. */
 #define HVS_BOOTLOADER_DLIST_END                32
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard, Rob Herring

The HDMI controllers found in the BCM2711 SoC need some adjustments to the
bindings, especially since the registers have been shuffled around in more
register ranges.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
new file mode 100644
index 000000000000..6091fe3d315b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/brcm,bcm2711-hdmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
+
+maintainers:
+  - Eric Anholt <eric@anholt.net>
+
+properties:
+  compatible:
+    enum:
+      - brcm,bcm2711-hdmi0
+      - brcm,bcm2711-hdmi1
+
+  reg:
+    items:
+      - description: HDMI controller register range
+      - description: DVP register range
+      - description: HDMI PHY register range
+      - description: Rate Manager register range
+      - description: Packet RAM register range
+      - description: Metadata RAM register range
+      - description: CSC register range
+      - description: CEC register range
+      - description: HD register range
+
+  reg-names:
+    items:
+      - const: hdmi
+      - const: dvp
+      - const: phy
+      - const: rm
+      - const: packet
+      - const: metadata
+      - const: csc
+      - const: cec
+      - const: hd
+
+  clocks:
+    description: The HDMI state machine clock
+
+  clock-names:
+    const: hdmi
+
+  ddc:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description: >
+      Phandle of the I2C controller used for DDC EDID probing
+
+  hpd-gpios:
+    description: >
+      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
+      as an interrupt/status bit in the HDMI controller itself)
+
+  dmas:
+    maxItems: 1
+    description: >
+      Should contain one entry pointing to the DMA channel used to
+      transfer audio data.
+
+  dma-names:
+    const: audio-rx
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - resets
+  - ddc
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi0: hdmi@7ef00700 {
+        compatible = "brcm,bcm2711-hdmi0";
+        reg = <0x7ef00700 0x300>,
+              <0x7ef00300 0x200>,
+              <0x7ef00f00 0x80>,
+              <0x7ef00f80 0x80>,
+              <0x7ef01b00 0x200>,
+              <0x7ef01f00 0x400>,
+              <0x7ef00200 0x80>,
+              <0x7ef04300 0x100>,
+              <0x7ef20000 0x100>;
+        reg-names = "hdmi",
+                    "dvp",
+                    "phy",
+                    "rm",
+                    "packet",
+                    "metadata",
+                    "csc",
+                    "cec",
+                    "hd";
+        clocks = <&firmware_clocks 13>;
+        clock-names = "hdmi";
+        resets = <&dvp 0>;
+        ddc = <&ddc0>;
+    };
+
+...
-- 
git-series 0.9.1

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

* [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Rob Herring, Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI controllers found in the BCM2711 SoC need some adjustments to the
bindings, especially since the registers have been shuffled around in more
register ranges.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
new file mode 100644
index 000000000000..6091fe3d315b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/brcm,bcm2711-hdmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
+
+maintainers:
+  - Eric Anholt <eric@anholt.net>
+
+properties:
+  compatible:
+    enum:
+      - brcm,bcm2711-hdmi0
+      - brcm,bcm2711-hdmi1
+
+  reg:
+    items:
+      - description: HDMI controller register range
+      - description: DVP register range
+      - description: HDMI PHY register range
+      - description: Rate Manager register range
+      - description: Packet RAM register range
+      - description: Metadata RAM register range
+      - description: CSC register range
+      - description: CEC register range
+      - description: HD register range
+
+  reg-names:
+    items:
+      - const: hdmi
+      - const: dvp
+      - const: phy
+      - const: rm
+      - const: packet
+      - const: metadata
+      - const: csc
+      - const: cec
+      - const: hd
+
+  clocks:
+    description: The HDMI state machine clock
+
+  clock-names:
+    const: hdmi
+
+  ddc:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description: >
+      Phandle of the I2C controller used for DDC EDID probing
+
+  hpd-gpios:
+    description: >
+      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
+      as an interrupt/status bit in the HDMI controller itself)
+
+  dmas:
+    maxItems: 1
+    description: >
+      Should contain one entry pointing to the DMA channel used to
+      transfer audio data.
+
+  dma-names:
+    const: audio-rx
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - resets
+  - ddc
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi0: hdmi@7ef00700 {
+        compatible = "brcm,bcm2711-hdmi0";
+        reg = <0x7ef00700 0x300>,
+              <0x7ef00300 0x200>,
+              <0x7ef00f00 0x80>,
+              <0x7ef00f80 0x80>,
+              <0x7ef01b00 0x200>,
+              <0x7ef01f00 0x400>,
+              <0x7ef00200 0x80>,
+              <0x7ef04300 0x100>,
+              <0x7ef20000 0x100>;
+        reg-names = "hdmi",
+                    "dvp",
+                    "phy",
+                    "rm",
+                    "packet",
+                    "metadata",
+                    "csc",
+                    "cec",
+                    "hd";
+        clocks = <&firmware_clocks 13>;
+        clock-names = "hdmi";
+        resets = <&dvp 0>;
+        ddc = <&ddc0>;
+    };
+
+...
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The HDMI controllers found in the BCM2711 SoC need some adjustments to the
bindings, especially since the registers have been shuffled around in more
register ranges.

Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
new file mode 100644
index 000000000000..6091fe3d315b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/brcm,bcm2711-hdmi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
+
+maintainers:
+  - Eric Anholt <eric@anholt.net>
+
+properties:
+  compatible:
+    enum:
+      - brcm,bcm2711-hdmi0
+      - brcm,bcm2711-hdmi1
+
+  reg:
+    items:
+      - description: HDMI controller register range
+      - description: DVP register range
+      - description: HDMI PHY register range
+      - description: Rate Manager register range
+      - description: Packet RAM register range
+      - description: Metadata RAM register range
+      - description: CSC register range
+      - description: CEC register range
+      - description: HD register range
+
+  reg-names:
+    items:
+      - const: hdmi
+      - const: dvp
+      - const: phy
+      - const: rm
+      - const: packet
+      - const: metadata
+      - const: csc
+      - const: cec
+      - const: hd
+
+  clocks:
+    description: The HDMI state machine clock
+
+  clock-names:
+    const: hdmi
+
+  ddc:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description: >
+      Phandle of the I2C controller used for DDC EDID probing
+
+  hpd-gpios:
+    description: >
+      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
+      as an interrupt/status bit in the HDMI controller itself)
+
+  dmas:
+    maxItems: 1
+    description: >
+      Should contain one entry pointing to the DMA channel used to
+      transfer audio data.
+
+  dma-names:
+    const: audio-rx
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - resets
+  - ddc
+
+additionalProperties: false
+
+examples:
+  - |
+    hdmi0: hdmi@7ef00700 {
+        compatible = "brcm,bcm2711-hdmi0";
+        reg = <0x7ef00700 0x300>,
+              <0x7ef00300 0x200>,
+              <0x7ef00f00 0x80>,
+              <0x7ef00f80 0x80>,
+              <0x7ef01b00 0x200>,
+              <0x7ef01f00 0x400>,
+              <0x7ef00200 0x80>,
+              <0x7ef04300 0x100>,
+              <0x7ef20000 0x100>;
+        reg-names = "hdmi",
+                    "dvp",
+                    "phy",
+                    "rm",
+                    "packet",
+                    "metadata",
+                    "csc",
+                    "cec",
+                    "hd";
+        clocks = <&firmware_clocks 13>;
+        clock-names = "hdmi";
+        resets = <&dvp 0>;
+        ddc = <&ddc0>;
+    };
+
+...
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 76/78] dt-bindings: display: vc4: Document BCM2711 VC5
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard, Rob Herring

The BCM2711 comes with a new VideoCore. Add a compatible for it.

Reviewed-by: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
index 0dcf0c397375..49a5e041aa49 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
@@ -17,6 +17,7 @@ description: >
 properties:
   compatible:
     enum:
+      - brcm,bcm2711-vc5
       - brcm,bcm2835-vc4
       - brcm,cygnus-vc4
 
-- 
git-series 0.9.1

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

* [PATCH v4 76/78] dt-bindings: display: vc4: Document BCM2711 VC5
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 comes with a new VideoCore. Add a compatible for it.

Reviewed-by: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
index 0dcf0c397375..49a5e041aa49 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
@@ -17,6 +17,7 @@ description: >
 properties:
   compatible:
     enum:
+      - brcm,bcm2711-vc5
       - brcm,bcm2835-vc4
       - brcm,cygnus-vc4
 
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 76/78] dt-bindings: display: vc4: Document BCM2711 VC5
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 comes with a new VideoCore. Add a compatible for it.

Reviewed-by: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
index 0dcf0c397375..49a5e041aa49 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
@@ -17,6 +17,7 @@ description: >
 properties:
   compatible:
     enum:
+      - brcm,bcm2711-vc5
       - brcm,bcm2835-vc4
       - brcm,cygnus-vc4
 
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

The BCM2711 has a reworked display pipeline, and the load tracker needs
some adjustement to operate properly. Let's add a compatible for BCM2711
and disable the load tracker until properly supported.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.c   |  1 +-
 drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
 drivers/gpu/drm/vc4/vc4_kms.c   | 42 +++++++++++++++++++++++-----------
 drivers/gpu/drm/vc4/vc4_plane.c |  5 ++++-
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 9567d1019212..f1a5fd5dab6f 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id vc4_of_match[] = {
+	{ .compatible = "brcm,bcm2711-vc5", },
 	{ .compatible = "brcm,bcm2835-vc4", },
 	{ .compatible = "brcm,cygnus-vc4", },
 	{},
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 501a48a714d3..8c8d96b6289f 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -200,6 +200,9 @@ struct vc4_dev {
 
 	int power_refcount;
 
+	/* Set to true when the load tracker is supported. */
+	bool load_tracker_available;
+
 	/* Set to true when the load tracker is active. */
 	bool load_tracker_enabled;
 
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 7c8a87339959..ae479f988666 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -532,6 +532,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state)
 	struct drm_plane *plane;
 	int i;
 
+	if (!vc4->load_tracker_available)
+		return 0;
+
 	priv_state = drm_atomic_get_private_obj_state(state,
 						      &vc4->load_tracker);
 	if (IS_ERR(priv_state))
@@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
 	struct vc4_load_tracker_state *load_state;
 	int ret;
 
-	/* Start with the load tracker enabled. Can be disabled through the
-	 * debugfs load_tracker file.
-	 */
-	vc4->load_tracker_enabled = true;
+	if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
+		vc4->load_tracker_available = true;
+
+		/* Start with the load tracker enabled. Can be
+		 * disabled through the debugfs load_tracker file.
+		 */
+		vc4->load_tracker_enabled = true;
+	}
 
 	sema_init(&vc4->async_modeset, 1);
 
@@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
 		return ret;
 	}
 
-	dev->mode_config.max_width = 2048;
-	dev->mode_config.max_height = 2048;
+	if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
+		dev->mode_config.max_width = 7680;
+		dev->mode_config.max_height = 7680;
+	} else {
+		dev->mode_config.max_width = 2048;
+		dev->mode_config.max_height = 2048;
+	}
+
 	dev->mode_config.funcs = &vc4_mode_funcs;
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.async_page_flip = true;
@@ -714,14 +727,17 @@ int vc4_kms_load(struct drm_device *dev)
 	drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
 				    &vc4_ctm_state_funcs);
 
-	load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
-	if (!load_state) {
-		drm_atomic_private_obj_fini(&vc4->ctm_manager);
-		return -ENOMEM;
-	}
+	if (vc4->load_tracker_available) {
+		load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
+		if (!load_state) {
+			drm_atomic_private_obj_fini(&vc4->ctm_manager);
+			return -ENOMEM;
+		}
 
-	drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base,
-				    &vc4_load_tracker_state_funcs);
+		drm_atomic_private_obj_init(dev, &vc4->load_tracker,
+					    &load_state->base,
+					    &vc4_load_tracker_state_funcs);
+	}
 
 	drm_mode_config_reset(dev);
 
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 1e38e603f83b..24d7e6db6fdd 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state)
 	struct vc4_plane_state *vc4_state;
 	struct drm_crtc_state *crtc_state;
 	unsigned int vscale_factor;
+	struct vc4_dev *vc4;
+
+	vc4 = to_vc4_dev(state->plane->dev);
+	if (!vc4->load_tracker_available)
+		return;
 
 	vc4_state = to_vc4_plane_state(state);
 	crtc_state = drm_atomic_get_existing_crtc_state(state->state,
-- 
git-series 0.9.1

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

* [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 has a reworked display pipeline, and the load tracker needs
some adjustement to operate properly. Let's add a compatible for BCM2711
and disable the load tracker until properly supported.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.c   |  1 +-
 drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
 drivers/gpu/drm/vc4/vc4_kms.c   | 42 +++++++++++++++++++++++-----------
 drivers/gpu/drm/vc4/vc4_plane.c |  5 ++++-
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 9567d1019212..f1a5fd5dab6f 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id vc4_of_match[] = {
+	{ .compatible = "brcm,bcm2711-vc5", },
 	{ .compatible = "brcm,bcm2835-vc4", },
 	{ .compatible = "brcm,cygnus-vc4", },
 	{},
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 501a48a714d3..8c8d96b6289f 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -200,6 +200,9 @@ struct vc4_dev {
 
 	int power_refcount;
 
+	/* Set to true when the load tracker is supported. */
+	bool load_tracker_available;
+
 	/* Set to true when the load tracker is active. */
 	bool load_tracker_enabled;
 
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 7c8a87339959..ae479f988666 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -532,6 +532,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state)
 	struct drm_plane *plane;
 	int i;
 
+	if (!vc4->load_tracker_available)
+		return 0;
+
 	priv_state = drm_atomic_get_private_obj_state(state,
 						      &vc4->load_tracker);
 	if (IS_ERR(priv_state))
@@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
 	struct vc4_load_tracker_state *load_state;
 	int ret;
 
-	/* Start with the load tracker enabled. Can be disabled through the
-	 * debugfs load_tracker file.
-	 */
-	vc4->load_tracker_enabled = true;
+	if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
+		vc4->load_tracker_available = true;
+
+		/* Start with the load tracker enabled. Can be
+		 * disabled through the debugfs load_tracker file.
+		 */
+		vc4->load_tracker_enabled = true;
+	}
 
 	sema_init(&vc4->async_modeset, 1);
 
@@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
 		return ret;
 	}
 
-	dev->mode_config.max_width = 2048;
-	dev->mode_config.max_height = 2048;
+	if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
+		dev->mode_config.max_width = 7680;
+		dev->mode_config.max_height = 7680;
+	} else {
+		dev->mode_config.max_width = 2048;
+		dev->mode_config.max_height = 2048;
+	}
+
 	dev->mode_config.funcs = &vc4_mode_funcs;
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.async_page_flip = true;
@@ -714,14 +727,17 @@ int vc4_kms_load(struct drm_device *dev)
 	drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
 				    &vc4_ctm_state_funcs);
 
-	load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
-	if (!load_state) {
-		drm_atomic_private_obj_fini(&vc4->ctm_manager);
-		return -ENOMEM;
-	}
+	if (vc4->load_tracker_available) {
+		load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
+		if (!load_state) {
+			drm_atomic_private_obj_fini(&vc4->ctm_manager);
+			return -ENOMEM;
+		}
 
-	drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base,
-				    &vc4_load_tracker_state_funcs);
+		drm_atomic_private_obj_init(dev, &vc4->load_tracker,
+					    &load_state->base,
+					    &vc4_load_tracker_state_funcs);
+	}
 
 	drm_mode_config_reset(dev);
 
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 1e38e603f83b..24d7e6db6fdd 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state)
 	struct vc4_plane_state *vc4_state;
 	struct drm_crtc_state *crtc_state;
 	unsigned int vscale_factor;
+	struct vc4_dev *vc4;
+
+	vc4 = to_vc4_dev(state->plane->dev);
+	if (!vc4->load_tracker_available)
+		return;
 
 	vc4_state = to_vc4_plane_state(state);
 	crtc_state = drm_atomic_get_existing_crtc_state(state->state,
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

The BCM2711 has a reworked display pipeline, and the load tracker needs
some adjustement to operate properly. Let's add a compatible for BCM2711
and disable the load tracker until properly supported.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 drivers/gpu/drm/vc4/vc4_drv.c   |  1 +-
 drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
 drivers/gpu/drm/vc4/vc4_kms.c   | 42 +++++++++++++++++++++++-----------
 drivers/gpu/drm/vc4/vc4_plane.c |  5 ++++-
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 9567d1019212..f1a5fd5dab6f 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id vc4_of_match[] = {
+	{ .compatible = "brcm,bcm2711-vc5", },
 	{ .compatible = "brcm,bcm2835-vc4", },
 	{ .compatible = "brcm,cygnus-vc4", },
 	{},
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 501a48a714d3..8c8d96b6289f 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -200,6 +200,9 @@ struct vc4_dev {
 
 	int power_refcount;
 
+	/* Set to true when the load tracker is supported. */
+	bool load_tracker_available;
+
 	/* Set to true when the load tracker is active. */
 	bool load_tracker_enabled;
 
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 7c8a87339959..ae479f988666 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -532,6 +532,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state)
 	struct drm_plane *plane;
 	int i;
 
+	if (!vc4->load_tracker_available)
+		return 0;
+
 	priv_state = drm_atomic_get_private_obj_state(state,
 						      &vc4->load_tracker);
 	if (IS_ERR(priv_state))
@@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
 	struct vc4_load_tracker_state *load_state;
 	int ret;
 
-	/* Start with the load tracker enabled. Can be disabled through the
-	 * debugfs load_tracker file.
-	 */
-	vc4->load_tracker_enabled = true;
+	if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
+		vc4->load_tracker_available = true;
+
+		/* Start with the load tracker enabled. Can be
+		 * disabled through the debugfs load_tracker file.
+		 */
+		vc4->load_tracker_enabled = true;
+	}
 
 	sema_init(&vc4->async_modeset, 1);
 
@@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
 		return ret;
 	}
 
-	dev->mode_config.max_width = 2048;
-	dev->mode_config.max_height = 2048;
+	if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
+		dev->mode_config.max_width = 7680;
+		dev->mode_config.max_height = 7680;
+	} else {
+		dev->mode_config.max_width = 2048;
+		dev->mode_config.max_height = 2048;
+	}
+
 	dev->mode_config.funcs = &vc4_mode_funcs;
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.async_page_flip = true;
@@ -714,14 +727,17 @@ int vc4_kms_load(struct drm_device *dev)
 	drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
 				    &vc4_ctm_state_funcs);
 
-	load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
-	if (!load_state) {
-		drm_atomic_private_obj_fini(&vc4->ctm_manager);
-		return -ENOMEM;
-	}
+	if (vc4->load_tracker_available) {
+		load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
+		if (!load_state) {
+			drm_atomic_private_obj_fini(&vc4->ctm_manager);
+			return -ENOMEM;
+		}
 
-	drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base,
-				    &vc4_load_tracker_state_funcs);
+		drm_atomic_private_obj_init(dev, &vc4->load_tracker,
+					    &load_state->base,
+					    &vc4_load_tracker_state_funcs);
+	}
 
 	drm_mode_config_reset(dev);
 
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 1e38e603f83b..24d7e6db6fdd 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state)
 	struct vc4_plane_state *vc4_state;
 	struct drm_crtc_state *crtc_state;
 	unsigned int vscale_factor;
+	struct vc4_dev *vc4;
+
+	vc4 = to_vc4_dev(state->plane->dev);
+	if (!vc4->load_tracker_available)
+		return;
 
 	vc4_state = to_vc4_plane_state(state);
 	crtc_state = drm_atomic_get_existing_crtc_state(state->state,
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-08 17:42     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Maxime Ripard

Now that all the drivers have been adjusted for it, let's bring in the
necessary device tree changes.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  46 +++++++++++-
 arch/arm/boot/dts/bcm2711.dtsi        | 115 ++++++++++++++++++++++++++-
 2 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
index 222d7825e1ab..b93eb30e1ddb 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
@@ -68,6 +68,14 @@
 	};
 };
 
+&ddc0 {
+	status = "okay";
+};
+
+&ddc1 {
+	status = "okay";
+};
+
 &firmware {
 	firmware_clocks: clocks {
 		compatible = "raspberrypi,firmware-clocks";
@@ -163,6 +171,36 @@
 			  "RGMII_TXD3";
 };
 
+&hdmi0 {
+	clocks = <&firmware_clocks 13>, <&dvp 0>;
+	status = "okay";
+};
+
+&hdmi1 {
+	clocks = <&firmware_clocks 13>, <&dvp 1>;
+	status = "okay";
+};
+
+&hvs {
+	clocks = <&firmware_clocks 4>;
+};
+
+&pixelvalve0 {
+	status = "okay";
+};
+
+&pixelvalve1 {
+	status = "okay";
+};
+
+&pixelvalve2 {
+	status = "okay";
+};
+
+&pixelvalve4 {
+	status = "okay";
+};
+
 &pwm1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
@@ -231,3 +269,11 @@
 &vchiq {
 	interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 };
+
+&vc4 {
+	status = "okay";
+};
+
+&vec {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index 00bcaed1be32..e637378650f6 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -12,6 +12,11 @@
 
 	interrupt-parent = <&gicv2>;
 
+	vc4: gpu {
+		compatible = "brcm,bcm2711-vc5";
+		status = "disabled";
+	};
+
 	clk_108MHz: clk-108M {
 		#clock-cells = <0>;
 		compatible = "fixed-clock";
@@ -238,6 +243,27 @@
 			status = "disabled";
 		};
 
+		pixelvalve0: pixelvalve@7e206000 {
+			compatible = "brcm,bcm2711-pixelvalve0";
+			reg = <0x7e206000 0x100>;
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		pixelvalve1: pixelvalve@7e207000 {
+			compatible = "brcm,bcm2711-pixelvalve1";
+			reg = <0x7e207000 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		pixelvalve2: pixelvalve@7e20a000 {
+			compatible = "brcm,bcm2711-pixelvalve2";
+			reg = <0x7e20a000 0x100>;
+			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
 		pwm1: pwm@7e20c800 {
 			compatible = "brcm,bcm2835-pwm";
 			reg = <0x7e20c800 0x28>;
@@ -248,10 +274,25 @@
 			status = "disabled";
 		};
 
-		hvs@7e400000 {
+		pixelvalve4: pixelvalve@7e216000 {
+			compatible = "brcm,bcm2711-pixelvalve4";
+			reg = <0x7e216000 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		hvs: hvs@7e400000 {
+			compatible = "brcm,bcm2711-hvs";
 			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		pixelvalve3: pixelvalve@7ec12000 {
+			compatible = "brcm,bcm2711-pixelvalve3";
+			reg = <0x7ec12000 0x100>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
 		dvp: clock@7ef00000 {
 			compatible = "brcm,brcm2711-dvp";
 			reg = <0x7ef00000 0x10>;
@@ -259,6 +300,78 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 		};
+
+		hdmi0: hdmi@7ef00700 {
+			compatible = "brcm,bcm2711-hdmi0";
+			reg = <0x7ef00700 0x300>,
+			      <0x7ef00300 0x200>,
+			      <0x7ef00f00 0x80>,
+			      <0x7ef00f80 0x80>,
+			      <0x7ef01b00 0x200>,
+			      <0x7ef01f00 0x400>,
+			      <0x7ef00200 0x80>,
+			      <0x7ef04300 0x100>,
+			      <0x7ef20000 0x100>;
+			reg-names = "hdmi",
+				    "dvp",
+				    "phy",
+				    "rm",
+				    "packet",
+				    "metadata",
+				    "csc",
+				    "cec",
+				    "hd";
+			clock-names = "hdmi", "clk-108M";
+			resets = <&dvp 0>;
+			ddc = <&ddc0>;
+			dmas = <&dma 10>;
+			dma-names = "audio-rx";
+			status = "disabled";
+		};
+
+		ddc0: i2c@7ef04500 {
+			compatible = "brcm,bcm2711-hdmi-i2c";
+			reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
+			reg-names = "bsc", "auto-i2c";
+			clock-frequency = <97500>;
+			status = "disabled";
+		};
+
+		hdmi1: hdmi@7ef05700 {
+			compatible = "brcm,bcm2711-hdmi1";
+			reg = <0x7ef05700 0x300>,
+			      <0x7ef05300 0x200>,
+			      <0x7ef05f00 0x80>,
+			      <0x7ef05f80 0x80>,
+			      <0x7ef06b00 0x200>,
+			      <0x7ef06f00 0x400>,
+			      <0x7ef00280 0x80>,
+			      <0x7ef09300 0x100>,
+			      <0x7ef20000 0x100>;
+			reg-names = "hdmi",
+				    "dvp",
+				    "phy",
+				    "rm",
+				    "packet",
+				    "metadata",
+				    "csc",
+				    "cec",
+				    "hd";
+			ddc = <&ddc1>;
+			clock-names = "hdmi", "clk-108M";
+			resets = <&dvp 1>;
+			dmas = <&dma 17>;
+			dma-names = "audio-rx";
+			status = "disabled";
+		};
+
+		ddc1: i2c@7ef09500 {
+			compatible = "brcm,bcm2711-hdmi-i2c";
+			reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
+			reg-names = "bsc", "auto-i2c";
+			clock-frequency = <97500>;
+			status = "disabled";
+		};
 	};
 
 	/*
-- 
git-series 0.9.1

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

* [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that all the drivers have been adjusted for it, let's bring in the
necessary device tree changes.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  46 +++++++++++-
 arch/arm/boot/dts/bcm2711.dtsi        | 115 ++++++++++++++++++++++++++-
 2 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
index 222d7825e1ab..b93eb30e1ddb 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
@@ -68,6 +68,14 @@
 	};
 };
 
+&ddc0 {
+	status = "okay";
+};
+
+&ddc1 {
+	status = "okay";
+};
+
 &firmware {
 	firmware_clocks: clocks {
 		compatible = "raspberrypi,firmware-clocks";
@@ -163,6 +171,36 @@
 			  "RGMII_TXD3";
 };
 
+&hdmi0 {
+	clocks = <&firmware_clocks 13>, <&dvp 0>;
+	status = "okay";
+};
+
+&hdmi1 {
+	clocks = <&firmware_clocks 13>, <&dvp 1>;
+	status = "okay";
+};
+
+&hvs {
+	clocks = <&firmware_clocks 4>;
+};
+
+&pixelvalve0 {
+	status = "okay";
+};
+
+&pixelvalve1 {
+	status = "okay";
+};
+
+&pixelvalve2 {
+	status = "okay";
+};
+
+&pixelvalve4 {
+	status = "okay";
+};
+
 &pwm1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
@@ -231,3 +269,11 @@
 &vchiq {
 	interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 };
+
+&vc4 {
+	status = "okay";
+};
+
+&vec {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index 00bcaed1be32..e637378650f6 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -12,6 +12,11 @@
 
 	interrupt-parent = <&gicv2>;
 
+	vc4: gpu {
+		compatible = "brcm,bcm2711-vc5";
+		status = "disabled";
+	};
+
 	clk_108MHz: clk-108M {
 		#clock-cells = <0>;
 		compatible = "fixed-clock";
@@ -238,6 +243,27 @@
 			status = "disabled";
 		};
 
+		pixelvalve0: pixelvalve@7e206000 {
+			compatible = "brcm,bcm2711-pixelvalve0";
+			reg = <0x7e206000 0x100>;
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		pixelvalve1: pixelvalve@7e207000 {
+			compatible = "brcm,bcm2711-pixelvalve1";
+			reg = <0x7e207000 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		pixelvalve2: pixelvalve@7e20a000 {
+			compatible = "brcm,bcm2711-pixelvalve2";
+			reg = <0x7e20a000 0x100>;
+			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
 		pwm1: pwm@7e20c800 {
 			compatible = "brcm,bcm2835-pwm";
 			reg = <0x7e20c800 0x28>;
@@ -248,10 +274,25 @@
 			status = "disabled";
 		};
 
-		hvs@7e400000 {
+		pixelvalve4: pixelvalve@7e216000 {
+			compatible = "brcm,bcm2711-pixelvalve4";
+			reg = <0x7e216000 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		hvs: hvs@7e400000 {
+			compatible = "brcm,bcm2711-hvs";
 			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		pixelvalve3: pixelvalve@7ec12000 {
+			compatible = "brcm,bcm2711-pixelvalve3";
+			reg = <0x7ec12000 0x100>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
 		dvp: clock@7ef00000 {
 			compatible = "brcm,brcm2711-dvp";
 			reg = <0x7ef00000 0x10>;
@@ -259,6 +300,78 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 		};
+
+		hdmi0: hdmi@7ef00700 {
+			compatible = "brcm,bcm2711-hdmi0";
+			reg = <0x7ef00700 0x300>,
+			      <0x7ef00300 0x200>,
+			      <0x7ef00f00 0x80>,
+			      <0x7ef00f80 0x80>,
+			      <0x7ef01b00 0x200>,
+			      <0x7ef01f00 0x400>,
+			      <0x7ef00200 0x80>,
+			      <0x7ef04300 0x100>,
+			      <0x7ef20000 0x100>;
+			reg-names = "hdmi",
+				    "dvp",
+				    "phy",
+				    "rm",
+				    "packet",
+				    "metadata",
+				    "csc",
+				    "cec",
+				    "hd";
+			clock-names = "hdmi", "clk-108M";
+			resets = <&dvp 0>;
+			ddc = <&ddc0>;
+			dmas = <&dma 10>;
+			dma-names = "audio-rx";
+			status = "disabled";
+		};
+
+		ddc0: i2c@7ef04500 {
+			compatible = "brcm,bcm2711-hdmi-i2c";
+			reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
+			reg-names = "bsc", "auto-i2c";
+			clock-frequency = <97500>;
+			status = "disabled";
+		};
+
+		hdmi1: hdmi@7ef05700 {
+			compatible = "brcm,bcm2711-hdmi1";
+			reg = <0x7ef05700 0x300>,
+			      <0x7ef05300 0x200>,
+			      <0x7ef05f00 0x80>,
+			      <0x7ef05f80 0x80>,
+			      <0x7ef06b00 0x200>,
+			      <0x7ef06f00 0x400>,
+			      <0x7ef00280 0x80>,
+			      <0x7ef09300 0x100>,
+			      <0x7ef20000 0x100>;
+			reg-names = "hdmi",
+				    "dvp",
+				    "phy",
+				    "rm",
+				    "packet",
+				    "metadata",
+				    "csc",
+				    "cec",
+				    "hd";
+			ddc = <&ddc1>;
+			clock-names = "hdmi", "clk-108M";
+			resets = <&dvp 1>;
+			dmas = <&dma 17>;
+			dma-names = "audio-rx";
+			status = "disabled";
+		};
+
+		ddc1: i2c@7ef09500 {
+			compatible = "brcm,bcm2711-hdmi-i2c";
+			reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
+			reg-names = "bsc", "auto-i2c";
+			clock-frequency = <97500>;
+			status = "disabled";
+		};
 	};
 
 	/*
-- 
git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline
@ 2020-07-08 17:42     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-08 17:42 UTC (permalink / raw)
  To: Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel, Maxime Ripard

Now that all the drivers have been adjusted for it, let's bring in the
necessary device tree changes.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
 arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  46 +++++++++++-
 arch/arm/boot/dts/bcm2711.dtsi        | 115 ++++++++++++++++++++++++++-
 2 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
index 222d7825e1ab..b93eb30e1ddb 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
@@ -68,6 +68,14 @@
 	};
 };
 
+&ddc0 {
+	status = "okay";
+};
+
+&ddc1 {
+	status = "okay";
+};
+
 &firmware {
 	firmware_clocks: clocks {
 		compatible = "raspberrypi,firmware-clocks";
@@ -163,6 +171,36 @@
 			  "RGMII_TXD3";
 };
 
+&hdmi0 {
+	clocks = <&firmware_clocks 13>, <&dvp 0>;
+	status = "okay";
+};
+
+&hdmi1 {
+	clocks = <&firmware_clocks 13>, <&dvp 1>;
+	status = "okay";
+};
+
+&hvs {
+	clocks = <&firmware_clocks 4>;
+};
+
+&pixelvalve0 {
+	status = "okay";
+};
+
+&pixelvalve1 {
+	status = "okay";
+};
+
+&pixelvalve2 {
+	status = "okay";
+};
+
+&pixelvalve4 {
+	status = "okay";
+};
+
 &pwm1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
@@ -231,3 +269,11 @@
 &vchiq {
 	interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 };
+
+&vc4 {
+	status = "okay";
+};
+
+&vec {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index 00bcaed1be32..e637378650f6 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -12,6 +12,11 @@
 
 	interrupt-parent = <&gicv2>;
 
+	vc4: gpu {
+		compatible = "brcm,bcm2711-vc5";
+		status = "disabled";
+	};
+
 	clk_108MHz: clk-108M {
 		#clock-cells = <0>;
 		compatible = "fixed-clock";
@@ -238,6 +243,27 @@
 			status = "disabled";
 		};
 
+		pixelvalve0: pixelvalve@7e206000 {
+			compatible = "brcm,bcm2711-pixelvalve0";
+			reg = <0x7e206000 0x100>;
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		pixelvalve1: pixelvalve@7e207000 {
+			compatible = "brcm,bcm2711-pixelvalve1";
+			reg = <0x7e207000 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		pixelvalve2: pixelvalve@7e20a000 {
+			compatible = "brcm,bcm2711-pixelvalve2";
+			reg = <0x7e20a000 0x100>;
+			interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
 		pwm1: pwm@7e20c800 {
 			compatible = "brcm,bcm2835-pwm";
 			reg = <0x7e20c800 0x28>;
@@ -248,10 +274,25 @@
 			status = "disabled";
 		};
 
-		hvs@7e400000 {
+		pixelvalve4: pixelvalve@7e216000 {
+			compatible = "brcm,bcm2711-pixelvalve4";
+			reg = <0x7e216000 0x100>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		hvs: hvs@7e400000 {
+			compatible = "brcm,bcm2711-hvs";
 			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		pixelvalve3: pixelvalve@7ec12000 {
+			compatible = "brcm,bcm2711-pixelvalve3";
+			reg = <0x7ec12000 0x100>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
 		dvp: clock@7ef00000 {
 			compatible = "brcm,brcm2711-dvp";
 			reg = <0x7ef00000 0x10>;
@@ -259,6 +300,78 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 		};
+
+		hdmi0: hdmi@7ef00700 {
+			compatible = "brcm,bcm2711-hdmi0";
+			reg = <0x7ef00700 0x300>,
+			      <0x7ef00300 0x200>,
+			      <0x7ef00f00 0x80>,
+			      <0x7ef00f80 0x80>,
+			      <0x7ef01b00 0x200>,
+			      <0x7ef01f00 0x400>,
+			      <0x7ef00200 0x80>,
+			      <0x7ef04300 0x100>,
+			      <0x7ef20000 0x100>;
+			reg-names = "hdmi",
+				    "dvp",
+				    "phy",
+				    "rm",
+				    "packet",
+				    "metadata",
+				    "csc",
+				    "cec",
+				    "hd";
+			clock-names = "hdmi", "clk-108M";
+			resets = <&dvp 0>;
+			ddc = <&ddc0>;
+			dmas = <&dma 10>;
+			dma-names = "audio-rx";
+			status = "disabled";
+		};
+
+		ddc0: i2c@7ef04500 {
+			compatible = "brcm,bcm2711-hdmi-i2c";
+			reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
+			reg-names = "bsc", "auto-i2c";
+			clock-frequency = <97500>;
+			status = "disabled";
+		};
+
+		hdmi1: hdmi@7ef05700 {
+			compatible = "brcm,bcm2711-hdmi1";
+			reg = <0x7ef05700 0x300>,
+			      <0x7ef05300 0x200>,
+			      <0x7ef05f00 0x80>,
+			      <0x7ef05f80 0x80>,
+			      <0x7ef06b00 0x200>,
+			      <0x7ef06f00 0x400>,
+			      <0x7ef00280 0x80>,
+			      <0x7ef09300 0x100>,
+			      <0x7ef20000 0x100>;
+			reg-names = "hdmi",
+				    "dvp",
+				    "phy",
+				    "rm",
+				    "packet",
+				    "metadata",
+				    "csc",
+				    "cec",
+				    "hd";
+			ddc = <&ddc1>;
+			clock-names = "hdmi", "clk-108M";
+			resets = <&dvp 1>;
+			dmas = <&dma 17>;
+			dma-names = "audio-rx";
+			status = "disabled";
+		};
+
+		ddc1: i2c@7ef09500 {
+			compatible = "brcm,bcm2711-hdmi-i2c";
+			reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
+			reg-names = "bsc", "auto-i2c";
+			clock-frequency = <97500>;
+			status = "disabled";
+		};
 	};
 
 	/*
-- 
git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-10  7:37     ` Jian-Hong Pan
  -1 siblings, 0 replies; 432+ messages in thread
From: Jian-Hong Pan @ 2020-07-10  7:37 UTC (permalink / raw)
  To: maxime
  Cc: bcm-kernel-feedback-list, dave.stevenson, devicetree, dri-devel,
	eric, kdasu.kdev, linux-arm-kernel, linux-clk, linux-kernel,
	linux-rpi-kernel, mturquette, nsaenzjulienne, phil, robh+dt,
	sboyd, tim.gover, linux

Hi Maxime,

Thanks for your version 4 patch again.
I took the patches and applied them upon next-20200708.

I make system cold reboot to multi-user target and the text console shows on the
screen. Then, I simply hot re-plug the HDMI cable on HDMI0 port, I not only lose
the text console on the screen (the display shows blank, backlight is off), but
also kernel does not probe modes for the HDMI connector again.

But HDMI1 does probe modes again for hot re-plugging. So, HDMI1 does not hit the
issue like HDMI0.

* System probes modes only once for HDMI0 port (HDMI-A-1), even hot re-plug HDMI
  cable to the same port:

[   15.611072] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:32:HDMI-A-1] probed modes :
[   15.611079] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[   15.611085] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[   15.611298] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[   15.611303] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2]
[   15.612184] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] disconnected
[   15.612191] [drm:drm_client_modeset_probe] connector 32 enabled? yes
[   15.612194] [drm:drm_client_modeset_probe] connector 38 enabled? no
[   15.612206] [drm:drm_client_modeset_probe] Not using firmware configuration
[   15.612213] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 32
[   15.612218] [drm:drm_client_modeset_probe] looking for preferred mode on connector 32 0
[   15.612221] [drm:drm_client_modeset_probe] found mode 1920x1080
...
[  108.263384] [drm:output_poll_execute] [CONNECTOR:32:HDMI-A-1] status updated from disconnected to connected
[  108.264307] vc4-drm gpu: [drm:drm_fb_helper_hotplug_event.part.0] 
[  108.264312] [drm:drm_client_modeset_probe] 
[  108.264321] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:32:HDMI-A-1]
[  109.303379] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2]
[  109.304258] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] disconnected
[  109.304266] [drm:drm_client_modeset_probe] No connectors reported connected with modes

* System probes modes again for HDMI1 port (HDMI-A-2), whenever hot re-plug the
  HDMI cable:

[  797.974649] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] probed modes :
[  797.974656] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  797.974662] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[  797.974874] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  797.974880] [drm:drm_client_modeset_probe] connector 32 enabled? no
[  797.974883] [drm:drm_client_modeset_probe] connector 38 enabled? yes
[  797.974895] [drm:drm_client_modeset_probe] Not using firmware configuration
[  797.974901] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 38
[  797.974905] [drm:drm_client_modeset_probe] looking for preferred mode on connector 38 0
[  797.974908] [drm:drm_client_modeset_probe] found mode 1920x1080
...
[  852.242615] vc4-drm gpu: [drm:drm_client_dev_hotplug] fbdev: ret=0
[  873.718277] [drm:output_poll_execute] [CONNECTOR:38:HDMI-A-2] status updated from disconnected to connected
[  873.718332] vc4-drm gpu: [drm:drm_fb_helper_hotplug_event.part.0] 
[  873.718338] [drm:drm_client_modeset_probe]
...
[  874.264013] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] probed modes :
[  874.264020] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  874.264026] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[  874.264239] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  874.264244] [drm:drm_client_modeset_probe] connector 32 enabled? no
[  874.264247] [drm:drm_client_modeset_probe] connector 38 enabled? yes
[  874.264259] [drm:drm_client_modeset_probe] Not using firmware configuration
[  874.264264] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 38
[  874.264268] [drm:drm_client_modeset_probe] looking for preferred mode on connector 38 0
[  874.264272] [drm:drm_client_modeset_probe] found mode 1920x1080

Here is the full dmesg: https://gist.github.com/starnight/5ffb86af552fedb9b6e5741d0540a878#file-dmesg-v4-log

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-10  7:37     ` Jian-Hong Pan
  0 siblings, 0 replies; 432+ messages in thread
From: Jian-Hong Pan @ 2020-07-10  7:37 UTC (permalink / raw)
  To: maxime
  Cc: devicetree, tim.gover, kdasu.kdev, sboyd, mturquette,
	dave.stevenson, linux-kernel, dri-devel, phil, eric, robh+dt,
	bcm-kernel-feedback-list, linux-rpi-kernel, nsaenzjulienne,
	linux, linux-clk, linux-arm-kernel

Hi Maxime,

Thanks for your version 4 patch again.
I took the patches and applied them upon next-20200708.

I make system cold reboot to multi-user target and the text console shows on the
screen. Then, I simply hot re-plug the HDMI cable on HDMI0 port, I not only lose
the text console on the screen (the display shows blank, backlight is off), but
also kernel does not probe modes for the HDMI connector again.

But HDMI1 does probe modes again for hot re-plugging. So, HDMI1 does not hit the
issue like HDMI0.

* System probes modes only once for HDMI0 port (HDMI-A-1), even hot re-plug HDMI
  cable to the same port:

[   15.611072] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:32:HDMI-A-1] probed modes :
[   15.611079] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[   15.611085] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[   15.611298] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[   15.611303] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2]
[   15.612184] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] disconnected
[   15.612191] [drm:drm_client_modeset_probe] connector 32 enabled? yes
[   15.612194] [drm:drm_client_modeset_probe] connector 38 enabled? no
[   15.612206] [drm:drm_client_modeset_probe] Not using firmware configuration
[   15.612213] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 32
[   15.612218] [drm:drm_client_modeset_probe] looking for preferred mode on connector 32 0
[   15.612221] [drm:drm_client_modeset_probe] found mode 1920x1080
...
[  108.263384] [drm:output_poll_execute] [CONNECTOR:32:HDMI-A-1] status updated from disconnected to connected
[  108.264307] vc4-drm gpu: [drm:drm_fb_helper_hotplug_event.part.0] 
[  108.264312] [drm:drm_client_modeset_probe] 
[  108.264321] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:32:HDMI-A-1]
[  109.303379] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2]
[  109.304258] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] disconnected
[  109.304266] [drm:drm_client_modeset_probe] No connectors reported connected with modes

* System probes modes again for HDMI1 port (HDMI-A-2), whenever hot re-plug the
  HDMI cable:

[  797.974649] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] probed modes :
[  797.974656] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  797.974662] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[  797.974874] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  797.974880] [drm:drm_client_modeset_probe] connector 32 enabled? no
[  797.974883] [drm:drm_client_modeset_probe] connector 38 enabled? yes
[  797.974895] [drm:drm_client_modeset_probe] Not using firmware configuration
[  797.974901] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 38
[  797.974905] [drm:drm_client_modeset_probe] looking for preferred mode on connector 38 0
[  797.974908] [drm:drm_client_modeset_probe] found mode 1920x1080
...
[  852.242615] vc4-drm gpu: [drm:drm_client_dev_hotplug] fbdev: ret=0
[  873.718277] [drm:output_poll_execute] [CONNECTOR:38:HDMI-A-2] status updated from disconnected to connected
[  873.718332] vc4-drm gpu: [drm:drm_fb_helper_hotplug_event.part.0] 
[  873.718338] [drm:drm_client_modeset_probe]
...
[  874.264013] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] probed modes :
[  874.264020] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  874.264026] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[  874.264239] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  874.264244] [drm:drm_client_modeset_probe] connector 32 enabled? no
[  874.264247] [drm:drm_client_modeset_probe] connector 38 enabled? yes
[  874.264259] [drm:drm_client_modeset_probe] Not using firmware configuration
[  874.264264] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 38
[  874.264268] [drm:drm_client_modeset_probe] looking for preferred mode on connector 38 0
[  874.264272] [drm:drm_client_modeset_probe] found mode 1920x1080

Here is the full dmesg: https://gist.github.com/starnight/5ffb86af552fedb9b6e5741d0540a878#file-dmesg-v4-log

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-10  7:37     ` Jian-Hong Pan
  0 siblings, 0 replies; 432+ messages in thread
From: Jian-Hong Pan @ 2020-07-10  7:37 UTC (permalink / raw)
  To: maxime
  Cc: devicetree, tim.gover, kdasu.kdev, sboyd, mturquette,
	dave.stevenson, linux-kernel, dri-devel, phil, robh+dt,
	bcm-kernel-feedback-list, linux-rpi-kernel, nsaenzjulienne,
	linux, linux-clk, linux-arm-kernel

Hi Maxime,

Thanks for your version 4 patch again.
I took the patches and applied them upon next-20200708.

I make system cold reboot to multi-user target and the text console shows on the
screen. Then, I simply hot re-plug the HDMI cable on HDMI0 port, I not only lose
the text console on the screen (the display shows blank, backlight is off), but
also kernel does not probe modes for the HDMI connector again.

But HDMI1 does probe modes again for hot re-plugging. So, HDMI1 does not hit the
issue like HDMI0.

* System probes modes only once for HDMI0 port (HDMI-A-1), even hot re-plug HDMI
  cable to the same port:

[   15.611072] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:32:HDMI-A-1] probed modes :
[   15.611079] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[   15.611085] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[   15.611298] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[   15.611303] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2]
[   15.612184] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] disconnected
[   15.612191] [drm:drm_client_modeset_probe] connector 32 enabled? yes
[   15.612194] [drm:drm_client_modeset_probe] connector 38 enabled? no
[   15.612206] [drm:drm_client_modeset_probe] Not using firmware configuration
[   15.612213] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 32
[   15.612218] [drm:drm_client_modeset_probe] looking for preferred mode on connector 32 0
[   15.612221] [drm:drm_client_modeset_probe] found mode 1920x1080
...
[  108.263384] [drm:output_poll_execute] [CONNECTOR:32:HDMI-A-1] status updated from disconnected to connected
[  108.264307] vc4-drm gpu: [drm:drm_fb_helper_hotplug_event.part.0] 
[  108.264312] [drm:drm_client_modeset_probe] 
[  108.264321] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:32:HDMI-A-1]
[  109.303379] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2]
[  109.304258] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] disconnected
[  109.304266] [drm:drm_client_modeset_probe] No connectors reported connected with modes

* System probes modes again for HDMI1 port (HDMI-A-2), whenever hot re-plug the
  HDMI cable:

[  797.974649] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] probed modes :
[  797.974656] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  797.974662] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[  797.974874] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  797.974880] [drm:drm_client_modeset_probe] connector 32 enabled? no
[  797.974883] [drm:drm_client_modeset_probe] connector 38 enabled? yes
[  797.974895] [drm:drm_client_modeset_probe] Not using firmware configuration
[  797.974901] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 38
[  797.974905] [drm:drm_client_modeset_probe] looking for preferred mode on connector 38 0
[  797.974908] [drm:drm_client_modeset_probe] found mode 1920x1080
...
[  852.242615] vc4-drm gpu: [drm:drm_client_dev_hotplug] fbdev: ret=0
[  873.718277] [drm:output_poll_execute] [CONNECTOR:38:HDMI-A-2] status updated from disconnected to connected
[  873.718332] vc4-drm gpu: [drm:drm_fb_helper_hotplug_event.part.0] 
[  873.718338] [drm:drm_client_modeset_probe]
...
[  874.264013] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-2] probed modes :
[  874.264020] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  874.264026] [drm:drm_mode_debug_printmodeline] Modeline "1920x1080": 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x40 0x5
...
[  874.264239] [drm:drm_mode_debug_printmodeline] Modeline "720x400": 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  874.264244] [drm:drm_client_modeset_probe] connector 32 enabled? no
[  874.264247] [drm:drm_client_modeset_probe] connector 38 enabled? yes
[  874.264259] [drm:drm_client_modeset_probe] Not using firmware configuration
[  874.264264] [drm:drm_client_modeset_probe] looking for cmdline mode on connector 38
[  874.264268] [drm:drm_client_modeset_probe] looking for preferred mode on connector 38 0
[  874.264272] [drm:drm_client_modeset_probe] found mode 1920x1080

Here is the full dmesg: https://gist.github.com/starnight/5ffb86af552fedb9b6e5741d0540a878#file-dmesg-v4-log
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-07-10  9:58     ` Stefan Wahren
  -1 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-07-10  9:58 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
	Michael Turquette, Kamal Dasu, linux-kernel, dri-devel,
	linux-clk, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Philipp Zabel, Phil Elwell, linux-arm-kernel

Hi Maxime,

Am 08.07.20 um 19:41 schrieb Maxime Ripard:
> Hi everyone,
>
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
>
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
>
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
>
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
>
> Let me know if you have any comments
> Maxime
>
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
>
> Changes from v3:
>   - Rebased on top of next-20200708
>   - Added a name to the HDMI audio codec component
>   - Only disable the BCM2711 HDMI pixelvalves at boot
>   - Fixed an error in the HVS binding
>   - Fix a framebuffer size condition that was inverted
>   - Changed the channel allocation algorithm using Eric's suggestion
>   - Always write the muxing values instead of updating if needed
>   - Improved a bit the hvs_available_channels comment in the structure
>   - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>   - Change the muxing code to take into account disparities between the
>     BCM2711 and previous SoCs.
>   - Only change the clock rate on BCM2711 during a modeset
>   - Fix a crash at atomic_disable
>   - Use clk_set_min_rate for the core clock too
>   - Add a few defines, and simplify the FIFO level stuff
>   - Reordered the patches according to Eric's reviews
>   - Fixed a regression with VID_CTL setting on RPI3
>
i additionally applied "drm/vc4/vc4_hdmi: fill ASoC card owner" on top
of your series (potential merge conflict).

I didn't see any issues with a RPI 3B or RPI 4B.

So this whole series is

Tested-by: Stefan Wahren <stefan.wahren@i2se.com>

Regards
Stefan


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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-10  9:58     ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-07-10  9:58 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Kamal Dasu, Stephen Boyd,
	Michael Turquette, Dave Stevenson, linux-kernel, dri-devel,
	Phil Elwell, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Philipp Zabel, linux-clk, linux-arm-kernel

Hi Maxime,

Am 08.07.20 um 19:41 schrieb Maxime Ripard:
> Hi everyone,
>
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
>
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
>
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
>
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
>
> Let me know if you have any comments
> Maxime
>
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
>
> Changes from v3:
>   - Rebased on top of next-20200708
>   - Added a name to the HDMI audio codec component
>   - Only disable the BCM2711 HDMI pixelvalves at boot
>   - Fixed an error in the HVS binding
>   - Fix a framebuffer size condition that was inverted
>   - Changed the channel allocation algorithm using Eric's suggestion
>   - Always write the muxing values instead of updating if needed
>   - Improved a bit the hvs_available_channels comment in the structure
>   - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>   - Change the muxing code to take into account disparities between the
>     BCM2711 and previous SoCs.
>   - Only change the clock rate on BCM2711 during a modeset
>   - Fix a crash at atomic_disable
>   - Use clk_set_min_rate for the core clock too
>   - Add a few defines, and simplify the FIFO level stuff
>   - Reordered the patches according to Eric's reviews
>   - Fixed a regression with VID_CTL setting on RPI3
>
i additionally applied "drm/vc4/vc4_hdmi: fill ASoC card owner" on top
of your series (potential merge conflict).

I didn't see any issues with a RPI 3B or RPI 4B.

So this whole series is

Tested-by: Stefan Wahren <stefan.wahren@i2se.com>

Regards
Stefan


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-07-10  9:58     ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-07-10  9:58 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Kamal Dasu, Stephen Boyd,
	Michael Turquette, Dave Stevenson, linux-kernel, dri-devel,
	Phil Elwell, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, linux-clk, linux-arm-kernel

Hi Maxime,

Am 08.07.20 um 19:41 schrieb Maxime Ripard:
> Hi everyone,
>
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
>
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
>
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
>
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
>
> Let me know if you have any comments
> Maxime
>
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
>
> Changes from v3:
>   - Rebased on top of next-20200708
>   - Added a name to the HDMI audio codec component
>   - Only disable the BCM2711 HDMI pixelvalves at boot
>   - Fixed an error in the HVS binding
>   - Fix a framebuffer size condition that was inverted
>   - Changed the channel allocation algorithm using Eric's suggestion
>   - Always write the muxing values instead of updating if needed
>   - Improved a bit the hvs_available_channels comment in the structure
>   - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>   - Change the muxing code to take into account disparities between the
>     BCM2711 and previous SoCs.
>   - Only change the clock rate on BCM2711 during a modeset
>   - Fix a crash at atomic_disable
>   - Use clk_set_min_rate for the core clock too
>   - Add a few defines, and simplify the FIFO level stuff
>   - Reordered the patches according to Eric's reviews
>   - Fixed a regression with VID_CTL setting on RPI3
>
i additionally applied "drm/vc4/vc4_hdmi: fill ASoC card owner" on top
of your series (potential merge conflict).

I didn't see any issues with a RPI 3B or RPI 4B.

So this whole series is

Tested-by: Stefan Wahren <stefan.wahren@i2se.com>

Regards
Stefan

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

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

* Re: [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28  9:48       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with
> pixelvalves each being assigned to a given output, but each output can
> then be muxed to feed from multiple FIFOs.
>
> Since vc4 had that entirely static, both were probably equivalent, but
> since that changes, let's rename hvs_channel to hvs_output in the
> vc4_crtc_data, since a pixelvalve is really connected to an output, and
> not to a FIFO.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
>  drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 2 +-
>  drivers/gpu/drm/vc4/vc4_txp.c  | 2 +-
>  4 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index fdecaba77836..d3126fe04d9a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
>         .base = {
> -               .hvs_channel = 0,
> +               .hvs_output = 0,
>         },
>         .debugfs_name = "crtc0_regs",
>         .pixels_per_clock = 1,
> @@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
>         .base = {
> -               .hvs_channel = 2,
> +               .hvs_output = 2,
>         },
>         .debugfs_name = "crtc1_regs",
>         .pixels_per_clock = 1,
> @@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
>         .base = {
> -               .hvs_channel = 1,
> +               .hvs_output = 1,
>         },
>         .debugfs_name = "crtc2_regs",
>         .pixels_per_clock = 1,
> @@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
>                                   crtc_funcs, NULL);
>         drm_crtc_helper_add(crtc, crtc_helper_funcs);
> -       vc4_crtc->channel = vc4_crtc->data->hvs_channel;
> +       vc4_crtc->channel = vc4_crtc->data->hvs_output;
>         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
>         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index d80fc3bbb450..d1cf4c038180 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_crtc_data {
> -       /* Which channel of the HVS this pixelvalve sources from. */
> -       int hvs_channel;
> +       /* Which output of the HVS this pixelvalve sources from. */
> +       int hvs_output;
>  };
>
>  struct vc4_pv_data {
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 091fdf4908aa..6fd9de1dc65a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
>
> -       if (vc4_crtc->data->hvs_channel == 2) {
> +       if (vc4_crtc->data->hvs_output == 2) {
>                 u32 dispctrl;
>                 u32 dsp3_mux;
>
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index a7c3af0005a0..f39d9900d027 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>  }
>
>  static const struct vc4_crtc_data vc4_txp_crtc_data = {
> -       .hvs_channel = 2,
> +       .hvs_output = 2,
>  };
>
>  static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
> --
> git-series 0.9.1

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

* Re: [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output
@ 2020-07-28  9:48       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with
> pixelvalves each being assigned to a given output, but each output can
> then be muxed to feed from multiple FIFOs.
>
> Since vc4 had that entirely static, both were probably equivalent, but
> since that changes, let's rename hvs_channel to hvs_output in the
> vc4_crtc_data, since a pixelvalve is really connected to an output, and
> not to a FIFO.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
>  drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 2 +-
>  drivers/gpu/drm/vc4/vc4_txp.c  | 2 +-
>  4 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index fdecaba77836..d3126fe04d9a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
>         .base = {
> -               .hvs_channel = 0,
> +               .hvs_output = 0,
>         },
>         .debugfs_name = "crtc0_regs",
>         .pixels_per_clock = 1,
> @@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
>         .base = {
> -               .hvs_channel = 2,
> +               .hvs_output = 2,
>         },
>         .debugfs_name = "crtc1_regs",
>         .pixels_per_clock = 1,
> @@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
>         .base = {
> -               .hvs_channel = 1,
> +               .hvs_output = 1,
>         },
>         .debugfs_name = "crtc2_regs",
>         .pixels_per_clock = 1,
> @@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
>                                   crtc_funcs, NULL);
>         drm_crtc_helper_add(crtc, crtc_helper_funcs);
> -       vc4_crtc->channel = vc4_crtc->data->hvs_channel;
> +       vc4_crtc->channel = vc4_crtc->data->hvs_output;
>         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
>         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index d80fc3bbb450..d1cf4c038180 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_crtc_data {
> -       /* Which channel of the HVS this pixelvalve sources from. */
> -       int hvs_channel;
> +       /* Which output of the HVS this pixelvalve sources from. */
> +       int hvs_output;
>  };
>
>  struct vc4_pv_data {
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 091fdf4908aa..6fd9de1dc65a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
>
> -       if (vc4_crtc->data->hvs_channel == 2) {
> +       if (vc4_crtc->data->hvs_output == 2) {
>                 u32 dispctrl;
>                 u32 dsp3_mux;
>
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index a7c3af0005a0..f39d9900d027 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>  }
>
>  static const struct vc4_crtc_data vc4_txp_crtc_data = {
> -       .hvs_channel = 2,
> +       .hvs_output = 2,
>  };
>
>  static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output
@ 2020-07-28  9:48       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In vc5, the HVS has 6 outputs and 3 FIFOs (or channels), with
> pixelvalves each being assigned to a given output, but each output can
> then be muxed to feed from multiple FIFOs.
>
> Since vc4 had that entirely static, both were probably equivalent, but
> since that changes, let's rename hvs_channel to hvs_output in the
> vc4_crtc_data, since a pixelvalve is really connected to an output, and
> not to a FIFO.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
>  drivers/gpu/drm/vc4/vc4_drv.h  | 4 ++--
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 2 +-
>  drivers/gpu/drm/vc4/vc4_txp.c  | 2 +-
>  4 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index fdecaba77836..d3126fe04d9a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -775,7 +775,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
>         .base = {
> -               .hvs_channel = 0,
> +               .hvs_output = 0,
>         },
>         .debugfs_name = "crtc0_regs",
>         .pixels_per_clock = 1,
> @@ -787,7 +787,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
>         .base = {
> -               .hvs_channel = 2,
> +               .hvs_output = 2,
>         },
>         .debugfs_name = "crtc1_regs",
>         .pixels_per_clock = 1,
> @@ -799,7 +799,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
>         .base = {
> -               .hvs_channel = 1,
> +               .hvs_output = 1,
>         },
>         .debugfs_name = "crtc2_regs",
>         .pixels_per_clock = 1,
> @@ -862,7 +862,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
>                                   crtc_funcs, NULL);
>         drm_crtc_helper_add(crtc, crtc_helper_funcs);
> -       vc4_crtc->channel = vc4_crtc->data->hvs_channel;
> +       vc4_crtc->channel = vc4_crtc->data->hvs_output;
>         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
>         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index d80fc3bbb450..d1cf4c038180 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -447,8 +447,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_crtc_data {
> -       /* Which channel of the HVS this pixelvalve sources from. */
> -       int hvs_channel;
> +       /* Which output of the HVS this pixelvalve sources from. */
> +       int hvs_output;
>  };
>
>  struct vc4_pv_data {
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 091fdf4908aa..6fd9de1dc65a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -419,7 +419,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
>
> -       if (vc4_crtc->data->hvs_channel == 2) {
> +       if (vc4_crtc->data->hvs_output == 2) {
>                 u32 dispctrl;
>                 u32 dsp3_mux;
>
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index a7c3af0005a0..f39d9900d027 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -452,7 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>  }
>
>  static const struct vc4_crtc_data vc4_txp_crtc_data = {
> -       .hvs_channel = 2,
> +       .hvs_output = 2,
>  };
>
>  static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28  9:50       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:50 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4_crtc_handle_page_flip already has a local variable holding the
> value of vc4_crtc->channel, so let's use it instead.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d3126fe04d9a..cdeaa0cd981f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
>                  * the CRTC and encoder already reconfigured, leading to
>                  * underruns. This can be seen when reconfiguring the CRTC.
>                  */
> -               vc4_hvs_unmask_underrun(dev, vc4_crtc->channel);
> +               vc4_hvs_unmask_underrun(dev, chan);
>         }
>         spin_unlock_irqrestore(&dev->event_lock, flags);
>  }
> --
> git-series 0.9.1

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

* Re: [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable
@ 2020-07-28  9:50       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:50 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4_crtc_handle_page_flip already has a local variable holding the
> value of vc4_crtc->channel, so let's use it instead.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d3126fe04d9a..cdeaa0cd981f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
>                  * the CRTC and encoder already reconfigured, leading to
>                  * underruns. This can be seen when reconfiguring the CRTC.
>                  */
> -               vc4_hvs_unmask_underrun(dev, vc4_crtc->channel);
> +               vc4_hvs_unmask_underrun(dev, chan);
>         }
>         spin_unlock_irqrestore(&dev->event_lock, flags);
>  }
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable
@ 2020-07-28  9:50       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:50 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4_crtc_handle_page_flip already has a local variable holding the
> value of vc4_crtc->channel, so let's use it instead.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d3126fe04d9a..cdeaa0cd981f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -533,7 +533,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
>                  * the CRTC and encoder already reconfigured, leading to
>                  * underruns. This can be seen when reconfiguring the CRTC.
>                  */
> -               vc4_hvs_unmask_underrun(dev, vc4_crtc->channel);
> +               vc4_hvs_unmask_underrun(dev, chan);
>         }
>         spin_unlock_irqrestore(&dev->event_lock, flags);
>  }
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28  9:57       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The VIDEN bit in the pixelvalve currently being used to enable or disable
> the pixelvalve seems to not be enough in some situations, which whill end
> up with the pixelvalve stalling.
>
> In such a case, even re-enabling VIDEN doesn't bring it back and we need to
> clear the FIFO. This can only be done if the pixelvalve is disabled though.
>
> In order to overcome this, we can configure the pixelvalve during
> mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
> there, and in atomic_disable disable the pixelvalve again.

Very minor nitpick: the configure is in vc4_crtc_config_pv, but that
is called from mode_set_no_fb. The comment is correct from a DRM
overview perspective, but not from the actual code. Describing the DRM
call is probably the better approach, but it looks odd when compared
to the code.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index cdeaa0cd981f..fe2e5675aed4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                    PV_CONTROL_TRIGGER_UNDERFLOW |
>                    PV_CONTROL_WAIT_HSTART |
>                    VC4_SET_FIELD(vc4_encoder->clock_select,
> -                                PV_CONTROL_CLK_SELECT) |
> -                  PV_CONTROL_FIFO_CLR |
> -                  PV_CONTROL_EN);
> +                                PV_CONTROL_CLK_SELECT));
>  }
>
>  static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> @@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
> +
>         vc4_hvs_atomic_disable(crtc, old_state);
>
>         /*
> @@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> +       /* Reset the PV fifo. */
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
> +                  PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
> +
>         /* Enable vblank irq handling before crtc is started otherwise
>          * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
>          */
> --
> git-series 0.9.1

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

* Re: [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
@ 2020-07-28  9:57       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The VIDEN bit in the pixelvalve currently being used to enable or disable
> the pixelvalve seems to not be enough in some situations, which whill end
> up with the pixelvalve stalling.
>
> In such a case, even re-enabling VIDEN doesn't bring it back and we need to
> clear the FIFO. This can only be done if the pixelvalve is disabled though.
>
> In order to overcome this, we can configure the pixelvalve during
> mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
> there, and in atomic_disable disable the pixelvalve again.

Very minor nitpick: the configure is in vc4_crtc_config_pv, but that
is called from mode_set_no_fb. The comment is correct from a DRM
overview perspective, but not from the actual code. Describing the DRM
call is probably the better approach, but it looks odd when compared
to the code.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index cdeaa0cd981f..fe2e5675aed4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                    PV_CONTROL_TRIGGER_UNDERFLOW |
>                    PV_CONTROL_WAIT_HSTART |
>                    VC4_SET_FIELD(vc4_encoder->clock_select,
> -                                PV_CONTROL_CLK_SELECT) |
> -                  PV_CONTROL_FIFO_CLR |
> -                  PV_CONTROL_EN);
> +                                PV_CONTROL_CLK_SELECT));
>  }
>
>  static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> @@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
> +
>         vc4_hvs_atomic_disable(crtc, old_state);
>
>         /*
> @@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> +       /* Reset the PV fifo. */
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
> +                  PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
> +
>         /* Enable vblank irq handling before crtc is started otherwise
>          * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
>          */
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
@ 2020-07-28  9:57       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28  9:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The VIDEN bit in the pixelvalve currently being used to enable or disable
> the pixelvalve seems to not be enough in some situations, which whill end
> up with the pixelvalve stalling.
>
> In such a case, even re-enabling VIDEN doesn't bring it back and we need to
> clear the FIFO. This can only be done if the pixelvalve is disabled though.
>
> In order to overcome this, we can configure the pixelvalve during
> mode_set_no_fb, but only enable it in atomic_enable and flush the FIFO
> there, and in atomic_disable disable the pixelvalve again.

Very minor nitpick: the configure is in vc4_crtc_config_pv, but that
is called from mode_set_no_fb. The comment is correct from a DRM
overview perspective, but not from the actual code. Describing the DRM
call is probably the better approach, but it looks odd when compared
to the code.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index cdeaa0cd981f..fe2e5675aed4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -332,9 +332,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                    PV_CONTROL_TRIGGER_UNDERFLOW |
>                    PV_CONTROL_WAIT_HSTART |
>                    VC4_SET_FIELD(vc4_encoder->clock_select,
> -                                PV_CONTROL_CLK_SELECT) |
> -                  PV_CONTROL_FIFO_CLR |
> -                  PV_CONTROL_EN);
> +                                PV_CONTROL_CLK_SELECT));
>  }
>
>  static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> @@ -386,6 +384,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
> +
>         vc4_hvs_atomic_disable(crtc, old_state);
>
>         /*
> @@ -410,6 +410,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> +       /* Reset the PV fifo. */
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) |
> +                  PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
> +
>         /* Enable vblank irq handling before crtc is started otherwise
>          * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
>          */
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 10:30       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't
> really make much sense to dump its register content in its caller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++--------------
>  1 file changed, 12 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index c2ab907611e3..181d3fd57bc7 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                        vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
>         u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
>         u8 ppc = pv_data->pixels_per_clock;
> +       bool debug_dump_regs = false;
> +
> +       if (debug_dump_regs) {
> +               struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> +               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
> +                        drm_crtc_index(crtc));
> +               drm_print_regset32(&p, &vc4_crtc->regset);
> +       }
>
>         vc4_crtc_pixelvalve_reset(crtc);
>
> @@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                    PV_CONTROL_WAIT_HSTART |
>                    VC4_SET_FIELD(vc4_encoder->clock_select,
>                                  PV_CONTROL_CLK_SELECT));
> -}
> -
> -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> -       bool debug_dump_regs = false;
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> -               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
> +               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
>                          drm_crtc_index(crtc));
>                 drm_print_regset32(&p, &vc4_crtc->regset);
>         }
> +}
>
> +static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
>         vc4_crtc_config_pv(crtc);
>
>         vc4_hvs_mode_set_nofb(crtc);
> -
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> -               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
> -                        drm_crtc_index(crtc));
> -               drm_print_regset32(&p, &vc4_crtc->regset);
> -       }
>  }
>
>  static void require_hvs_enabled(struct drm_device *dev)
> --
> git-series 0.9.1

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

* Re: [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv
@ 2020-07-28 10:30       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't
> really make much sense to dump its register content in its caller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++--------------
>  1 file changed, 12 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index c2ab907611e3..181d3fd57bc7 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                        vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
>         u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
>         u8 ppc = pv_data->pixels_per_clock;
> +       bool debug_dump_regs = false;
> +
> +       if (debug_dump_regs) {
> +               struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> +               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
> +                        drm_crtc_index(crtc));
> +               drm_print_regset32(&p, &vc4_crtc->regset);
> +       }
>
>         vc4_crtc_pixelvalve_reset(crtc);
>
> @@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                    PV_CONTROL_WAIT_HSTART |
>                    VC4_SET_FIELD(vc4_encoder->clock_select,
>                                  PV_CONTROL_CLK_SELECT));
> -}
> -
> -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> -       bool debug_dump_regs = false;
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> -               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
> +               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
>                          drm_crtc_index(crtc));
>                 drm_print_regset32(&p, &vc4_crtc->regset);
>         }
> +}
>
> +static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
>         vc4_crtc_config_pv(crtc);
>
>         vc4_hvs_mode_set_nofb(crtc);
> -
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> -               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
> -                        drm_crtc_index(crtc));
> -               drm_print_regset32(&p, &vc4_crtc->regset);
> -       }
>  }
>
>  static void require_hvs_enabled(struct drm_device *dev)
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv
@ 2020-07-28 10:30       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that we only configure the PixelValve in vc4_crtc_config_pv, it doesn't
> really make much sense to dump its register content in its caller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 26 ++++++++++++--------------
>  1 file changed, 12 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index c2ab907611e3..181d3fd57bc7 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -290,6 +290,14 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                        vc4_encoder->type == VC4_ENCODER_TYPE_DSI1);
>         u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24;
>         u8 ppc = pv_data->pixels_per_clock;
> +       bool debug_dump_regs = false;
> +
> +       if (debug_dump_regs) {
> +               struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> +               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
> +                        drm_crtc_index(crtc));
> +               drm_print_regset32(&p, &vc4_crtc->regset);
> +       }
>
>         vc4_crtc_pixelvalve_reset(crtc);
>
> @@ -359,30 +367,20 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>                    PV_CONTROL_WAIT_HSTART |
>                    VC4_SET_FIELD(vc4_encoder->clock_select,
>                                  PV_CONTROL_CLK_SELECT));
> -}
> -
> -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> -       bool debug_dump_regs = false;
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> -               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs before:\n",
> +               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
>                          drm_crtc_index(crtc));
>                 drm_print_regset32(&p, &vc4_crtc->regset);
>         }
> +}
>
> +static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
>         vc4_crtc_config_pv(crtc);
>
>         vc4_hvs_mode_set_nofb(crtc);
> -
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_crtc->pdev->dev);
> -               dev_info(&vc4_crtc->pdev->dev, "CRTC %d regs after:\n",
> -                        drm_crtc_index(crtc));
> -               drm_print_regset32(&p, &vc4_crtc->regset);
> -       }
>  }
>
>  static void require_hvs_enabled(struct drm_device *dev)
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 10:31       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to make further refactoring easier, let's move the HVS channel
> setup / teardown to their own function.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++----------------
>  1 file changed, 58 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 50f9a9674a7e..78bb1c0b0b76 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
>         vc4_hvs_lut_load(crtc);
>  }
>
> +static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
> +                               struct drm_display_mode *mode, bool oneshot)
> +{
> +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
> +       unsigned int chan = vc4_crtc_state->assigned_channel;
> +       u32 dispctrl;
> +
> +       /* Turn on the scaler, which will wait for vstart to start
> +        * compositing.
> +        * When feeding the transposer, we should operate in oneshot
> +        * mode.
> +        */
> +       dispctrl = SCALER_DISPCTRLX_ENABLE;
> +
> +       if (!vc4->hvs->hvs5)
> +               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> +                                         SCALER_DISPCTRLX_WIDTH) |
> +                           VC4_SET_FIELD(mode->vdisplay,
> +                                         SCALER_DISPCTRLX_HEIGHT) |
> +                           (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
> +       else
> +               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> +                                         SCALER5_DISPCTRLX_WIDTH) |
> +                           VC4_SET_FIELD(mode->vdisplay,
> +                                         SCALER5_DISPCTRLX_HEIGHT) |
> +                           (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
> +
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
> +
> +       return 0;
> +}
> +
> +static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
> +{
> +       struct vc4_dev *vc4 = to_vc4_dev(dev);
> +
> +       if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
> +               return;
> +
> +       HVS_WRITE(SCALER_DISPCTRLX(chan),
> +                 HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan),
> +                 HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
> +
> +       /* Once we leave, the scaler should be disabled and its fifo empty. */
> +       WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
> +
> +       WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
> +                                  SCALER_DISPSTATX_MODE) !=
> +                    SCALER_DISPSTATX_MODE_DISABLED);
> +
> +       WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
> +                     (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
> +                    SCALER_DISPSTATX_EMPTY);
> +}
> +
>  int vc4_hvs_atomic_check(struct drm_crtc *crtc,
>                          struct drm_crtc_state *state)
>  {
> @@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool oneshot = vc4_state->feed_txp;
> -       u32 dispctrl;
>
>         vc4_hvs_update_dlist(crtc);
> -
> -       /* Turn on the scaler, which will wait for vstart to start
> -        * compositing.
> -        * When feeding the transposer, we should operate in oneshot
> -        * mode.
> -        */
> -       dispctrl = SCALER_DISPCTRLX_ENABLE;
> -
> -       if (!vc4->hvs->hvs5)
> -               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> -                                         SCALER_DISPCTRLX_WIDTH) |
> -                           VC4_SET_FIELD(mode->vdisplay,
> -                                         SCALER_DISPCTRLX_HEIGHT) |
> -                           (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
> -       else
> -               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> -                                         SCALER5_DISPCTRLX_WIDTH) |
> -                           VC4_SET_FIELD(mode->vdisplay,
> -                                         SCALER5_DISPCTRLX_HEIGHT) |
> -                           (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
> -
> -       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
> +       vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
>  }
>
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
>                             struct drm_crtc_state *old_state)
>  {
>         struct drm_device *dev = crtc->dev;
> -       struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
>         unsigned int chan = vc4_state->assigned_channel;
>
> -       if (HVS_READ(SCALER_DISPCTRLX(chan)) &
> -           SCALER_DISPCTRLX_ENABLE) {
> -               HVS_WRITE(SCALER_DISPCTRLX(chan),
> -                         SCALER_DISPCTRLX_RESET);
> -
> -               /* While the docs say that reset is self-clearing, it
> -                * seems it doesn't actually.
> -                */
> -               HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> -       }
> -
> -       /* Once we leave, the scaler should be disabled and its fifo empty. */
> -
> -       WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
> -
> -       WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
> -                                  SCALER_DISPSTATX_MODE) !=
> -                    SCALER_DISPSTATX_MODE_DISABLED);
> -
> -       WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
> -                     (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
> -                    SCALER_DISPSTATX_EMPTY);
> +       vc4_hvs_stop_channel(dev, chan);
>  }
>
>  void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
> --
> git-series 0.9.1

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

* Re: [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function
@ 2020-07-28 10:31       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to make further refactoring easier, let's move the HVS channel
> setup / teardown to their own function.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++----------------
>  1 file changed, 58 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 50f9a9674a7e..78bb1c0b0b76 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
>         vc4_hvs_lut_load(crtc);
>  }
>
> +static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
> +                               struct drm_display_mode *mode, bool oneshot)
> +{
> +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
> +       unsigned int chan = vc4_crtc_state->assigned_channel;
> +       u32 dispctrl;
> +
> +       /* Turn on the scaler, which will wait for vstart to start
> +        * compositing.
> +        * When feeding the transposer, we should operate in oneshot
> +        * mode.
> +        */
> +       dispctrl = SCALER_DISPCTRLX_ENABLE;
> +
> +       if (!vc4->hvs->hvs5)
> +               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> +                                         SCALER_DISPCTRLX_WIDTH) |
> +                           VC4_SET_FIELD(mode->vdisplay,
> +                                         SCALER_DISPCTRLX_HEIGHT) |
> +                           (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
> +       else
> +               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> +                                         SCALER5_DISPCTRLX_WIDTH) |
> +                           VC4_SET_FIELD(mode->vdisplay,
> +                                         SCALER5_DISPCTRLX_HEIGHT) |
> +                           (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
> +
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
> +
> +       return 0;
> +}
> +
> +static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
> +{
> +       struct vc4_dev *vc4 = to_vc4_dev(dev);
> +
> +       if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
> +               return;
> +
> +       HVS_WRITE(SCALER_DISPCTRLX(chan),
> +                 HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan),
> +                 HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
> +
> +       /* Once we leave, the scaler should be disabled and its fifo empty. */
> +       WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
> +
> +       WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
> +                                  SCALER_DISPSTATX_MODE) !=
> +                    SCALER_DISPSTATX_MODE_DISABLED);
> +
> +       WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
> +                     (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
> +                    SCALER_DISPSTATX_EMPTY);
> +}
> +
>  int vc4_hvs_atomic_check(struct drm_crtc *crtc,
>                          struct drm_crtc_state *state)
>  {
> @@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool oneshot = vc4_state->feed_txp;
> -       u32 dispctrl;
>
>         vc4_hvs_update_dlist(crtc);
> -
> -       /* Turn on the scaler, which will wait for vstart to start
> -        * compositing.
> -        * When feeding the transposer, we should operate in oneshot
> -        * mode.
> -        */
> -       dispctrl = SCALER_DISPCTRLX_ENABLE;
> -
> -       if (!vc4->hvs->hvs5)
> -               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> -                                         SCALER_DISPCTRLX_WIDTH) |
> -                           VC4_SET_FIELD(mode->vdisplay,
> -                                         SCALER_DISPCTRLX_HEIGHT) |
> -                           (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
> -       else
> -               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> -                                         SCALER5_DISPCTRLX_WIDTH) |
> -                           VC4_SET_FIELD(mode->vdisplay,
> -                                         SCALER5_DISPCTRLX_HEIGHT) |
> -                           (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
> -
> -       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
> +       vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
>  }
>
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
>                             struct drm_crtc_state *old_state)
>  {
>         struct drm_device *dev = crtc->dev;
> -       struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
>         unsigned int chan = vc4_state->assigned_channel;
>
> -       if (HVS_READ(SCALER_DISPCTRLX(chan)) &
> -           SCALER_DISPCTRLX_ENABLE) {
> -               HVS_WRITE(SCALER_DISPCTRLX(chan),
> -                         SCALER_DISPCTRLX_RESET);
> -
> -               /* While the docs say that reset is self-clearing, it
> -                * seems it doesn't actually.
> -                */
> -               HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> -       }
> -
> -       /* Once we leave, the scaler should be disabled and its fifo empty. */
> -
> -       WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
> -
> -       WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
> -                                  SCALER_DISPSTATX_MODE) !=
> -                    SCALER_DISPSTATX_MODE_DISABLED);
> -
> -       WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
> -                     (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
> -                    SCALER_DISPSTATX_EMPTY);
> +       vc4_hvs_stop_channel(dev, chan);
>  }
>
>  void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function
@ 2020-07-28 10:31       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to make further refactoring easier, let's move the HVS channel
> setup / teardown to their own function.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 104 +++++++++++++++++++----------------
>  1 file changed, 58 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 50f9a9674a7e..78bb1c0b0b76 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -196,6 +196,62 @@ static void vc4_hvs_update_gamma_lut(struct drm_crtc *crtc)
>         vc4_hvs_lut_load(crtc);
>  }
>
> +static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
> +                               struct drm_display_mode *mode, bool oneshot)
> +{
> +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
> +       unsigned int chan = vc4_crtc_state->assigned_channel;
> +       u32 dispctrl;
> +
> +       /* Turn on the scaler, which will wait for vstart to start
> +        * compositing.
> +        * When feeding the transposer, we should operate in oneshot
> +        * mode.
> +        */
> +       dispctrl = SCALER_DISPCTRLX_ENABLE;
> +
> +       if (!vc4->hvs->hvs5)
> +               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> +                                         SCALER_DISPCTRLX_WIDTH) |
> +                           VC4_SET_FIELD(mode->vdisplay,
> +                                         SCALER_DISPCTRLX_HEIGHT) |
> +                           (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
> +       else
> +               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> +                                         SCALER5_DISPCTRLX_WIDTH) |
> +                           VC4_SET_FIELD(mode->vdisplay,
> +                                         SCALER5_DISPCTRLX_HEIGHT) |
> +                           (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
> +
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
> +
> +       return 0;
> +}
> +
> +static void vc4_hvs_stop_channel(struct drm_device *dev, unsigned int chan)
> +{
> +       struct vc4_dev *vc4 = to_vc4_dev(dev);
> +
> +       if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
> +               return;
> +
> +       HVS_WRITE(SCALER_DISPCTRLX(chan),
> +                 HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan),
> +                 HVS_READ(SCALER_DISPCTRLX(chan)) & ~SCALER_DISPCTRLX_ENABLE);
> +
> +       /* Once we leave, the scaler should be disabled and its fifo empty. */
> +       WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
> +
> +       WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
> +                                  SCALER_DISPSTATX_MODE) !=
> +                    SCALER_DISPSTATX_MODE_DISABLED);
> +
> +       WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
> +                     (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
> +                    SCALER_DISPSTATX_EMPTY);
> +}
> +
>  int vc4_hvs_atomic_check(struct drm_crtc *crtc,
>                          struct drm_crtc_state *state)
>  {
> @@ -268,63 +324,19 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool oneshot = vc4_state->feed_txp;
> -       u32 dispctrl;
>
>         vc4_hvs_update_dlist(crtc);
> -
> -       /* Turn on the scaler, which will wait for vstart to start
> -        * compositing.
> -        * When feeding the transposer, we should operate in oneshot
> -        * mode.
> -        */
> -       dispctrl = SCALER_DISPCTRLX_ENABLE;
> -
> -       if (!vc4->hvs->hvs5)
> -               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> -                                         SCALER_DISPCTRLX_WIDTH) |
> -                           VC4_SET_FIELD(mode->vdisplay,
> -                                         SCALER_DISPCTRLX_HEIGHT) |
> -                           (oneshot ? SCALER_DISPCTRLX_ONESHOT : 0);
> -       else
> -               dispctrl |= VC4_SET_FIELD(mode->hdisplay,
> -                                         SCALER5_DISPCTRLX_WIDTH) |
> -                           VC4_SET_FIELD(mode->vdisplay,
> -                                         SCALER5_DISPCTRLX_HEIGHT) |
> -                           (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
> -
> -       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
> +       vc4_hvs_init_channel(vc4, crtc, mode, oneshot);
>  }
>
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
>                             struct drm_crtc_state *old_state)
>  {
>         struct drm_device *dev = crtc->dev;
> -       struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
>         unsigned int chan = vc4_state->assigned_channel;
>
> -       if (HVS_READ(SCALER_DISPCTRLX(chan)) &
> -           SCALER_DISPCTRLX_ENABLE) {
> -               HVS_WRITE(SCALER_DISPCTRLX(chan),
> -                         SCALER_DISPCTRLX_RESET);
> -
> -               /* While the docs say that reset is self-clearing, it
> -                * seems it doesn't actually.
> -                */
> -               HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> -       }
> -
> -       /* Once we leave, the scaler should be disabled and its fifo empty. */
> -
> -       WARN_ON_ONCE(HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_RESET);
> -
> -       WARN_ON_ONCE(VC4_GET_FIELD(HVS_READ(SCALER_DISPSTATX(chan)),
> -                                  SCALER_DISPSTATX_MODE) !=
> -                    SCALER_DISPSTATX_MODE_DISABLED);
> -
> -       WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
> -                     (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
> -                    SCALER_DISPSTATX_EMPTY);
> +       vc4_hvs_stop_channel(dev, chan);
>  }
>
>  void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 10:37       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to clear our intermediate FIFOs that might end up with a stale
> pixel, let's make sure our FIFO channel is reset everytime our channel is
> setup.

Minor nit pick: s/everytime/every time

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index c7de77afbf0a..64b9d72471ef 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>         u32 dispbkgndx;
>         u32 dispctrl;
>
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> +
>         /* Turn on the scaler, which will wait for vstart to start
>          * compositing.
>          * When feeding the transposer, we should operate in oneshot
> --
> git-series 0.9.1

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

* Re: [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset
@ 2020-07-28 10:37       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to clear our intermediate FIFOs that might end up with a stale
> pixel, let's make sure our FIFO channel is reset everytime our channel is
> setup.

Minor nit pick: s/everytime/every time

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index c7de77afbf0a..64b9d72471ef 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>         u32 dispbkgndx;
>         u32 dispctrl;
>
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> +
>         /* Turn on the scaler, which will wait for vstart to start
>          * compositing.
>          * When feeding the transposer, we should operate in oneshot
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset
@ 2020-07-28 10:37       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to clear our intermediate FIFOs that might end up with a stale
> pixel, let's make sure our FIFO channel is reset everytime our channel is
> setup.

Minor nit pick: s/everytime/every time

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hvs.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index c7de77afbf0a..64b9d72471ef 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -205,6 +205,10 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>         u32 dispbkgndx;
>         u32 dispctrl;
>
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
> +       HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
> +
>         /* Turn on the scaler, which will wait for vstart to start
>          * compositing.
>          * When feeding the transposer, we should operate in oneshot
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 10:38       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:38 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the
> pixelvalve needs to be setup each time there's a mode change or enable /
> disable sequence.
>
> Therefore, we can't really use mode_set_nofb anymore to configure it, but
> we need to move it to atomic_enable.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 284a85b9d7d4..2eda2e6429ec 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>         }
>  }
>
> -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       vc4_crtc_config_pv(crtc);
> -}
> -
>  static void require_hvs_enabled(struct drm_device *dev)
>  {
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> @@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>         require_hvs_enabled(dev);
>
>         vc4_crtc_pixelvalve_reset(crtc);
> +       vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>
> @@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
>  };
>
>  static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
> -       .mode_set_nofb = vc4_crtc_mode_set_nofb,
>         .mode_valid = vc4_crtc_mode_valid,
>         .atomic_check = vc4_crtc_atomic_check,
>         .atomic_flush = vc4_hvs_atomic_flush,
> --
> git-series 0.9.1

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

* Re: [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb
@ 2020-07-28 10:38       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:38 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the
> pixelvalve needs to be setup each time there's a mode change or enable /
> disable sequence.
>
> Therefore, we can't really use mode_set_nofb anymore to configure it, but
> we need to move it to atomic_enable.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 284a85b9d7d4..2eda2e6429ec 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>         }
>  }
>
> -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       vc4_crtc_config_pv(crtc);
> -}
> -
>  static void require_hvs_enabled(struct drm_device *dev)
>  {
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> @@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>         require_hvs_enabled(dev);
>
>         vc4_crtc_pixelvalve_reset(crtc);
> +       vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>
> @@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
>  };
>
>  static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
> -       .mode_set_nofb = vc4_crtc_mode_set_nofb,
>         .mode_valid = vc4_crtc_mode_valid,
>         .atomic_check = vc4_crtc_atomic_check,
>         .atomic_flush = vc4_hvs_atomic_flush,
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb
@ 2020-07-28 10:38       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:38 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> On BCM2711 to avoid stale pixels getting stuck in intermediate FIFOs, the
> pixelvalve needs to be setup each time there's a mode change or enable /
> disable sequence.
>
> Therefore, we can't really use mode_set_nofb anymore to configure it, but
> we need to move it to atomic_enable.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 284a85b9d7d4..2eda2e6429ec 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -376,11 +376,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>         }
>  }
>
> -static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       vc4_crtc_config_pv(crtc);
> -}
> -
>  static void require_hvs_enabled(struct drm_device *dev)
>  {
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> @@ -433,6 +428,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>         require_hvs_enabled(dev);
>
>         vc4_crtc_pixelvalve_reset(crtc);
> +       vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>
> @@ -791,7 +787,6 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
>  };
>
>  static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
> -       .mode_set_nofb = vc4_crtc_mode_set_nofb,
>         .mode_valid = vc4_crtc_mode_valid,
>         .atomic_check = vc4_crtc_atomic_check,
>         .atomic_flush = vc4_hvs_atomic_flush,
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 10:39       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:39 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Since we moved the pixelvalve configuration to atomic_enable, we're now
> first calling the function that resets the pixelvalve and then the one that
> configures it.
>
> However, the first thing the latter is doing is calling the reset function,
> meaning that we reset twice our pixelvalve. Let's remove the first call.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 2eda2e6429ec..2c5ff45dc315 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> -       vc4_crtc_pixelvalve_reset(crtc);
>         vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> --
> git-series 0.9.1

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

* Re: [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset
@ 2020-07-28 10:39       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:39 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Since we moved the pixelvalve configuration to atomic_enable, we're now
> first calling the function that resets the pixelvalve and then the one that
> configures it.
>
> However, the first thing the latter is doing is calling the reset function,
> meaning that we reset twice our pixelvalve. Let's remove the first call.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 2eda2e6429ec..2c5ff45dc315 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> -       vc4_crtc_pixelvalve_reset(crtc);
>         vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset
@ 2020-07-28 10:39       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:39 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Since we moved the pixelvalve configuration to atomic_enable, we're now
> first calling the function that resets the pixelvalve and then the one that
> configures it.
>
> However, the first thing the latter is doing is calling the reset function,
> meaning that we reset twice our pixelvalve. Let's remove the first call.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 2eda2e6429ec..2c5ff45dc315 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -427,7 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> -       vc4_crtc_pixelvalve_reset(crtc);
>         vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 10:40       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid stale pixels getting stuck in an intermediate FIFO
> between the HVS and the pixelvalve on BCM2711, we need to configure the HVS
> channel before the pixelvalve is reset and configured.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 2c5ff45dc315..b7b0e19e2fe1 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> -       vc4_crtc_config_pv(crtc);
> -
> -       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> -
>         /* Enable vblank irq handling before crtc is started otherwise
>          * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
>          */
> @@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         vc4_hvs_atomic_enable(crtc, old_state);
>
> +       vc4_crtc_config_pv(crtc);
> +
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> +
>         /* When feeding the transposer block the pixelvalve is unneeded and
>          * should not be enabled.
>          */
> --
> git-series 0.9.1

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

* Re: [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation
@ 2020-07-28 10:40       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid stale pixels getting stuck in an intermediate FIFO
> between the HVS and the pixelvalve on BCM2711, we need to configure the HVS
> channel before the pixelvalve is reset and configured.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 2c5ff45dc315..b7b0e19e2fe1 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> -       vc4_crtc_config_pv(crtc);
> -
> -       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> -
>         /* Enable vblank irq handling before crtc is started otherwise
>          * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
>          */
> @@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         vc4_hvs_atomic_enable(crtc, old_state);
>
> +       vc4_crtc_config_pv(crtc);
> +
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> +
>         /* When feeding the transposer block the pixelvalve is unneeded and
>          * should not be enabled.
>          */
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation
@ 2020-07-28 10:40       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 10:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid stale pixels getting stuck in an intermediate FIFO
> between the HVS and the pixelvalve on BCM2711, we need to configure the HVS
> channel before the pixelvalve is reset and configured.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 2c5ff45dc315..b7b0e19e2fe1 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -427,10 +427,6 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         require_hvs_enabled(dev);
>
> -       vc4_crtc_config_pv(crtc);
> -
> -       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> -
>         /* Enable vblank irq handling before crtc is started otherwise
>          * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
>          */
> @@ -438,6 +434,10 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         vc4_hvs_atomic_enable(crtc, old_state);
>
> +       vc4_crtc_config_pv(crtc);
> +
> +       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
> +
>         /* When feeding the transposer block the pixelvalve is unneeded and
>          * should not be enabled.
>          */
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 11:25       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
> requires very precise ordering and timing that the regular atomic callbacks
> don't provide. Let's add new callbacks on top of the regular ones to be
> able to split the configuration as needed.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++
>  drivers/gpu/drm/vc4/vc4_drv.h  |  7 +++++++
>  2 files changed, 26 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index b7b0e19e2fe1..d0b326e1df0a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
> +       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
>         int ret;
>
>         require_hvs_enabled(dev);
> @@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       if (vc4_encoder->post_crtc_disable)
> +               vc4_encoder->post_crtc_disable(encoder);
> +
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
>
>         vc4_hvs_atomic_disable(crtc, old_state);
>
> +       if (vc4_encoder->post_crtc_powerdown)
> +               vc4_encoder->post_crtc_powerdown(encoder);
> +
>         /*
>          * Make sure we issue a vblank event after disabling the CRTC if
>          * someone was waiting it.
> @@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
> +       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
>
>         require_hvs_enabled(dev);
>
> @@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         vc4_hvs_atomic_enable(crtc, old_state);
>
> +       if (vc4_encoder->pre_crtc_configure)
> +               vc4_encoder->pre_crtc_configure(encoder);
> +
>         vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>
> +       if (vc4_encoder->pre_crtc_enable)
> +               vc4_encoder->pre_crtc_enable(encoder);
> +
>         /* When feeding the transposer block the pixelvalve is unneeded and
>          * should not be enabled.
>          */
>         CRTC_WRITE(PV_V_CONTROL,
>                    CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
> +
> +       if (vc4_encoder->post_crtc_enable)
> +               vc4_encoder->post_crtc_enable(encoder);
>  }
>
>  static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index dfcc684f5d28..251fcc35530c 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -439,6 +439,13 @@ struct vc4_encoder {
>         struct drm_encoder base;
>         enum vc4_encoder_type type;
>         u32 clock_select;
> +
> +       void (*pre_crtc_configure)(struct drm_encoder *encoder);
> +       void (*pre_crtc_enable)(struct drm_encoder *encoder);
> +       void (*post_crtc_enable)(struct drm_encoder *encoder);
> +
> +       void (*post_crtc_disable)(struct drm_encoder *encoder);
> +       void (*post_crtc_powerdown)(struct drm_encoder *encoder);
>  };
>
>  static inline struct vc4_encoder *
> --
> git-series 0.9.1

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

* Re: [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks
@ 2020-07-28 11:25       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
> requires very precise ordering and timing that the regular atomic callbacks
> don't provide. Let's add new callbacks on top of the regular ones to be
> able to split the configuration as needed.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++
>  drivers/gpu/drm/vc4/vc4_drv.h  |  7 +++++++
>  2 files changed, 26 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index b7b0e19e2fe1..d0b326e1df0a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
> +       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
>         int ret;
>
>         require_hvs_enabled(dev);
> @@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       if (vc4_encoder->post_crtc_disable)
> +               vc4_encoder->post_crtc_disable(encoder);
> +
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
>
>         vc4_hvs_atomic_disable(crtc, old_state);
>
> +       if (vc4_encoder->post_crtc_powerdown)
> +               vc4_encoder->post_crtc_powerdown(encoder);
> +
>         /*
>          * Make sure we issue a vblank event after disabling the CRTC if
>          * someone was waiting it.
> @@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
> +       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
>
>         require_hvs_enabled(dev);
>
> @@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         vc4_hvs_atomic_enable(crtc, old_state);
>
> +       if (vc4_encoder->pre_crtc_configure)
> +               vc4_encoder->pre_crtc_configure(encoder);
> +
>         vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>
> +       if (vc4_encoder->pre_crtc_enable)
> +               vc4_encoder->pre_crtc_enable(encoder);
> +
>         /* When feeding the transposer block the pixelvalve is unneeded and
>          * should not be enabled.
>          */
>         CRTC_WRITE(PV_V_CONTROL,
>                    CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
> +
> +       if (vc4_encoder->post_crtc_enable)
> +               vc4_encoder->post_crtc_enable(encoder);
>  }
>
>  static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index dfcc684f5d28..251fcc35530c 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -439,6 +439,13 @@ struct vc4_encoder {
>         struct drm_encoder base;
>         enum vc4_encoder_type type;
>         u32 clock_select;
> +
> +       void (*pre_crtc_configure)(struct drm_encoder *encoder);
> +       void (*pre_crtc_enable)(struct drm_encoder *encoder);
> +       void (*post_crtc_enable)(struct drm_encoder *encoder);
> +
> +       void (*post_crtc_disable)(struct drm_encoder *encoder);
> +       void (*post_crtc_powerdown)(struct drm_encoder *encoder);
>  };
>
>  static inline struct vc4_encoder *
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks
@ 2020-07-28 11:25       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller
> requires very precise ordering and timing that the regular atomic callbacks
> don't provide. Let's add new callbacks on top of the regular ones to be
> able to split the configuration as needed.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++
>  drivers/gpu/drm/vc4/vc4_drv.h  |  7 +++++++
>  2 files changed, 26 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index b7b0e19e2fe1..d0b326e1df0a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -389,6 +389,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
> +       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
>         int ret;
>
>         require_hvs_enabled(dev);
> @@ -401,10 +403,16 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       if (vc4_encoder->post_crtc_disable)
> +               vc4_encoder->post_crtc_disable(encoder);
> +
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
>
>         vc4_hvs_atomic_disable(crtc, old_state);
>
> +       if (vc4_encoder->post_crtc_powerdown)
> +               vc4_encoder->post_crtc_powerdown(encoder);
> +
>         /*
>          * Make sure we issue a vblank event after disabling the CRTC if
>          * someone was waiting it.
> @@ -424,6 +432,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc);
> +       struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
>
>         require_hvs_enabled(dev);
>
> @@ -434,15 +444,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
>
>         vc4_hvs_atomic_enable(crtc, old_state);
>
> +       if (vc4_encoder->pre_crtc_configure)
> +               vc4_encoder->pre_crtc_configure(encoder);
> +
>         vc4_crtc_config_pv(crtc);
>
>         CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) | PV_CONTROL_EN);
>
> +       if (vc4_encoder->pre_crtc_enable)
> +               vc4_encoder->pre_crtc_enable(encoder);
> +
>         /* When feeding the transposer block the pixelvalve is unneeded and
>          * should not be enabled.
>          */
>         CRTC_WRITE(PV_V_CONTROL,
>                    CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
> +
> +       if (vc4_encoder->post_crtc_enable)
> +               vc4_encoder->post_crtc_enable(encoder);
>  }
>
>  static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index dfcc684f5d28..251fcc35530c 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -439,6 +439,13 @@ struct vc4_encoder {
>         struct drm_encoder base;
>         enum vc4_encoder_type type;
>         u32 clock_select;
> +
> +       void (*pre_crtc_configure)(struct drm_encoder *encoder);
> +       void (*pre_crtc_enable)(struct drm_encoder *encoder);
> +       void (*post_crtc_enable)(struct drm_encoder *encoder);
> +
> +       void (*post_crtc_disable)(struct drm_encoder *encoder);
> +       void (*post_crtc_powerdown)(struct drm_encoder *encoder);
>  };
>
>  static inline struct vc4_encoder *
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 11:40       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid a stale pixel getting stuck on mode change or a disable
> / enable cycle, we need to make sure to flush the PV FIFO on disable.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 7b178d67187f..13fe0e370fb3 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -408,8 +408,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         if (vc4_encoder->post_crtc_disable)
>                 vc4_encoder->post_crtc_disable(encoder);
>
> -       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
> -
> +       vc4_crtc_pixelvalve_reset(crtc);
>         vc4_hvs_atomic_disable(crtc, old_state);
>
>         if (vc4_encoder->post_crtc_powerdown)
> --
> git-series 0.9.1

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

* Re: [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable
@ 2020-07-28 11:40       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid a stale pixel getting stuck on mode change or a disable
> / enable cycle, we need to make sure to flush the PV FIFO on disable.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 7b178d67187f..13fe0e370fb3 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -408,8 +408,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         if (vc4_encoder->post_crtc_disable)
>                 vc4_encoder->post_crtc_disable(encoder);
>
> -       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
> -
> +       vc4_crtc_pixelvalve_reset(crtc);
>         vc4_hvs_atomic_disable(crtc, old_state);
>
>         if (vc4_encoder->post_crtc_powerdown)
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable
@ 2020-07-28 11:40       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid a stale pixel getting stuck on mode change or a disable
> / enable cycle, we need to make sure to flush the PV FIFO on disable.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 7b178d67187f..13fe0e370fb3 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -408,8 +408,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         if (vc4_encoder->post_crtc_disable)
>                 vc4_encoder->post_crtc_disable(encoder);
>
> -       CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN);
> -
> +       vc4_crtc_pixelvalve_reset(crtc);
>         vc4_hvs_atomic_disable(crtc, old_state);
>
>         if (vc4_encoder->post_crtc_powerdown)
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 11:41       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:41 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Even though it's not really clear why we need to flush the PV FIFO during
> the configuration even though we started by flushing it, experience shows
> that without it we get a stale pixel stuck in the FIFO between the HVS and
> the PV.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 13fe0e370fb3..25a77cd46b28 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>         if (is_dsi)
>                 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
>
> -       CRTC_WRITE(PV_CONTROL,
> +       CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
>                    vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
>                    VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
>                    VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
> --
> git-series 0.9.1

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

* Re: [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration
@ 2020-07-28 11:41       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:41 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Even though it's not really clear why we need to flush the PV FIFO during
> the configuration even though we started by flushing it, experience shows
> that without it we get a stale pixel stuck in the FIFO between the HVS and
> the PV.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 13fe0e370fb3..25a77cd46b28 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>         if (is_dsi)
>                 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
>
> -       CRTC_WRITE(PV_CONTROL,
> +       CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
>                    vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
>                    VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
>                    VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration
@ 2020-07-28 11:41       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:41 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Even though it's not really clear why we need to flush the PV FIFO during
> the configuration even though we started by flushing it, experience shows
> that without it we get a stale pixel stuck in the FIFO between the HVS and
> the PV.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 13fe0e370fb3..25a77cd46b28 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -358,7 +358,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>         if (is_dsi)
>                 CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
>
> -       CRTC_WRITE(PV_CONTROL,
> +       CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR |
>                    vc4_crtc_get_fifo_full_level_bits(vc4_crtc, format) |
>                    VC4_SET_FIELD(format, PV_CONTROL_FORMAT) |
>                    VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) |
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 11:58       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:58 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> the vc4_hdmi driver has some custom structures to hold the data it needs to
> associate with the drm_encoder and drm_connector structures.
>
> However, it allocates them separately from the vc4_hdmi structure which
> makes it more complicated than it needs to be.
>
> Move those structures to be contained by vc4_hdmi and update the code
> accordingly.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
>  2 files changed, 72 insertions(+), 79 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index db79e0d88625..1e2214f24ed7 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
>         .get_modes = vc4_hdmi_connector_get_modes,
>  };
>
> -static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
> -                                                    struct drm_encoder *encoder,
> -                                                    struct i2c_adapter *ddc)
> +static int vc4_hdmi_connector_init(struct drm_device *dev,
> +                                  struct vc4_hdmi *vc4_hdmi,
> +                                  struct i2c_adapter *ddc)
>  {
> -       struct drm_connector *connector;
> -       struct vc4_hdmi_connector *hdmi_connector;
> +       struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
> +       struct drm_connector *connector = &hdmi_connector->base;
> +       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
>         int ret;
>
> -       hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
> -                                     GFP_KERNEL);
> -       if (!hdmi_connector)
> -               return ERR_PTR(-ENOMEM);
> -       connector = &hdmi_connector->base;
> -
>         hdmi_connector->encoder = encoder;
>
>         drm_connector_init_with_ddc(dev, connector,
> @@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>         /* Create and attach TV margin props to this connector. */
>         ret = drm_mode_create_tv_margin_properties(dev);
>         if (ret)
> -               return ERR_PTR(ret);
> +               return ret;
>
>         drm_connector_attach_tv_margin_properties(connector);
>
> @@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>
>         drm_connector_attach_encoder(connector, encoder);
>
> -       return connector;
> +       return 0;
>  }
>
>  static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
> @@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         struct vc4_dev *vc4 = encoder->dev->dev_private;
>         struct vc4_hdmi *hdmi = vc4->hdmi;
> -       struct drm_connector_state *cstate = hdmi->connector->state;
> +       struct drm_connector *connector = &hdmi->connector.base;
> +       struct drm_connector_state *cstate = connector->state;
>         struct drm_crtc *crtc = encoder->crtc;
>         const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         union hdmi_infoframe frame;
>         int ret;
>
>         ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -                                                      hdmi->connector, mode);
> +                                                      connector, mode);
>         if (ret < 0) {
>                 DRM_ERROR("couldn't fill AVI infoframe\n");
>                 return;
>         }
>
>         drm_hdmi_avi_infoframe_quant_range(&frame.avi,
> -                                          hdmi->connector, mode,
> +                                          connector, mode,
>                                            vc4_encoder->limited_rgb_range ?
>                                            HDMI_QUANTIZATION_RANGE_LIMITED :
>                                            HDMI_QUANTIZATION_RANGE_FULL);
> @@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_device *drm = hdmi->encoder->dev;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>         u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
>         unsigned long n, m;
> @@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_crtc *crtc = encoder->crtc;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_connector *connector = &hdmi->connector.base;
>         struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
>         int ret;
>
> @@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> -       ret = snd_pcm_hw_constraint_eld(substream->runtime,
> -                                       hdmi->connector->eld);
> +       ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
>         if (ret)
>                 return ret;
>
> @@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>
>  static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                                     struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>
> @@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
>         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
> -       uinfo->count = sizeof(hdmi->connector->eld);
> +       uinfo->count = sizeof(connector->eld);
>
>         return 0;
>  }
> @@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
> -       memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
> -              sizeof(hdmi->connector->eld));
> +       memcpy(ucontrol->value.bytes.data, connector->eld,
> +              sizeof(connector->eld));
>
>         return 0;
>  }
> @@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
>         struct vc4_hdmi *hdmi;
> -       struct vc4_hdmi_encoder *vc4_hdmi_encoder;
> +       struct drm_encoder *encoder;
>         struct device_node *ddc_node;
>         u32 value;
>         int ret;
> @@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!hdmi)
>                 return -ENOMEM;
>
> -       vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
> -                                       GFP_KERNEL);
> -       if (!vc4_hdmi_encoder)
> -               return -ENOMEM;
> -       vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
> -       hdmi->encoder = &vc4_hdmi_encoder->base.base;
> -
> +       encoder = &hdmi->encoder.base.base;
> +       hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         hdmi->pdev = pdev;
> +
>         hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(hdmi->hdmicore_regs))
>                 return PTR_ERR(hdmi->hdmicore_regs);
> @@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>         pm_runtime_enable(dev);
>
> -       drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
> -       drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
> +       drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> +       drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
>
> -       hdmi->connector =
> -               vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
> -       if (IS_ERR(hdmi->connector)) {
> -               ret = PTR_ERR(hdmi->connector);
> +       ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
> +       if (ret)
>                 goto err_destroy_encoder;
> -       }
> +
>  #ifdef CONFIG_DRM_VC4_HDMI_CEC
>         hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                               vc4, "vc4",
> @@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret < 0)
>                 goto err_destroy_conn;
>
> -       cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
> +       cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
>         cec_s_conn_info(hdmi->cec_adap, &conn_info);
>
>         HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> @@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_delete_cec_adap:
>         cec_delete_adapter(hdmi->cec_adap);
>  err_destroy_conn:
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
>  #endif
>  err_destroy_encoder:
> -       drm_encoder_cleanup(hdmi->encoder);
> +       drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> @@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         struct vc4_hdmi *hdmi = vc4->hdmi;
>
>         cec_unregister_adapter(hdmi->cec_adap);
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> -       drm_encoder_cleanup(hdmi->encoder);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
> +       drm_encoder_cleanup(&hdmi->encoder.base.base);
>
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 5ec5d1f6b1e6..17079a39f1b1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -8,6 +8,36 @@
>
>  #include "vc4_drv.h"
>
> +/* VC4 HDMI encoder KMS struct */
> +struct vc4_hdmi_encoder {
> +       struct vc4_encoder base;
> +       bool hdmi_monitor;
> +       bool limited_rgb_range;
> +};
> +
> +static inline struct vc4_hdmi_encoder *
> +to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> +}
> +
> +/* VC4 HDMI connector KMS struct */
> +struct vc4_hdmi_connector {
> +       struct drm_connector base;
> +
> +       /* Since the connector is attached to just the one encoder,
> +        * this is the reference to it so we can do the best_encoder()
> +        * hook.
> +        */
> +       struct drm_encoder *encoder;
> +};
> +
> +static inline struct vc4_hdmi_connector *
> +to_vc4_hdmi_connector(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct vc4_hdmi_connector, base);
> +}
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
>  struct vc4_hdmi {
>         struct platform_device *pdev;
>
> -       struct drm_encoder *encoder;
> -       struct drm_connector *connector;
> +       struct vc4_hdmi_encoder encoder;
> +       struct vc4_hdmi_connector connector;
>
>         struct vc4_hdmi_audio audio;
>
> @@ -53,34 +83,4 @@ struct vc4_hdmi {
>  #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
>  #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
>
> -/* VC4 HDMI encoder KMS struct */
> -struct vc4_hdmi_encoder {
> -       struct vc4_encoder base;
> -       bool hdmi_monitor;
> -       bool limited_rgb_range;
> -};
> -
> -static inline struct vc4_hdmi_encoder *
> -to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> -{
> -       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> -}
> -
> -/* VC4 HDMI connector KMS struct */
> -struct vc4_hdmi_connector {
> -       struct drm_connector base;
> -
> -       /* Since the connector is attached to just the one encoder,
> -        * this is the reference to it so we can do the best_encoder()
> -        * hook.
> -        */
> -       struct drm_encoder *encoder;
> -};
> -
> -static inline struct vc4_hdmi_connector *
> -to_vc4_hdmi_connector(struct drm_connector *connector)
> -{
> -       return container_of(connector, struct vc4_hdmi_connector, base);
> -}
> -
>  #endif /* _VC4_HDMI_H_ */
> --
> git-series 0.9.1

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

* Re: [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders
@ 2020-07-28 11:58       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:58 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> the vc4_hdmi driver has some custom structures to hold the data it needs to
> associate with the drm_encoder and drm_connector structures.
>
> However, it allocates them separately from the vc4_hdmi structure which
> makes it more complicated than it needs to be.
>
> Move those structures to be contained by vc4_hdmi and update the code
> accordingly.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
>  2 files changed, 72 insertions(+), 79 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index db79e0d88625..1e2214f24ed7 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
>         .get_modes = vc4_hdmi_connector_get_modes,
>  };
>
> -static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
> -                                                    struct drm_encoder *encoder,
> -                                                    struct i2c_adapter *ddc)
> +static int vc4_hdmi_connector_init(struct drm_device *dev,
> +                                  struct vc4_hdmi *vc4_hdmi,
> +                                  struct i2c_adapter *ddc)
>  {
> -       struct drm_connector *connector;
> -       struct vc4_hdmi_connector *hdmi_connector;
> +       struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
> +       struct drm_connector *connector = &hdmi_connector->base;
> +       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
>         int ret;
>
> -       hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
> -                                     GFP_KERNEL);
> -       if (!hdmi_connector)
> -               return ERR_PTR(-ENOMEM);
> -       connector = &hdmi_connector->base;
> -
>         hdmi_connector->encoder = encoder;
>
>         drm_connector_init_with_ddc(dev, connector,
> @@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>         /* Create and attach TV margin props to this connector. */
>         ret = drm_mode_create_tv_margin_properties(dev);
>         if (ret)
> -               return ERR_PTR(ret);
> +               return ret;
>
>         drm_connector_attach_tv_margin_properties(connector);
>
> @@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>
>         drm_connector_attach_encoder(connector, encoder);
>
> -       return connector;
> +       return 0;
>  }
>
>  static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
> @@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         struct vc4_dev *vc4 = encoder->dev->dev_private;
>         struct vc4_hdmi *hdmi = vc4->hdmi;
> -       struct drm_connector_state *cstate = hdmi->connector->state;
> +       struct drm_connector *connector = &hdmi->connector.base;
> +       struct drm_connector_state *cstate = connector->state;
>         struct drm_crtc *crtc = encoder->crtc;
>         const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         union hdmi_infoframe frame;
>         int ret;
>
>         ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -                                                      hdmi->connector, mode);
> +                                                      connector, mode);
>         if (ret < 0) {
>                 DRM_ERROR("couldn't fill AVI infoframe\n");
>                 return;
>         }
>
>         drm_hdmi_avi_infoframe_quant_range(&frame.avi,
> -                                          hdmi->connector, mode,
> +                                          connector, mode,
>                                            vc4_encoder->limited_rgb_range ?
>                                            HDMI_QUANTIZATION_RANGE_LIMITED :
>                                            HDMI_QUANTIZATION_RANGE_FULL);
> @@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_device *drm = hdmi->encoder->dev;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>         u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
>         unsigned long n, m;
> @@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_crtc *crtc = encoder->crtc;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_connector *connector = &hdmi->connector.base;
>         struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
>         int ret;
>
> @@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> -       ret = snd_pcm_hw_constraint_eld(substream->runtime,
> -                                       hdmi->connector->eld);
> +       ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
>         if (ret)
>                 return ret;
>
> @@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>
>  static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                                     struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>
> @@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
>         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
> -       uinfo->count = sizeof(hdmi->connector->eld);
> +       uinfo->count = sizeof(connector->eld);
>
>         return 0;
>  }
> @@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
> -       memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
> -              sizeof(hdmi->connector->eld));
> +       memcpy(ucontrol->value.bytes.data, connector->eld,
> +              sizeof(connector->eld));
>
>         return 0;
>  }
> @@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
>         struct vc4_hdmi *hdmi;
> -       struct vc4_hdmi_encoder *vc4_hdmi_encoder;
> +       struct drm_encoder *encoder;
>         struct device_node *ddc_node;
>         u32 value;
>         int ret;
> @@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!hdmi)
>                 return -ENOMEM;
>
> -       vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
> -                                       GFP_KERNEL);
> -       if (!vc4_hdmi_encoder)
> -               return -ENOMEM;
> -       vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
> -       hdmi->encoder = &vc4_hdmi_encoder->base.base;
> -
> +       encoder = &hdmi->encoder.base.base;
> +       hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         hdmi->pdev = pdev;
> +
>         hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(hdmi->hdmicore_regs))
>                 return PTR_ERR(hdmi->hdmicore_regs);
> @@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>         pm_runtime_enable(dev);
>
> -       drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
> -       drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
> +       drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> +       drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
>
> -       hdmi->connector =
> -               vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
> -       if (IS_ERR(hdmi->connector)) {
> -               ret = PTR_ERR(hdmi->connector);
> +       ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
> +       if (ret)
>                 goto err_destroy_encoder;
> -       }
> +
>  #ifdef CONFIG_DRM_VC4_HDMI_CEC
>         hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                               vc4, "vc4",
> @@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret < 0)
>                 goto err_destroy_conn;
>
> -       cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
> +       cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
>         cec_s_conn_info(hdmi->cec_adap, &conn_info);
>
>         HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> @@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_delete_cec_adap:
>         cec_delete_adapter(hdmi->cec_adap);
>  err_destroy_conn:
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
>  #endif
>  err_destroy_encoder:
> -       drm_encoder_cleanup(hdmi->encoder);
> +       drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> @@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         struct vc4_hdmi *hdmi = vc4->hdmi;
>
>         cec_unregister_adapter(hdmi->cec_adap);
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> -       drm_encoder_cleanup(hdmi->encoder);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
> +       drm_encoder_cleanup(&hdmi->encoder.base.base);
>
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 5ec5d1f6b1e6..17079a39f1b1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -8,6 +8,36 @@
>
>  #include "vc4_drv.h"
>
> +/* VC4 HDMI encoder KMS struct */
> +struct vc4_hdmi_encoder {
> +       struct vc4_encoder base;
> +       bool hdmi_monitor;
> +       bool limited_rgb_range;
> +};
> +
> +static inline struct vc4_hdmi_encoder *
> +to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> +}
> +
> +/* VC4 HDMI connector KMS struct */
> +struct vc4_hdmi_connector {
> +       struct drm_connector base;
> +
> +       /* Since the connector is attached to just the one encoder,
> +        * this is the reference to it so we can do the best_encoder()
> +        * hook.
> +        */
> +       struct drm_encoder *encoder;
> +};
> +
> +static inline struct vc4_hdmi_connector *
> +to_vc4_hdmi_connector(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct vc4_hdmi_connector, base);
> +}
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
>  struct vc4_hdmi {
>         struct platform_device *pdev;
>
> -       struct drm_encoder *encoder;
> -       struct drm_connector *connector;
> +       struct vc4_hdmi_encoder encoder;
> +       struct vc4_hdmi_connector connector;
>
>         struct vc4_hdmi_audio audio;
>
> @@ -53,34 +83,4 @@ struct vc4_hdmi {
>  #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
>  #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
>
> -/* VC4 HDMI encoder KMS struct */
> -struct vc4_hdmi_encoder {
> -       struct vc4_encoder base;
> -       bool hdmi_monitor;
> -       bool limited_rgb_range;
> -};
> -
> -static inline struct vc4_hdmi_encoder *
> -to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> -{
> -       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> -}
> -
> -/* VC4 HDMI connector KMS struct */
> -struct vc4_hdmi_connector {
> -       struct drm_connector base;
> -
> -       /* Since the connector is attached to just the one encoder,
> -        * this is the reference to it so we can do the best_encoder()
> -        * hook.
> -        */
> -       struct drm_encoder *encoder;
> -};
> -
> -static inline struct vc4_hdmi_connector *
> -to_vc4_hdmi_connector(struct drm_connector *connector)
> -{
> -       return container_of(connector, struct vc4_hdmi_connector, base);
> -}
> -
>  #endif /* _VC4_HDMI_H_ */
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders
@ 2020-07-28 11:58       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 11:58 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> the vc4_hdmi driver has some custom structures to hold the data it needs to
> associate with the drm_encoder and drm_connector structures.
>
> However, it allocates them separately from the vc4_hdmi structure which
> makes it more complicated than it needs to be.
>
> Move those structures to be contained by vc4_hdmi and update the code
> accordingly.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 87 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 64 +++++++++++++-------------
>  2 files changed, 72 insertions(+), 79 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index db79e0d88625..1e2214f24ed7 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -191,20 +191,15 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
>         .get_modes = vc4_hdmi_connector_get_modes,
>  };
>
> -static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
> -                                                    struct drm_encoder *encoder,
> -                                                    struct i2c_adapter *ddc)
> +static int vc4_hdmi_connector_init(struct drm_device *dev,
> +                                  struct vc4_hdmi *vc4_hdmi,
> +                                  struct i2c_adapter *ddc)
>  {
> -       struct drm_connector *connector;
> -       struct vc4_hdmi_connector *hdmi_connector;
> +       struct vc4_hdmi_connector *hdmi_connector = &vc4_hdmi->connector;
> +       struct drm_connector *connector = &hdmi_connector->base;
> +       struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
>         int ret;
>
> -       hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector),
> -                                     GFP_KERNEL);
> -       if (!hdmi_connector)
> -               return ERR_PTR(-ENOMEM);
> -       connector = &hdmi_connector->base;
> -
>         hdmi_connector->encoder = encoder;
>
>         drm_connector_init_with_ddc(dev, connector,
> @@ -216,7 +211,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>         /* Create and attach TV margin props to this connector. */
>         ret = drm_mode_create_tv_margin_properties(dev);
>         if (ret)
> -               return ERR_PTR(ret);
> +               return ret;
>
>         drm_connector_attach_tv_margin_properties(connector);
>
> @@ -228,7 +223,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
>
>         drm_connector_attach_encoder(connector, encoder);
>
> -       return connector;
> +       return 0;
>  }
>
>  static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
> @@ -298,21 +293,22 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         struct vc4_dev *vc4 = encoder->dev->dev_private;
>         struct vc4_hdmi *hdmi = vc4->hdmi;
> -       struct drm_connector_state *cstate = hdmi->connector->state;
> +       struct drm_connector *connector = &hdmi->connector.base;
> +       struct drm_connector_state *cstate = connector->state;
>         struct drm_crtc *crtc = encoder->crtc;
>         const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         union hdmi_infoframe frame;
>         int ret;
>
>         ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -                                                      hdmi->connector, mode);
> +                                                      connector, mode);
>         if (ret < 0) {
>                 DRM_ERROR("couldn't fill AVI infoframe\n");
>                 return;
>         }
>
>         drm_hdmi_avi_infoframe_quant_range(&frame.avi,
> -                                          hdmi->connector, mode,
> +                                          connector, mode,
>                                            vc4_encoder->limited_rgb_range ?
>                                            HDMI_QUANTIZATION_RANGE_LIMITED :
>                                            HDMI_QUANTIZATION_RANGE_FULL);
> @@ -628,7 +624,8 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_device *drm = hdmi->encoder->dev;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>         u32 hsm_clock = clk_get_rate(hdmi->hsm_clock);
>         unsigned long n, m;
> @@ -647,7 +644,7 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *hdmi)
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_crtc *crtc = encoder->crtc;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -685,7 +682,8 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
> +       struct drm_connector *connector = &hdmi->connector.base;
>         struct vc4_dev *vc4 = to_vc4_dev(encoder->dev);
>         int ret;
>
> @@ -702,8 +700,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> -       ret = snd_pcm_hw_constraint_eld(substream->runtime,
> -                                       hdmi->connector->eld);
> +       ret = snd_pcm_hw_constraint_eld(substream->runtime, connector->eld);
>         if (ret)
>                 return ret;
>
> @@ -717,7 +714,7 @@ static int vc4_hdmi_audio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>
>  static void vc4_hdmi_audio_reset(struct vc4_hdmi *hdmi)
>  {
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -751,7 +748,7 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                                     struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct device *dev = &hdmi->pdev->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
> @@ -824,7 +821,7 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                                   struct snd_soc_dai *dai)
>  {
>         struct vc4_hdmi *hdmi = dai_to_hdmi(dai);
> -       struct drm_encoder *encoder = hdmi->encoder;
> +       struct drm_encoder *encoder = &hdmi->encoder.base.base;
>         struct drm_device *drm = encoder->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(drm);
>
> @@ -868,9 +865,10 @@ static int vc4_hdmi_audio_eld_ctl_info(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
>         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
> -       uinfo->count = sizeof(hdmi->connector->eld);
> +       uinfo->count = sizeof(connector->eld);
>
>         return 0;
>  }
> @@ -880,9 +878,10 @@ static int vc4_hdmi_audio_eld_ctl_get(struct snd_kcontrol *kcontrol,
>  {
>         struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
>         struct vc4_hdmi *hdmi = snd_component_to_hdmi(component);
> +       struct drm_connector *connector = &hdmi->connector.base;
>
> -       memcpy(ucontrol->value.bytes.data, hdmi->connector->eld,
> -              sizeof(hdmi->connector->eld));
> +       memcpy(ucontrol->value.bytes.data, connector->eld,
> +              sizeof(connector->eld));
>
>         return 0;
>  }
> @@ -1221,7 +1220,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
>         struct vc4_hdmi *hdmi;
> -       struct vc4_hdmi_encoder *vc4_hdmi_encoder;
> +       struct drm_encoder *encoder;
>         struct device_node *ddc_node;
>         u32 value;
>         int ret;
> @@ -1230,14 +1229,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!hdmi)
>                 return -ENOMEM;
>
> -       vc4_hdmi_encoder = devm_kzalloc(dev, sizeof(*vc4_hdmi_encoder),
> -                                       GFP_KERNEL);
> -       if (!vc4_hdmi_encoder)
> -               return -ENOMEM;
> -       vc4_hdmi_encoder->base.type = VC4_ENCODER_TYPE_HDMI0;
> -       hdmi->encoder = &vc4_hdmi_encoder->base.base;
> -
> +       encoder = &hdmi->encoder.base.base;
> +       hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         hdmi->pdev = pdev;
> +
>         hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(hdmi->hdmicore_regs))
>                 return PTR_ERR(hdmi->hdmicore_regs);
> @@ -1325,15 +1320,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>         pm_runtime_enable(dev);
>
> -       drm_simple_encoder_init(drm, hdmi->encoder, DRM_MODE_ENCODER_TMDS);
> -       drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
> +       drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> +       drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
>
> -       hdmi->connector =
> -               vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
> -       if (IS_ERR(hdmi->connector)) {
> -               ret = PTR_ERR(hdmi->connector);
> +       ret = vc4_hdmi_connector_init(drm, hdmi, hdmi->ddc);
> +       if (ret)
>                 goto err_destroy_encoder;
> -       }
> +
>  #ifdef CONFIG_DRM_VC4_HDMI_CEC
>         hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                               vc4, "vc4",
> @@ -1343,7 +1336,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret < 0)
>                 goto err_destroy_conn;
>
> -       cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
> +       cec_fill_conn_info_from_drm(&conn_info, &hdmi->connector.base);
>         cec_s_conn_info(hdmi->cec_adap, &conn_info);
>
>         HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> @@ -1380,10 +1373,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_delete_cec_adap:
>         cec_delete_adapter(hdmi->cec_adap);
>  err_destroy_conn:
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
>  #endif
>  err_destroy_encoder:
> -       drm_encoder_cleanup(hdmi->encoder);
> +       drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> @@ -1401,8 +1394,8 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         struct vc4_hdmi *hdmi = vc4->hdmi;
>
>         cec_unregister_adapter(hdmi->cec_adap);
> -       vc4_hdmi_connector_destroy(hdmi->connector);
> -       drm_encoder_cleanup(hdmi->encoder);
> +       vc4_hdmi_connector_destroy(&hdmi->connector.base);
> +       drm_encoder_cleanup(&hdmi->encoder.base.base);
>
>         clk_disable_unprepare(hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 5ec5d1f6b1e6..17079a39f1b1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -8,6 +8,36 @@
>
>  #include "vc4_drv.h"
>
> +/* VC4 HDMI encoder KMS struct */
> +struct vc4_hdmi_encoder {
> +       struct vc4_encoder base;
> +       bool hdmi_monitor;
> +       bool limited_rgb_range;
> +};
> +
> +static inline struct vc4_hdmi_encoder *
> +to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> +{
> +       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> +}
> +
> +/* VC4 HDMI connector KMS struct */
> +struct vc4_hdmi_connector {
> +       struct drm_connector base;
> +
> +       /* Since the connector is attached to just the one encoder,
> +        * this is the reference to it so we can do the best_encoder()
> +        * hook.
> +        */
> +       struct drm_encoder *encoder;
> +};
> +
> +static inline struct vc4_hdmi_connector *
> +to_vc4_hdmi_connector(struct drm_connector *connector)
> +{
> +       return container_of(connector, struct vc4_hdmi_connector, base);
> +}
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -25,8 +55,8 @@ struct vc4_hdmi_audio {
>  struct vc4_hdmi {
>         struct platform_device *pdev;
>
> -       struct drm_encoder *encoder;
> -       struct drm_connector *connector;
> +       struct vc4_hdmi_encoder encoder;
> +       struct vc4_hdmi_connector connector;
>
>         struct vc4_hdmi_audio audio;
>
> @@ -53,34 +83,4 @@ struct vc4_hdmi {
>  #define HD_READ(offset) readl(vc4->hdmi->hd_regs + offset)
>  #define HD_WRITE(offset, val) writel(val, vc4->hdmi->hd_regs + offset)
>
> -/* VC4 HDMI encoder KMS struct */
> -struct vc4_hdmi_encoder {
> -       struct vc4_encoder base;
> -       bool hdmi_monitor;
> -       bool limited_rgb_range;
> -};
> -
> -static inline struct vc4_hdmi_encoder *
> -to_vc4_hdmi_encoder(struct drm_encoder *encoder)
> -{
> -       return container_of(encoder, struct vc4_hdmi_encoder, base.base);
> -}
> -
> -/* VC4 HDMI connector KMS struct */
> -struct vc4_hdmi_connector {
> -       struct drm_connector base;
> -
> -       /* Since the connector is attached to just the one encoder,
> -        * this is the reference to it so we can do the best_encoder()
> -        * hook.
> -        */
> -       struct drm_encoder *encoder;
> -};
> -
> -static inline struct vc4_hdmi_connector *
> -to_vc4_hdmi_connector(struct drm_connector *connector)
> -{
> -       return container_of(connector, struct vc4_hdmi_connector, base);
> -}
> -
>  #endif /* _VC4_HDMI_H_ */
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 12:32       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The unbind function needs to retrieve a vc4_hdmi structure pointer through
> the struct device that we're given since we want to support multiple HDMI
> controllers.
>
> However, our optional ASoC support doesn't make that trivial since it will
> overwrite the device drvdata if we use it, but obviously won't if we don't
> use it.
>
> Let's make sure the fields are at the proper offset to be able to cast
> between the snd_soc_card structure and the vc4_hdmi structure
> transparently so we can support both cases.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++--
>  2 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 09b297a1b39d..7cd1394c10fa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1200,6 +1200,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!vc4_hdmi)
>                 return -ENOMEM;
>
> +       dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
>         vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         vc4_hdmi->pdev = pdev;
> @@ -1362,7 +1363,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>  {
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
> -       struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
> +       struct vc4_hdmi *vc4_hdmi;
> +
> +       /*
> +        * ASoC makes it a bit hard to retrieve a pointer to the
> +        * vc4_hdmi structure. Registering the card will overwrite our
> +        * device drvdata with a pointer to the snd_soc_card structure,
> +        * which can then be used to retrieve whatever drvdata we want
> +        * to associate.
> +        *
> +        * However, that doesn't fly in the case where we wouldn't
> +        * register an ASoC card (because of an old DT that is missing
> +        * the dmas properties for example), then the card isn't
> +        * registered and the device drvdata wouldn't be set.
> +        *
> +        * We can deal with both cases by making sure a snd_soc_card
> +        * pointer and a vc4_hdmi structure are pointing to the same
> +        * memory address, so we can treat them indistinctly without any
> +        * issue.
> +        */
> +       BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
> +       BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
> +       vc4_hdmi = dev_get_drvdata(dev);
>
>         cec_unregister_adapter(vc4_hdmi->cec_adap);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 749a807cd1f3..d43462789450 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -53,13 +53,13 @@ struct vc4_hdmi_audio {
>
>  /* General HDMI hardware state. */
>  struct vc4_hdmi {
> +       struct vc4_hdmi_audio audio;
> +
>         struct platform_device *pdev;
>
>         struct vc4_hdmi_encoder encoder;
>         struct vc4_hdmi_connector connector;
>
> -       struct vc4_hdmi_audio audio;
> -
>         struct i2c_adapter *ddc;
>         void __iomem *hdmicore_regs;
>         void __iomem *hd_regs;
> --
> git-series 0.9.1

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

* Re: [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
@ 2020-07-28 12:32       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The unbind function needs to retrieve a vc4_hdmi structure pointer through
> the struct device that we're given since we want to support multiple HDMI
> controllers.
>
> However, our optional ASoC support doesn't make that trivial since it will
> overwrite the device drvdata if we use it, but obviously won't if we don't
> use it.
>
> Let's make sure the fields are at the proper offset to be able to cast
> between the snd_soc_card structure and the vc4_hdmi structure
> transparently so we can support both cases.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++--
>  2 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 09b297a1b39d..7cd1394c10fa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1200,6 +1200,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!vc4_hdmi)
>                 return -ENOMEM;
>
> +       dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
>         vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         vc4_hdmi->pdev = pdev;
> @@ -1362,7 +1363,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>  {
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
> -       struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
> +       struct vc4_hdmi *vc4_hdmi;
> +
> +       /*
> +        * ASoC makes it a bit hard to retrieve a pointer to the
> +        * vc4_hdmi structure. Registering the card will overwrite our
> +        * device drvdata with a pointer to the snd_soc_card structure,
> +        * which can then be used to retrieve whatever drvdata we want
> +        * to associate.
> +        *
> +        * However, that doesn't fly in the case where we wouldn't
> +        * register an ASoC card (because of an old DT that is missing
> +        * the dmas properties for example), then the card isn't
> +        * registered and the device drvdata wouldn't be set.
> +        *
> +        * We can deal with both cases by making sure a snd_soc_card
> +        * pointer and a vc4_hdmi structure are pointing to the same
> +        * memory address, so we can treat them indistinctly without any
> +        * issue.
> +        */
> +       BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
> +       BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
> +       vc4_hdmi = dev_get_drvdata(dev);
>
>         cec_unregister_adapter(vc4_hdmi->cec_adap);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 749a807cd1f3..d43462789450 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -53,13 +53,13 @@ struct vc4_hdmi_audio {
>
>  /* General HDMI hardware state. */
>  struct vc4_hdmi {
> +       struct vc4_hdmi_audio audio;
> +
>         struct platform_device *pdev;
>
>         struct vc4_hdmi_encoder encoder;
>         struct vc4_hdmi_connector connector;
>
> -       struct vc4_hdmi_audio audio;
> -
>         struct i2c_adapter *ddc;
>         void __iomem *hdmicore_regs;
>         void __iomem *hd_regs;
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
@ 2020-07-28 12:32       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The unbind function needs to retrieve a vc4_hdmi structure pointer through
> the struct device that we're given since we want to support multiple HDMI
> controllers.
>
> However, our optional ASoC support doesn't make that trivial since it will
> overwrite the device drvdata if we use it, but obviously won't if we don't
> use it.
>
> Let's make sure the fields are at the proper offset to be able to cast
> between the snd_soc_card structure and the vc4_hdmi structure
> transparently so we can support both cases.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 24 +++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  4 ++--
>  2 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 09b297a1b39d..7cd1394c10fa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1200,6 +1200,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (!vc4_hdmi)
>                 return -ENOMEM;
>
> +       dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
>         vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
>         vc4_hdmi->pdev = pdev;
> @@ -1362,7 +1363,28 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>  {
>         struct drm_device *drm = dev_get_drvdata(master);
>         struct vc4_dev *vc4 = drm->dev_private;
> -       struct vc4_hdmi *vc4_hdmi = vc4->hdmi;
> +       struct vc4_hdmi *vc4_hdmi;
> +
> +       /*
> +        * ASoC makes it a bit hard to retrieve a pointer to the
> +        * vc4_hdmi structure. Registering the card will overwrite our
> +        * device drvdata with a pointer to the snd_soc_card structure,
> +        * which can then be used to retrieve whatever drvdata we want
> +        * to associate.
> +        *
> +        * However, that doesn't fly in the case where we wouldn't
> +        * register an ASoC card (because of an old DT that is missing
> +        * the dmas properties for example), then the card isn't
> +        * registered and the device drvdata wouldn't be set.
> +        *
> +        * We can deal with both cases by making sure a snd_soc_card
> +        * pointer and a vc4_hdmi structure are pointing to the same
> +        * memory address, so we can treat them indistinctly without any
> +        * issue.
> +        */
> +       BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
> +       BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
> +       vc4_hdmi = dev_get_drvdata(dev);
>
>         cec_unregister_adapter(vc4_hdmi->cec_adap);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 749a807cd1f3..d43462789450 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -53,13 +53,13 @@ struct vc4_hdmi_audio {
>
>  /* General HDMI hardware state. */
>  struct vc4_hdmi {
> +       struct vc4_hdmi_audio audio;
> +
>         struct platform_device *pdev;
>
>         struct vc4_hdmi_encoder encoder;
>         struct vc4_hdmi_connector connector;
>
> -       struct vc4_hdmi_audio audio;
> -
>         struct i2c_adapter *ddc;
>         void __iomem *hdmicore_regs;
>         void __iomem *hd_regs;
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 12:37       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI controllers found in the BCM2711 has a pretty different clock and
> registers areas than found in the older BCM283x SoCs.
>
> Let's create a variant structure to store the various adjustments we'll
> need later on, and a function to get the resources needed for one
> particular version.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++-
>  2 files changed, 51 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ec7710dfd04e..ac021e07a8cb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1179,28 +1179,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>  };
>  #endif
>
> -static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
> +static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>  {
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       struct cec_connector_info conn_info;
> -#endif
> -       struct platform_device *pdev = to_platform_device(dev);
> -       struct drm_device *drm = dev_get_drvdata(master);
> -       struct vc4_hdmi *vc4_hdmi;
> -       struct drm_encoder *encoder;
> -       struct device_node *ddc_node;
> -       u32 value;
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       struct device *dev = &pdev->dev;
>         int ret;
>
> -       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
> -       if (!vc4_hdmi)
> -               return -ENOMEM;
> -
> -       dev_set_drvdata(dev, vc4_hdmi);
> -       encoder = &vc4_hdmi->encoder.base.base;
> -       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> -       vc4_hdmi->pdev = pdev;
> -
>         vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(vc4_hdmi->hdmicore_regs))
>                 return PTR_ERR(vc4_hdmi->hdmicore_regs);
> @@ -1212,6 +1196,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
>         vc4_hdmi->hdmi_regset.regs = hdmi_regs;
>         vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
> +
>         vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
>         vc4_hdmi->hd_regset.regs = hd_regs;
>         vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
> @@ -1223,12 +1208,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                         DRM_ERROR("Failed to get pixel clock\n");
>                 return ret;
>         }
> +
>         vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
>         if (IS_ERR(vc4_hdmi->hsm_clock)) {
>                 DRM_ERROR("Failed to get HDMI state machine clock\n");
>                 return PTR_ERR(vc4_hdmi->hsm_clock);
>         }
>
> +       return 0;
> +}
> +
> +static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
> +{
> +#ifdef CONFIG_DRM_VC4_HDMI_CEC
> +       struct cec_connector_info conn_info;
> +#endif
> +       const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
> +       struct platform_device *pdev = to_platform_device(dev);
> +       struct drm_device *drm = dev_get_drvdata(master);
> +       struct vc4_hdmi *vc4_hdmi;
> +       struct drm_encoder *encoder;
> +       struct device_node *ddc_node;
> +       u32 value;
> +       int ret;
> +
> +       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
> +       if (!vc4_hdmi)
> +               return -ENOMEM;
> +
> +       dev_set_drvdata(dev, vc4_hdmi);
> +       encoder = &vc4_hdmi->encoder.base.base;
> +       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> +       vc4_hdmi->pdev = pdev;
> +       vc4_hdmi->variant = variant;
> +
> +       ret = variant->init_resources(vc4_hdmi);
> +       if (ret)
> +               return ret;
> +
>         ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
>         if (!ddc_node) {
>                 DRM_ERROR("Failed to find ddc node in device tree\n");
> @@ -1404,8 +1421,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .init_resources         = vc4_hdmi_init_resources,
> +};
> +
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> -       { .compatible = "brcm,bcm2835-hdmi" },
> +       { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
>         {}
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 674541493909..0eaf979fe811 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>         return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>  }
>
> +struct vc4_hdmi;
> +
> +struct vc4_hdmi_variant {
> +       /* Callback to get the resources (memory region, interrupts,
> +        * clocks, etc) for that variant.
> +        */
> +       int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
> +};
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -39,6 +48,7 @@ struct vc4_hdmi {
>         struct vc4_hdmi_audio audio;
>
>         struct platform_device *pdev;
> +       const struct vc4_hdmi_variant *variant;
>
>         struct vc4_hdmi_encoder encoder;
>         struct drm_connector connector;
> --
> git-series 0.9.1

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

* Re: [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant
@ 2020-07-28 12:37       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI controllers found in the BCM2711 has a pretty different clock and
> registers areas than found in the older BCM283x SoCs.
>
> Let's create a variant structure to store the various adjustments we'll
> need later on, and a function to get the resources needed for one
> particular version.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++-
>  2 files changed, 51 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ec7710dfd04e..ac021e07a8cb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1179,28 +1179,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>  };
>  #endif
>
> -static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
> +static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>  {
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       struct cec_connector_info conn_info;
> -#endif
> -       struct platform_device *pdev = to_platform_device(dev);
> -       struct drm_device *drm = dev_get_drvdata(master);
> -       struct vc4_hdmi *vc4_hdmi;
> -       struct drm_encoder *encoder;
> -       struct device_node *ddc_node;
> -       u32 value;
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       struct device *dev = &pdev->dev;
>         int ret;
>
> -       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
> -       if (!vc4_hdmi)
> -               return -ENOMEM;
> -
> -       dev_set_drvdata(dev, vc4_hdmi);
> -       encoder = &vc4_hdmi->encoder.base.base;
> -       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> -       vc4_hdmi->pdev = pdev;
> -
>         vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(vc4_hdmi->hdmicore_regs))
>                 return PTR_ERR(vc4_hdmi->hdmicore_regs);
> @@ -1212,6 +1196,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
>         vc4_hdmi->hdmi_regset.regs = hdmi_regs;
>         vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
> +
>         vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
>         vc4_hdmi->hd_regset.regs = hd_regs;
>         vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
> @@ -1223,12 +1208,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                         DRM_ERROR("Failed to get pixel clock\n");
>                 return ret;
>         }
> +
>         vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
>         if (IS_ERR(vc4_hdmi->hsm_clock)) {
>                 DRM_ERROR("Failed to get HDMI state machine clock\n");
>                 return PTR_ERR(vc4_hdmi->hsm_clock);
>         }
>
> +       return 0;
> +}
> +
> +static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
> +{
> +#ifdef CONFIG_DRM_VC4_HDMI_CEC
> +       struct cec_connector_info conn_info;
> +#endif
> +       const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
> +       struct platform_device *pdev = to_platform_device(dev);
> +       struct drm_device *drm = dev_get_drvdata(master);
> +       struct vc4_hdmi *vc4_hdmi;
> +       struct drm_encoder *encoder;
> +       struct device_node *ddc_node;
> +       u32 value;
> +       int ret;
> +
> +       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
> +       if (!vc4_hdmi)
> +               return -ENOMEM;
> +
> +       dev_set_drvdata(dev, vc4_hdmi);
> +       encoder = &vc4_hdmi->encoder.base.base;
> +       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> +       vc4_hdmi->pdev = pdev;
> +       vc4_hdmi->variant = variant;
> +
> +       ret = variant->init_resources(vc4_hdmi);
> +       if (ret)
> +               return ret;
> +
>         ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
>         if (!ddc_node) {
>                 DRM_ERROR("Failed to find ddc node in device tree\n");
> @@ -1404,8 +1421,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .init_resources         = vc4_hdmi_init_resources,
> +};
> +
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> -       { .compatible = "brcm,bcm2835-hdmi" },
> +       { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
>         {}
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 674541493909..0eaf979fe811 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>         return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>  }
>
> +struct vc4_hdmi;
> +
> +struct vc4_hdmi_variant {
> +       /* Callback to get the resources (memory region, interrupts,
> +        * clocks, etc) for that variant.
> +        */
> +       int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
> +};
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -39,6 +48,7 @@ struct vc4_hdmi {
>         struct vc4_hdmi_audio audio;
>
>         struct platform_device *pdev;
> +       const struct vc4_hdmi_variant *variant;
>
>         struct vc4_hdmi_encoder encoder;
>         struct drm_connector connector;
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant
@ 2020-07-28 12:37       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI controllers found in the BCM2711 has a pretty different clock and
> registers areas than found in the older BCM283x SoCs.
>
> Let's create a variant structure to store the various adjustments we'll
> need later on, and a function to get the resources needed for one
> particular version.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 61 +++++++++++++++++++++++------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 10 ++++++-
>  2 files changed, 51 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ec7710dfd04e..ac021e07a8cb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1179,28 +1179,12 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>  };
>  #endif
>
> -static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
> +static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>  {
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       struct cec_connector_info conn_info;
> -#endif
> -       struct platform_device *pdev = to_platform_device(dev);
> -       struct drm_device *drm = dev_get_drvdata(master);
> -       struct vc4_hdmi *vc4_hdmi;
> -       struct drm_encoder *encoder;
> -       struct device_node *ddc_node;
> -       u32 value;
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       struct device *dev = &pdev->dev;
>         int ret;
>
> -       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
> -       if (!vc4_hdmi)
> -               return -ENOMEM;
> -
> -       dev_set_drvdata(dev, vc4_hdmi);
> -       encoder = &vc4_hdmi->encoder.base.base;
> -       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> -       vc4_hdmi->pdev = pdev;
> -
>         vc4_hdmi->hdmicore_regs = vc4_ioremap_regs(pdev, 0);
>         if (IS_ERR(vc4_hdmi->hdmicore_regs))
>                 return PTR_ERR(vc4_hdmi->hdmicore_regs);
> @@ -1212,6 +1196,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
>         vc4_hdmi->hdmi_regset.regs = hdmi_regs;
>         vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
> +
>         vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
>         vc4_hdmi->hd_regset.regs = hd_regs;
>         vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
> @@ -1223,12 +1208,44 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                         DRM_ERROR("Failed to get pixel clock\n");
>                 return ret;
>         }
> +
>         vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
>         if (IS_ERR(vc4_hdmi->hsm_clock)) {
>                 DRM_ERROR("Failed to get HDMI state machine clock\n");
>                 return PTR_ERR(vc4_hdmi->hsm_clock);
>         }
>
> +       return 0;
> +}
> +
> +static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
> +{
> +#ifdef CONFIG_DRM_VC4_HDMI_CEC
> +       struct cec_connector_info conn_info;
> +#endif
> +       const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
> +       struct platform_device *pdev = to_platform_device(dev);
> +       struct drm_device *drm = dev_get_drvdata(master);
> +       struct vc4_hdmi *vc4_hdmi;
> +       struct drm_encoder *encoder;
> +       struct device_node *ddc_node;
> +       u32 value;
> +       int ret;
> +
> +       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
> +       if (!vc4_hdmi)
> +               return -ENOMEM;
> +
> +       dev_set_drvdata(dev, vc4_hdmi);
> +       encoder = &vc4_hdmi->encoder.base.base;
> +       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> +       vc4_hdmi->pdev = pdev;
> +       vc4_hdmi->variant = variant;
> +
> +       ret = variant->init_resources(vc4_hdmi);
> +       if (ret)
> +               return ret;
> +
>         ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
>         if (!ddc_node) {
>                 DRM_ERROR("Failed to find ddc node in device tree\n");
> @@ -1404,8 +1421,12 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>         return 0;
>  }
>
> +static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .init_resources         = vc4_hdmi_init_resources,
> +};
> +
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> -       { .compatible = "brcm,bcm2835-hdmi" },
> +       { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
>         {}
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 674541493909..0eaf979fe811 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,6 +21,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>         return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>  }
>
> +struct vc4_hdmi;
> +
> +struct vc4_hdmi_variant {
> +       /* Callback to get the resources (memory region, interrupts,
> +        * clocks, etc) for that variant.
> +        */
> +       int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
> +};
> +
>  /* HDMI audio information */
>  struct vc4_hdmi_audio {
>         struct snd_soc_card card;
> @@ -39,6 +48,7 @@ struct vc4_hdmi {
>         struct vc4_hdmi_audio audio;
>
>         struct platform_device *pdev;
> +       const struct vc4_hdmi_variant *variant;
>
>         struct vc4_hdmi_encoder encoder;
>         struct drm_connector connector;
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-28 12:59       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:59 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI controllers found in the BCM2711 have most of the registers
> reorganized in multiple registers areas and at different offsets than
> previously found.
>
> The logic however remains pretty much the same, so it doesn't really make
> sense to create a whole new driver and we should share the code as much as
> possible.
>
> Let's implement some indirection to wrap around a register and depending on
> the variant will lookup the associated register on that particular variant.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c      | 427 ++++++++++++++---------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h      |  12 +-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h      |  92 +------
>  4 files changed, 464 insertions(+), 308 deletions(-)
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ac021e07a8cb..a4fed1439bf3 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -50,62 +50,13 @@
>  #include "media/cec.h"
>  #include "vc4_drv.h"
>  #include "vc4_hdmi.h"
> +#include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
>  #define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>  #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
>
> -static const struct debugfs_reg32 hdmi_regs[] = {
> -       VC4_REG32(VC4_HDMI_CORE_REV),
> -       VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
> -       VC4_REG32(VC4_HDMI_HOTPLUG_INT),
> -       VC4_REG32(VC4_HDMI_HOTPLUG),
> -       VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
> -       VC4_REG32(VC4_HDMI_MAI_CONFIG),
> -       VC4_REG32(VC4_HDMI_MAI_FORMAT),
> -       VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
> -       VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
> -       VC4_REG32(VC4_HDMI_HORZA),
> -       VC4_REG32(VC4_HDMI_HORZB),
> -       VC4_REG32(VC4_HDMI_FIFO_CTL),
> -       VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
> -       VC4_REG32(VC4_HDMI_VERTA0),
> -       VC4_REG32(VC4_HDMI_VERTA1),
> -       VC4_REG32(VC4_HDMI_VERTB0),
> -       VC4_REG32(VC4_HDMI_VERTB1),
> -       VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
> -       VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
> -
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
> -       VC4_REG32(VC4_HDMI_CPU_STATUS),
> -       VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
> -
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
> -};
> -
> -static const struct debugfs_reg32 hd_regs[] = {
> -       VC4_REG32(VC4_HD_M_CTL),
> -       VC4_REG32(VC4_HD_MAI_CTL),
> -       VC4_REG32(VC4_HD_MAI_THR),
> -       VC4_REG32(VC4_HD_MAI_FMT),
> -       VC4_REG32(VC4_HD_MAI_SMP),
> -       VC4_REG32(VC4_HD_VID_CTL),
> -       VC4_REG32(VC4_HD_CSC_CTL),
> -       VC4_REG32(VC4_HD_FRAME_COUNT),
> -};
> -
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>  {
>         struct drm_info_node *node = (struct drm_info_node *)m->private;
> @@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>         if (drm_probe_ddc(vc4_hdmi->ddc))
>                 return connector_status_connected;
>
> -       if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
> +       if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
>                 return connector_status_connected;
>         cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
>         return connector_status_disconnected;
> @@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         u32 packet_id = type - 0x80;
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                  HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                  HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
>
> -       return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
> +       return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
>                           BIT(packet_id)), 100);
>  }
>
> @@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
>  {
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         u32 packet_id = frame->any.type - 0x80;
> -       u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
> +       const struct vc4_hdmi_register *ram_packet_start =
> +               &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
> +       u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
> +       void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
> +                                                      ram_packet_start->reg);
>         uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
>         ssize_t len, i;
>         int ret;
>
> -       WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +       WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                     VC4_HDMI_RAM_PACKET_ENABLE),
>                   "Packet RAM has to be on to store the packet.");
>
> @@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
>         }
>
>         for (i = 0; i < len; i += 7) {
> -               HDMI_WRITE(packet_reg,
> -                          buffer[i + 0] << 0 |
> -                          buffer[i + 1] << 8 |
> -                          buffer[i + 2] << 16);
> +               writel(buffer[i + 0] << 0 |
> +                      buffer[i + 1] << 8 |
> +                      buffer[i + 2] << 16,
> +                      base + packet_reg);
>                 packet_reg += 4;
>
> -               HDMI_WRITE(packet_reg,
> -                          buffer[i + 3] << 0 |
> -                          buffer[i + 4] << 8 |
> -                          buffer[i + 5] << 16 |
> -                          buffer[i + 6] << 24);
> +               writel(buffer[i + 3] << 0 |
> +                      buffer[i + 4] << 8 |
> +                      buffer[i + 5] << 16 |
> +                      buffer[i + 6] << 24,
> +                      base + packet_reg);
>                 packet_reg += 4;
>         }
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                  HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
> -       ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                  HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
> +       ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
>                         BIT(packet_id)), 100);
>         if (ret)
>                 DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
> @@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         int ret;
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
>
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
>         clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
> @@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
>                    VC4_HDMI_SW_RESET_HDMI |
>                    VC4_HDMI_SW_RESET_FORMAT_DETECT);
>
> -       HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
>
>         /* PHY should be in reset, like
>          * vc4_hdmi_encoder_disable() does.
>          */
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
>
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 drm_print_regset32(&p, &vc4_hdmi->hd_regset);
>         }
>
> -       HD_WRITE(VC4_HD_VID_CTL, 0);
> +       HDMI_WRITE(HDMI_VID_CTL, 0);
>
> -       HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                  HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +       HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                  HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
>                    VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
>
> -       HDMI_WRITE(VC4_HDMI_HORZA,
> +       HDMI_WRITE(HDMI_HORZA,
>                    (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
>                    (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
>                    VC4_SET_FIELD(mode->hdisplay * pixel_rep,
>                                  VC4_HDMI_HORZA_HAP));
>
> -       HDMI_WRITE(VC4_HDMI_HORZB,
> +       HDMI_WRITE(HDMI_HORZB,
>                    VC4_SET_FIELD((mode->htotal -
>                                   mode->hsync_end) * pixel_rep,
>                                  VC4_HDMI_HORZB_HBP) |
> @@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                                   mode->hdisplay) * pixel_rep,
>                                  VC4_HDMI_HORZB_HFP));
>
> -       HDMI_WRITE(VC4_HDMI_VERTA0, verta);
> -       HDMI_WRITE(VC4_HDMI_VERTA1, verta);
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
>
> -       HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
> -       HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
>
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
>         csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
>                                 VC4_HD_CSC_CTL_ORDER);
> @@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
>                                          VC4_HD_CSC_CTL_MODE);
>
> -               HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
> -               HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
> -               HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
>                 vc4_encoder->limited_rgb_range = true;
>         } else {
>                 vc4_encoder->limited_rgb_range = false;
>         }
>
>         /* The RGB order applies even when CSC is disabled. */
> -       HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
>
> -       HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
> +       HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 drm_print_regset32(&p, &vc4_hdmi->hd_regset);
>         }
>
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                HD_READ(VC4_HD_VID_CTL) |
> -                VC4_HD_VID_CTL_ENABLE |
> -                VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> -                VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) |
> +                  VC4_HD_VID_CTL_ENABLE |
> +                  VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> +                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
>
>         if (vc4_encoder->hdmi_monitor) {
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                            VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
>
> -               ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                                VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
>         } else {
> -               HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                          HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +               HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                          HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                            ~(VC4_HDMI_RAM_PACKET_ENABLE));
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                            ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
>
> -               ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                                  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
> @@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_encoder->hdmi_monitor) {
>                 u32 drift;
>
> -               WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                           VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                            VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
>
> -               HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> +               HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
>                            VC4_HDMI_RAM_PACKET_ENABLE);
>
>                 vc4_hdmi_set_infoframes(encoder);
>
> -               drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
> +               drift = HDMI_READ(HDMI_FIFO_CTL);
>                 drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
>
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift | VC4_HDMI_FIFO_CTL_RECENTER);
>                 usleep_range(1000, 1100);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift | VC4_HDMI_FIFO_CTL_RECENTER);
>
> -               ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
> +               ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
>                                VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> @@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
>                                      VC4_HD_MAI_SMP_M_SHIFT) + 1,
>                                     &n, &m);
>
> -       HD_WRITE(VC4_HD_MAI_SMP,
> -                VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
> -                VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
> +       HDMI_WRITE(HDMI_MAI_SMP,
> +                  VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
> +                  VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
>  }
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
> @@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
>         do_div(tmp, 128 * samplerate);
>         cts = tmp;
>
> -       HDMI_WRITE(VC4_HDMI_CRP_CFG,
> +       HDMI_WRITE(HDMI_CRP_CFG,
>                    VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
>                    VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
>
> @@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
>          * providing a CTS_1 value.  The two CTS values are alternated
>          * between based on the period fields
>          */
> -       HDMI_WRITE(VC4_HDMI_CTS_0, cts);
> -       HDMI_WRITE(VC4_HDMI_CTS_1, cts);
> +       HDMI_WRITE(HDMI_CTS_0, cts);
> +       HDMI_WRITE(HDMI_CTS_1, cts);
>  }
>
>  static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
> @@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>          * If the HDMI encoder hasn't probed, or the encoder is
>          * currently in DVI mode, treat the codec dai as missing.
>          */
> -       if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +       if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> @@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
>         if (ret)
>                 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
>
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
>  }
>
>  static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
> @@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>         vc4_hdmi->audio.channels = params_channels(params);
>         vc4_hdmi->audio.samplerate = params_rate(params);
>
> -       HD_WRITE(VC4_HD_MAI_CTL,
> -                VC4_HD_MAI_CTL_RESET |
> -                VC4_HD_MAI_CTL_FLUSH |
> -                VC4_HD_MAI_CTL_DLATE |
> -                VC4_HD_MAI_CTL_ERRORE |
> -                VC4_HD_MAI_CTL_ERRORF);
> +       HDMI_WRITE(HDMI_MAI_CTL,
> +                  VC4_HD_MAI_CTL_RESET |
> +                  VC4_HD_MAI_CTL_FLUSH |
> +                  VC4_HD_MAI_CTL_DLATE |
> +                  VC4_HD_MAI_CTL_ERRORE |
> +                  VC4_HD_MAI_CTL_ERRORF);
>
>         vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
>
> @@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>
>         /* Set the MAI threshold.  This logic mimics the firmware's. */
>         if (vc4_hdmi->audio.samplerate > 96000) {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
>         } else if (vc4_hdmi->audio.samplerate > 48000) {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
>         } else {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
>         }
>
> -       HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
> +       HDMI_WRITE(HDMI_MAI_CONFIG,
>                    VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
>                    VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
>
> @@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                         channel_map |= i << (3 * i);
>         }
>
> -       HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
> -       HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
> +       HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
> +       HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
>         vc4_hdmi_set_n_cts(vc4_hdmi);
>
>         return 0;
> @@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 vc4_hdmi_set_audio_infoframe(encoder);
> -               HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
> -                          HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
> +               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                          HDMI_READ(HDMI_TX_PHY_CTL_0) &
>                            ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> -               HD_WRITE(VC4_HD_MAI_CTL,
> -                        VC4_SET_FIELD(vc4_hdmi->audio.channels,
> -                                      VC4_HD_MAI_CTL_CHNUM) |
> -                        VC4_HD_MAI_CTL_ENABLE);
> +
> +               HDMI_WRITE(HDMI_MAI_CTL,
> +                          VC4_SET_FIELD(vc4_hdmi->audio.channels,
> +                                        VC4_HD_MAI_CTL_CHNUM) |
> +                          VC4_HD_MAI_CTL_ENABLE);
>                 break;
>         case SNDRV_PCM_TRIGGER_STOP:
> -               HD_WRITE(VC4_HD_MAI_CTL,
> -                        VC4_HD_MAI_CTL_DLATE |
> -                        VC4_HD_MAI_CTL_ERRORE |
> -                        VC4_HD_MAI_CTL_ERRORF);
> -               HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
> -                          HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
> +               HDMI_WRITE(HDMI_MAI_CTL,
> +                          VC4_HD_MAI_CTL_DLATE |
> +                          VC4_HD_MAI_CTL_ERRORE |
> +                          VC4_HD_MAI_CTL_ERRORF);
> +               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                          HDMI_READ(HDMI_TX_PHY_CTL_0) |
>                            VC4_HDMI_TX_PHY_RNG_PWRDN);
>                 break;
>         default:
> @@ -946,6 +902,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
>
>  static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>  {
> +       const struct vc4_hdmi_register *mai_data =
> +               &vc4_hdmi->variant->registers[HDMI_MAI_DATA];
>         struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
>         struct snd_soc_card *card = &vc4_hdmi->audio.card;
>         struct device *dev = &vc4_hdmi->pdev->dev;
> @@ -958,6 +916,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>                 return 0;
>         }
>
> +       if (mai_data->reg != VC4_HD) {
> +               WARN_ONCE(true, "MAI isn't in the HD block\n");
> +               return -EINVAL;
> +       }
> +
>         /*
>          * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve
>          * the bus address specified in the DT, because the physical address
> @@ -966,7 +929,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>          * This VC/MMU should probably be exposed to avoid this kind of hacks.
>          */
>         addr = of_get_address(dev->of_node, 1, NULL, NULL);
> -       vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
> +       vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
>         vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
>         vc4_hdmi->audio.dma_data.maxburst = 2;
>
> @@ -1058,7 +1021,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
>         msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
>                                         VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
>         for (i = 0; i < msg->len; i += 4) {
> -               u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
> +               u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i);
>
>                 msg->msg[i] = val & 0xff;
>                 msg->msg[i + 1] = (val >> 8) & 0xff;
> @@ -1070,26 +1033,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
>  static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
>  {
>         struct vc4_hdmi *vc4_hdmi = priv;
> -       u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
> +       u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
>         u32 cntrl1, cntrl5;
>
>         if (!(stat & VC4_HDMI_CPU_CEC))
>                 return IRQ_NONE;
>         vc4_hdmi->cec_rx_msg.len = 0;
> -       cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> -       cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
> +       cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
> +       cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
>         vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
>         if (vc4_hdmi->cec_irq_was_rx) {
>                 vc4_cec_read_msg(vc4_hdmi, cntrl1);
>                 cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
>                 cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
>         } else {
>                 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
>                 cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
>         }
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
> -       HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
> +       HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
>
>         return IRQ_WAKE_THREAD;
>  }
> @@ -1099,7 +1062,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
>         struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
>         /* clock period in microseconds */
>         const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
> -       u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
> +       u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
>
>         val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
>                  VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
> @@ -1108,30 +1071,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
>                ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
>
>         if (enable) {
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
>                            VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
> -                        ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
> -                        ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
> -                        ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
> -                        ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
> -                        ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
> -                        ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
> -                        ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
> -                        ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
> -                        ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
> -                        ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
> -                        ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
> -                        ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
> -                        ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
> -
> -               HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_2,
> +                          ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
> +                          ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
> +                          ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
> +                          ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
> +                          ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
> +               HDMI_WRITE(HDMI_CEC_CNTRL_3,
> +                          ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
> +                          ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
> +                          ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
> +                          ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
> +               HDMI_WRITE(HDMI_CEC_CNTRL_4,
> +                          ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
> +                          ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
> +                          ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
> +                          ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
> +
> +               HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
>         } else {
> -               HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
> +               HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
>                            VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
>         }
>         return 0;
> @@ -1141,8 +1104,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
>  {
>         struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
>
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
> -                  (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1,
> +                  (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
>                    (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
>         return 0;
>  }
> @@ -1155,20 +1118,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
>         unsigned int i;
>
>         for (i = 0; i < msg->len; i += 4)
> -               HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
> +               HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i,
>                            (msg->msg[i]) |
>                            (msg->msg[i + 1] << 8) |
>                            (msg->msg[i + 2] << 16) |
>                            (msg->msg[i + 3] << 24));
>
> -       val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> +       val = HDMI_READ(HDMI_CEC_CNTRL_1);
>         val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
>         val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
>         val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
>         val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
>
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
>         return 0;
>  }
>
> @@ -1179,6 +1142,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>  };
>  #endif
>
> +static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
> +                                struct debugfs_regset32 *regset,
> +                                enum vc4_hdmi_regs reg)
> +{
> +       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> +       struct debugfs_reg32 *regs, *new_regs;
> +       unsigned int count = 0;
> +       unsigned int i;
> +
> +       regs = kcalloc(variant->num_registers, sizeof(*regs),
> +                      GFP_KERNEL);
> +       if (!regs)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < variant->num_registers; i++) {
> +               const struct vc4_hdmi_register *field = &variant->registers[i];
> +
> +               if (field->reg != reg)
> +                       continue;
> +
> +               regs[count].name = field->name;
> +               regs[count].offset = field->offset;
> +               count++;
> +       }
> +
> +       new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
> +       if (!new_regs)
> +               return -ENOMEM;
> +
> +       regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
> +       regset->regs = new_regs;
> +       regset->nregs = count;
> +
> +       return 0;
> +}
> +
>  static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>  {
>         struct platform_device *pdev = vc4_hdmi->pdev;
> @@ -1193,13 +1192,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>         if (IS_ERR(vc4_hdmi->hd_regs))
>                 return PTR_ERR(vc4_hdmi->hd_regs);
>
> -       vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
> -       vc4_hdmi->hdmi_regset.regs = hdmi_regs;
> -       vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
> +       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
> +       if (ret)
> +               return ret;
>
> -       vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
> -       vc4_hdmi->hd_regset.regs = hd_regs;
> -       vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
> +       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
> +       if (ret)
> +               return ret;
>
>         vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
>         if (IS_ERR(vc4_hdmi->pixel_clock)) {
> @@ -1294,12 +1293,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>
>         /* HDMI core must be enabled. */
> -       if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
> -               HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
> +       if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
> +               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
>                 udelay(1);
> -               HD_WRITE(VC4_HD_M_CTL, 0);
> +               HDMI_WRITE(HDMI_M_CTL, 0);
>
> -               HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
> +               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
>         }
>         pm_runtime_enable(dev);
>
> @@ -1322,8 +1321,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
>         cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
>
> -       HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> -       value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> +       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> +       value = HDMI_READ(HDMI_CEC_CNTRL_1);
>         value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
>         /*
>          * Set the logical address to Unregistered and set the clock
> @@ -1332,7 +1331,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>          */
>         value |= VC4_HDMI_CEC_ADDR_MASK |
>                  (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
>         ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
>                                         vc4_cec_irq_handler,
>                                         vc4_cec_irq_handler_thread, 0,
> @@ -1395,6 +1394,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
>         vc4_hdmi = dev_get_drvdata(dev);
>
> +       kfree(vc4_hdmi->hdmi_regset.regs);
> +       kfree(vc4_hdmi->hd_regset.regs);
> +
>         cec_unregister_adapter(vc4_hdmi->cec_adap);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
> @@ -1422,6 +1424,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  }
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .registers              = vc4_hdmi_fields,
> +       .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
> +
>         .init_resources         = vc4_hdmi_init_resources,
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0eaf979fe811..b36e0210671f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_hdmi;
> +struct vc4_hdmi_register;
>
>  struct vc4_hdmi_variant {
> +       /* List of the registers available on that variant */
> +       const struct vc4_hdmi_register *registers;
> +
> +       /* Number of registers on that variant */
> +       unsigned int num_registers;
> +
>         /* Callback to get the resources (memory region, interrupts,
>          * clocks, etc) for that variant.
>          */
> @@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>         return container_of(_encoder, struct vc4_hdmi, encoder);
>  }
>
> -#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
> -#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
> -#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
> -#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
> -
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> new file mode 100644
> index 000000000000..bc47cc9bc883
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -0,0 +1,241 @@
> +#ifndef _VC4_HDMI_REGS_H_
> +#define _VC4_HDMI_REGS_H_
> +
> +#include "vc4_hdmi.h"
> +
> +#define VC4_HDMI_PACKET_STRIDE                 0x24
> +
> +enum vc4_hdmi_regs {
> +       VC4_INVALID = 0,
> +       VC4_HDMI,
> +       VC4_HD,
> +};
> +
> +enum vc4_hdmi_field {
> +       HDMI_AUDIO_PACKET_CONFIG,
> +       HDMI_CEC_CNTRL_1,
> +       HDMI_CEC_CNTRL_2,
> +       HDMI_CEC_CNTRL_3,
> +       HDMI_CEC_CNTRL_4,
> +       HDMI_CEC_CNTRL_5,
> +       HDMI_CEC_CPU_CLEAR,
> +       HDMI_CEC_CPU_MASK_CLEAR,
> +       HDMI_CEC_CPU_MASK_SET,
> +       HDMI_CEC_CPU_MASK_STATUS,
> +       HDMI_CEC_CPU_STATUS,
> +
> +       /*
> +        * Transmit data, first byte is low byte of the 32-bit reg.
> +        * MSB of each byte transmitted first.
> +        */
> +       HDMI_CEC_RX_DATA_1,
> +       HDMI_CEC_RX_DATA_2,
> +       HDMI_CEC_RX_DATA_3,
> +       HDMI_CEC_RX_DATA_4,
> +       HDMI_CEC_TX_DATA_1,
> +       HDMI_CEC_TX_DATA_2,
> +       HDMI_CEC_TX_DATA_3,
> +       HDMI_CEC_TX_DATA_4,
> +       HDMI_CORE_REV,
> +       HDMI_CRP_CFG,
> +       HDMI_CSC_12_11,
> +       HDMI_CSC_14_13,
> +       HDMI_CSC_22_21,
> +       HDMI_CSC_24_23,
> +       HDMI_CSC_32_31,
> +       HDMI_CSC_34_33,
> +       HDMI_CSC_CTL,
> +
> +       /*
> +        * 20-bit fields containing CTS values to be transmitted if
> +        * !EXTERNAL_CTS_EN
> +        */
> +       HDMI_CTS_0,
> +       HDMI_CTS_1,
> +       HDMI_FIFO_CTL,
> +       HDMI_FRAME_COUNT,
> +       HDMI_HORZA,
> +       HDMI_HORZB,
> +       HDMI_HOTPLUG,
> +       HDMI_HOTPLUG_INT,
> +
> +       /*
> +        * 3 bits per field, where each field maps from that
> +        * corresponding MAI bus channel to the given HDMI channel.
> +        */
> +       HDMI_MAI_CHANNEL_MAP,
> +       HDMI_MAI_CONFIG,
> +       HDMI_MAI_CTL,
> +
> +       /*
> +        * Register for DMAing in audio data to be transported over
> +        * the MAI bus to the Falcon core.
> +        */
> +       HDMI_MAI_DATA,
> +
> +       /* Format header to be placed on the MAI data. Unused. */
> +       HDMI_MAI_FMT,
> +
> +       /* Last received format word on the MAI bus. */
> +       HDMI_MAI_FORMAT,
> +       HDMI_MAI_SMP,
> +       HDMI_MAI_THR,
> +       HDMI_M_CTL,
> +       HDMI_RAM_PACKET_CONFIG,
> +       HDMI_RAM_PACKET_START,
> +       HDMI_RAM_PACKET_STATUS,
> +       HDMI_SCHEDULER_CONTROL,
> +       HDMI_SW_RESET_CONTROL,
> +       HDMI_TX_PHY_CTL_0,
> +       HDMI_TX_PHY_RESET_CTL,
> +       HDMI_VERTA0,
> +       HDMI_VERTA1,
> +       HDMI_VERTB0,
> +       HDMI_VERTB1,
> +       HDMI_VID_CTL,
> +};
> +
> +struct vc4_hdmi_register {
> +       char *name;
> +       enum vc4_hdmi_regs reg;
> +       unsigned int offset;
> +};
> +
> +#define _VC4_REG(_base, _reg, _offset) \
> +       [_reg] = {                              \
> +               .name = #_reg,                  \
> +               .reg = _base,                   \
> +               .offset = _offset,              \
> +       }
> +
> +#define VC4_HD_REG(reg, offset)                _VC4_REG(VC4_HD, reg, offset)
> +#define VC4_HDMI_REG(reg, offset)      _VC4_REG(VC4_HDMI, reg, offset)
> +
> +static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
> +       VC4_HD_REG(HDMI_M_CTL, 0x000c),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0018),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x001c),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x0020),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x002c),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0038),
> +       VC4_HD_REG(HDMI_CSC_CTL, 0x0040),
> +       VC4_HD_REG(HDMI_CSC_12_11, 0x0044),
> +       VC4_HD_REG(HDMI_CSC_14_13, 0x0048),
> +       VC4_HD_REG(HDMI_CSC_22_21, 0x004c),
> +       VC4_HD_REG(HDMI_CSC_24_23, 0x0050),
> +       VC4_HD_REG(HDMI_CSC_32_31, 0x0054),
> +       VC4_HD_REG(HDMI_CSC_34_33, 0x0058),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068),
> +
> +       VC4_HDMI_REG(HDMI_CORE_REV, 0x0000),
> +       VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004),
> +       VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c),
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094),
> +       VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x00ac),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x00b0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x00c4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x00c8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x00cc),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x00d0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x00d4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x00d8),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118),
> +       VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0),
> +       VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
> +};
> +
> +static inline
> +void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
> +                                       enum vc4_hdmi_regs reg)
> +{
> +       switch (reg) {
> +       case VC4_HD:
> +               return hdmi->hd_regs;
> +
> +       case VC4_HDMI:
> +               return hdmi->hdmicore_regs;
> +
> +       default:
> +               return NULL;
> +       }
> +
> +       return NULL;
> +}
> +
> +static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
> +                               enum vc4_hdmi_regs reg)
> +{
> +       const struct vc4_hdmi_register *field;
> +       const struct vc4_hdmi_variant *variant = hdmi->variant;
> +       void __iomem *base;
> +
> +       if (reg > variant->num_registers) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Invalid register ID %u\n", reg);
> +               return 0;
> +       }
> +
> +       field = &variant->registers[reg];
> +       base = __vc4_hdmi_get_field_base(hdmi, field->reg);
> +       if (!base) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Unknown register ID %u\n", reg);
> +               return 0;
> +       }
> +
> +       return readl(base + field->offset);
> +}
> +#define HDMI_READ(reg)         vc4_hdmi_read(vc4_hdmi, reg)
> +
> +static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
> +                                 enum vc4_hdmi_regs reg,
> +                                 u32 value)
> +{
> +       const struct vc4_hdmi_register *field;
> +       const struct vc4_hdmi_variant *variant = hdmi->variant;
> +       void __iomem *base;
> +
> +       if (reg > variant->num_registers) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Invalid register ID %u\n", reg);
> +               return;
> +       }
> +
> +       field = &variant->registers[reg];
> +       base = __vc4_hdmi_get_field_base(hdmi, field->reg);
> +       if (!base)
> +               return;
> +
> +       writel(value, base + field->offset);
> +}
> +#define HDMI_WRITE(reg, val)   vc4_hdmi_write(vc4_hdmi, reg, val)
> +
> +#endif /* _VC4_HDMI_REGS_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index c0031ab19689..d1e8961edaa0 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -493,32 +493,16 @@
>
>  #define SCALER5_DLIST_START                    0x00004000
>
> -#define VC4_HDMI_CORE_REV                      0x000
> -
> -#define VC4_HDMI_SW_RESET_CONTROL              0x004
>  # define VC4_HDMI_SW_RESET_FORMAT_DETECT       BIT(1)
>  # define VC4_HDMI_SW_RESET_HDMI                        BIT(0)
>
> -#define VC4_HDMI_HOTPLUG_INT                   0x008
> -
> -#define VC4_HDMI_HOTPLUG                       0x00c
>  # define VC4_HDMI_HOTPLUG_CONNECTED            BIT(0)
>
> -/* 3 bits per field, where each field maps from that corresponding MAI
> - * bus channel to the given HDMI channel.
> - */
> -#define VC4_HDMI_MAI_CHANNEL_MAP               0x090
> -
> -#define VC4_HDMI_MAI_CONFIG                    0x094
>  # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE            BIT(27)
>  # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE               BIT(26)
>  # define VC4_HDMI_MAI_CHANNEL_MASK_MASK                        VC4_MASK(15, 0)
>  # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT               0
>
> -/* Last received format word on the MAI bus. */
> -#define VC4_HDMI_MAI_FORMAT                    0x098
> -
> -#define VC4_HDMI_AUDIO_PACKET_CONFIG           0x09c
>  # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT                BIT(29)
>  # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS  BIT(24)
>  # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT            BIT(19)
> @@ -532,12 +516,8 @@
>  # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK                   VC4_MASK(7, 0)
>  # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT                  0
>
> -#define VC4_HDMI_RAM_PACKET_CONFIG             0x0a0
>  # define VC4_HDMI_RAM_PACKET_ENABLE            BIT(16)
>
> -#define VC4_HDMI_RAM_PACKET_STATUS             0x0a4
> -
> -#define VC4_HDMI_CRP_CFG                       0x0a8
>  /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
>   * of pixel clock.
>   */
> @@ -551,23 +531,12 @@
>  # define VC4_HDMI_CRP_CFG_N_MASK               VC4_MASK(19, 0)
>  # define VC4_HDMI_CRP_CFG_N_SHIFT              0
>
> -/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */
> -#define VC4_HDMI_CTS_0                         0x0ac
> -#define VC4_HDMI_CTS_1                         0x0b0
> -/* 20-bit fields containing number of clocks to send CTS0/1 before
> - * switching to the other one.
> - */
> -#define VC4_HDMI_CTS_PERIOD_0                  0x0b4
> -#define VC4_HDMI_CTS_PERIOD_1                  0x0b8
> -
> -#define VC4_HDMI_HORZA                         0x0c4
>  # define VC4_HDMI_HORZA_VPOS                   BIT(14)
>  # define VC4_HDMI_HORZA_HPOS                   BIT(13)
>  /* Horizontal active pixels (hdisplay). */
>  # define VC4_HDMI_HORZA_HAP_MASK               VC4_MASK(12, 0)
>  # define VC4_HDMI_HORZA_HAP_SHIFT              0
>
> -#define VC4_HDMI_HORZB                         0x0c8
>  /* Horizontal pack porch (htotal - hsync_end). */
>  # define VC4_HDMI_HORZB_HBP_MASK               VC4_MASK(29, 20)
>  # define VC4_HDMI_HORZB_HBP_SHIFT              20
> @@ -578,7 +547,6 @@
>  # define VC4_HDMI_HORZB_HFP_MASK               VC4_MASK(9, 0)
>  # define VC4_HDMI_HORZB_HFP_SHIFT              0
>
> -#define VC4_HDMI_FIFO_CTL                      0x05c
>  # define VC4_HDMI_FIFO_CTL_RECENTER_DONE       BIT(14)
>  # define VC4_HDMI_FIFO_CTL_USE_EMPTY           BIT(13)
>  # define VC4_HDMI_FIFO_CTL_ON_VB               BIT(7)
> @@ -591,15 +559,12 @@
>  # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N      BIT(0)
>  # define VC4_HDMI_FIFO_VALID_WRITE_MASK                0xefff
>
> -#define VC4_HDMI_SCHEDULER_CONTROL             0x0c0
>  # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
>  # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
>  # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT        BIT(3)
>  # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE        BIT(1)
>  # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI  BIT(0)
>
> -#define VC4_HDMI_VERTA0                                0x0cc
> -#define VC4_HDMI_VERTA1                                0x0d4
>  /* Vertical sync pulse (vsync_end - vsync_start). */
>  # define VC4_HDMI_VERTA_VSP_MASK               VC4_MASK(24, 20)
>  # define VC4_HDMI_VERTA_VSP_SHIFT              20
> @@ -610,8 +575,6 @@
>  # define VC4_HDMI_VERTA_VAL_MASK               VC4_MASK(12, 0)
>  # define VC4_HDMI_VERTA_VAL_SHIFT              0
>
> -#define VC4_HDMI_VERTB0                                0x0d0
> -#define VC4_HDMI_VERTB1                                0x0d8
>  /* Vertical sync pulse offset (for interlaced) */
>  # define VC4_HDMI_VERTB_VSPO_MASK              VC4_MASK(21, 9)
>  # define VC4_HDMI_VERTB_VSPO_SHIFT             9
> @@ -619,7 +582,6 @@
>  # define VC4_HDMI_VERTB_VBP_MASK               VC4_MASK(8, 0)
>  # define VC4_HDMI_VERTB_VBP_SHIFT              0
>
> -#define VC4_HDMI_CEC_CNTRL_1                   0x0e8
>  /* Set when the transmission has ended. */
>  # define VC4_HDMI_CEC_TX_EOM                   BIT(31)
>  /* If set, transmission was acked on the 1st or 2nd attempt (only one
> @@ -660,7 +622,6 @@
>  /* Set these fields to how many bit clock cycles get to that many
>   * microseconds.
>   */
> -#define VC4_HDMI_CEC_CNTRL_2                   0x0ec
>  # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK      VC4_MASK(30, 24)
>  # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK      VC4_MASK(23, 17)
> @@ -672,7 +633,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_400_US_MASK       VC4_MASK(4, 0)
>  # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT      0
>
> -#define VC4_HDMI_CEC_CNTRL_3                   0x0f0
>  # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK      VC4_MASK(31, 24)
>  # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK      VC4_MASK(23, 16)
> @@ -682,7 +642,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT     0
>
> -#define VC4_HDMI_CEC_CNTRL_4                   0x0f4
>  # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK      VC4_MASK(31, 24)
>  # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK      VC4_MASK(23, 16)
> @@ -692,7 +651,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT     0
>
> -#define VC4_HDMI_CEC_CNTRL_5                   0x0f8
>  # define VC4_HDMI_CEC_TX_SW_RESET              BIT(27)
>  # define VC4_HDMI_CEC_RX_SW_RESET              BIT(26)
>  # define VC4_HDMI_CEC_PAD_SW_RESET             BIT(25)
> @@ -705,39 +663,11 @@
>  # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT     0
>
> -/* Transmit data, first byte is low byte of the 32-bit reg.  MSB of
> - * each byte transmitted first.
> - */
> -#define VC4_HDMI_CEC_TX_DATA_1                 0x0fc
> -#define VC4_HDMI_CEC_TX_DATA_2                 0x100
> -#define VC4_HDMI_CEC_TX_DATA_3                 0x104
> -#define VC4_HDMI_CEC_TX_DATA_4                 0x108
> -#define VC4_HDMI_CEC_RX_DATA_1                 0x10c
> -#define VC4_HDMI_CEC_RX_DATA_2                 0x110
> -#define VC4_HDMI_CEC_RX_DATA_3                 0x114
> -#define VC4_HDMI_CEC_RX_DATA_4                 0x118
> -
> -#define VC4_HDMI_TX_PHY_RESET_CTL              0x2c0
> -
> -#define VC4_HDMI_TX_PHY_CTL0                   0x2c4
>  # define VC4_HDMI_TX_PHY_RNG_PWRDN             BIT(25)
>
> -/* Interrupt status bits */
> -#define VC4_HDMI_CPU_STATUS                    0x340
> -#define VC4_HDMI_CPU_SET                       0x344
> -#define VC4_HDMI_CPU_CLEAR                     0x348
>  # define VC4_HDMI_CPU_CEC                      BIT(6)
>  # define VC4_HDMI_CPU_HOTPLUG                  BIT(0)
>
> -#define VC4_HDMI_CPU_MASK_STATUS               0x34c
> -#define VC4_HDMI_CPU_MASK_SET                  0x350
> -#define VC4_HDMI_CPU_MASK_CLEAR                        0x354
> -
> -#define VC4_HDMI_GCP(x)                                (0x400 + ((x) * 0x4))
> -#define VC4_HDMI_RAM_PACKET(x)                 (0x400 + ((x) * 0x24))
> -#define VC4_HDMI_PACKET_STRIDE                 0x24
> -
> -#define VC4_HD_M_CTL                           0x00c
>  /* Debug: Current receive value on the CEC pad. */
>  # define VC4_HD_CECRXD                         BIT(9)
>  /* Debug: Override CEC output to 0. */
> @@ -747,7 +677,6 @@
>  # define VC4_HD_M_SW_RST                       BIT(2)
>  # define VC4_HD_M_ENABLE                       BIT(0)
>
> -#define VC4_HD_MAI_CTL                         0x014
>  /* Set when audio stream is received at a slower rate than the
>   * sampling period, so MAI fifo goes empty.  Write 1 to clear.
>   */
> @@ -772,7 +701,6 @@
>  /* Single-shot reset bit.  Read value is undefined. */
>  # define VC4_HD_MAI_CTL_RESET                  BIT(0)
>
> -#define VC4_HD_MAI_THR                         0x018
>  # define VC4_HD_MAI_THR_PANICHIGH_MASK         VC4_MASK(29, 24)
>  # define VC4_HD_MAI_THR_PANICHIGH_SHIFT                24
>  # define VC4_HD_MAI_THR_PANICLOW_MASK          VC4_MASK(21, 16)
> @@ -782,31 +710,20 @@
>  # define VC4_HD_MAI_THR_DREQLOW_MASK           VC4_MASK(5, 0)
>  # define VC4_HD_MAI_THR_DREQLOW_SHIFT          0
>
> -/* Format header to be placed on the MAI data. Unused. */
> -#define VC4_HD_MAI_FMT                         0x01c
> -
> -/* Register for DMAing in audio data to be transported over the MAI
> - * bus to the Falcon core.
> - */
> -#define VC4_HD_MAI_DATA                                0x020
> -
>  /* Divider from HDMI HSM clock to MAI serial clock.  Sampling period
>   * converges to N / (M + 1) cycles.
>   */
> -#define VC4_HD_MAI_SMP                         0x02c
>  # define VC4_HD_MAI_SMP_N_MASK                 VC4_MASK(31, 8)
>  # define VC4_HD_MAI_SMP_N_SHIFT                        8
>  # define VC4_HD_MAI_SMP_M_MASK                 VC4_MASK(7, 0)
>  # define VC4_HD_MAI_SMP_M_SHIFT                        0
>
> -#define VC4_HD_VID_CTL                         0x038
>  # define VC4_HD_VID_CTL_ENABLE                 BIT(31)
>  # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE       BIT(30)
>  # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET    BIT(29)
>  # define VC4_HD_VID_CTL_VSYNC_LOW              BIT(28)
>  # define VC4_HD_VID_CTL_HSYNC_LOW              BIT(27)
>
> -#define VC4_HD_CSC_CTL                         0x040
>  # define VC4_HD_CSC_CTL_ORDER_MASK             VC4_MASK(7, 5)
>  # define VC4_HD_CSC_CTL_ORDER_SHIFT            5
>  # define VC4_HD_CSC_CTL_ORDER_RGB              0
> @@ -824,15 +741,6 @@
>  # define VC4_HD_CSC_CTL_RGB2YCC                        BIT(1)
>  # define VC4_HD_CSC_CTL_ENABLE                 BIT(0)
>
> -#define VC4_HD_CSC_12_11                       0x044
> -#define VC4_HD_CSC_14_13                       0x048
> -#define VC4_HD_CSC_22_21                       0x04c
> -#define VC4_HD_CSC_24_23                       0x050
> -#define VC4_HD_CSC_32_31                       0x054
> -#define VC4_HD_CSC_34_33                       0x058
> -
> -#define VC4_HD_FRAME_COUNT                     0x068
> -
>  /* HVS display list information. */
>  #define HVS_BOOTLOADER_DLIST_END                32
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction
@ 2020-07-28 12:59       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:59 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI controllers found in the BCM2711 have most of the registers
> reorganized in multiple registers areas and at different offsets than
> previously found.
>
> The logic however remains pretty much the same, so it doesn't really make
> sense to create a whole new driver and we should share the code as much as
> possible.
>
> Let's implement some indirection to wrap around a register and depending on
> the variant will lookup the associated register on that particular variant.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c      | 427 ++++++++++++++---------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h      |  12 +-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h      |  92 +------
>  4 files changed, 464 insertions(+), 308 deletions(-)
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ac021e07a8cb..a4fed1439bf3 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -50,62 +50,13 @@
>  #include "media/cec.h"
>  #include "vc4_drv.h"
>  #include "vc4_hdmi.h"
> +#include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
>  #define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>  #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
>
> -static const struct debugfs_reg32 hdmi_regs[] = {
> -       VC4_REG32(VC4_HDMI_CORE_REV),
> -       VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
> -       VC4_REG32(VC4_HDMI_HOTPLUG_INT),
> -       VC4_REG32(VC4_HDMI_HOTPLUG),
> -       VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
> -       VC4_REG32(VC4_HDMI_MAI_CONFIG),
> -       VC4_REG32(VC4_HDMI_MAI_FORMAT),
> -       VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
> -       VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
> -       VC4_REG32(VC4_HDMI_HORZA),
> -       VC4_REG32(VC4_HDMI_HORZB),
> -       VC4_REG32(VC4_HDMI_FIFO_CTL),
> -       VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
> -       VC4_REG32(VC4_HDMI_VERTA0),
> -       VC4_REG32(VC4_HDMI_VERTA1),
> -       VC4_REG32(VC4_HDMI_VERTB0),
> -       VC4_REG32(VC4_HDMI_VERTB1),
> -       VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
> -       VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
> -
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
> -       VC4_REG32(VC4_HDMI_CPU_STATUS),
> -       VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
> -
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
> -};
> -
> -static const struct debugfs_reg32 hd_regs[] = {
> -       VC4_REG32(VC4_HD_M_CTL),
> -       VC4_REG32(VC4_HD_MAI_CTL),
> -       VC4_REG32(VC4_HD_MAI_THR),
> -       VC4_REG32(VC4_HD_MAI_FMT),
> -       VC4_REG32(VC4_HD_MAI_SMP),
> -       VC4_REG32(VC4_HD_VID_CTL),
> -       VC4_REG32(VC4_HD_CSC_CTL),
> -       VC4_REG32(VC4_HD_FRAME_COUNT),
> -};
> -
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>  {
>         struct drm_info_node *node = (struct drm_info_node *)m->private;
> @@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>         if (drm_probe_ddc(vc4_hdmi->ddc))
>                 return connector_status_connected;
>
> -       if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
> +       if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
>                 return connector_status_connected;
>         cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
>         return connector_status_disconnected;
> @@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         u32 packet_id = type - 0x80;
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                  HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                  HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
>
> -       return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
> +       return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
>                           BIT(packet_id)), 100);
>  }
>
> @@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
>  {
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         u32 packet_id = frame->any.type - 0x80;
> -       u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
> +       const struct vc4_hdmi_register *ram_packet_start =
> +               &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
> +       u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
> +       void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
> +                                                      ram_packet_start->reg);
>         uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
>         ssize_t len, i;
>         int ret;
>
> -       WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +       WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                     VC4_HDMI_RAM_PACKET_ENABLE),
>                   "Packet RAM has to be on to store the packet.");
>
> @@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
>         }
>
>         for (i = 0; i < len; i += 7) {
> -               HDMI_WRITE(packet_reg,
> -                          buffer[i + 0] << 0 |
> -                          buffer[i + 1] << 8 |
> -                          buffer[i + 2] << 16);
> +               writel(buffer[i + 0] << 0 |
> +                      buffer[i + 1] << 8 |
> +                      buffer[i + 2] << 16,
> +                      base + packet_reg);
>                 packet_reg += 4;
>
> -               HDMI_WRITE(packet_reg,
> -                          buffer[i + 3] << 0 |
> -                          buffer[i + 4] << 8 |
> -                          buffer[i + 5] << 16 |
> -                          buffer[i + 6] << 24);
> +               writel(buffer[i + 3] << 0 |
> +                      buffer[i + 4] << 8 |
> +                      buffer[i + 5] << 16 |
> +                      buffer[i + 6] << 24,
> +                      base + packet_reg);
>                 packet_reg += 4;
>         }
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                  HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
> -       ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                  HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
> +       ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
>                         BIT(packet_id)), 100);
>         if (ret)
>                 DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
> @@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         int ret;
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
>
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
>         clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
> @@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
>                    VC4_HDMI_SW_RESET_HDMI |
>                    VC4_HDMI_SW_RESET_FORMAT_DETECT);
>
> -       HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
>
>         /* PHY should be in reset, like
>          * vc4_hdmi_encoder_disable() does.
>          */
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
>
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 drm_print_regset32(&p, &vc4_hdmi->hd_regset);
>         }
>
> -       HD_WRITE(VC4_HD_VID_CTL, 0);
> +       HDMI_WRITE(HDMI_VID_CTL, 0);
>
> -       HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                  HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +       HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                  HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
>                    VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
>
> -       HDMI_WRITE(VC4_HDMI_HORZA,
> +       HDMI_WRITE(HDMI_HORZA,
>                    (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
>                    (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
>                    VC4_SET_FIELD(mode->hdisplay * pixel_rep,
>                                  VC4_HDMI_HORZA_HAP));
>
> -       HDMI_WRITE(VC4_HDMI_HORZB,
> +       HDMI_WRITE(HDMI_HORZB,
>                    VC4_SET_FIELD((mode->htotal -
>                                   mode->hsync_end) * pixel_rep,
>                                  VC4_HDMI_HORZB_HBP) |
> @@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                                   mode->hdisplay) * pixel_rep,
>                                  VC4_HDMI_HORZB_HFP));
>
> -       HDMI_WRITE(VC4_HDMI_VERTA0, verta);
> -       HDMI_WRITE(VC4_HDMI_VERTA1, verta);
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
>
> -       HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
> -       HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
>
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
>         csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
>                                 VC4_HD_CSC_CTL_ORDER);
> @@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
>                                          VC4_HD_CSC_CTL_MODE);
>
> -               HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
> -               HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
> -               HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
>                 vc4_encoder->limited_rgb_range = true;
>         } else {
>                 vc4_encoder->limited_rgb_range = false;
>         }
>
>         /* The RGB order applies even when CSC is disabled. */
> -       HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
>
> -       HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
> +       HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 drm_print_regset32(&p, &vc4_hdmi->hd_regset);
>         }
>
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                HD_READ(VC4_HD_VID_CTL) |
> -                VC4_HD_VID_CTL_ENABLE |
> -                VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> -                VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) |
> +                  VC4_HD_VID_CTL_ENABLE |
> +                  VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> +                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
>
>         if (vc4_encoder->hdmi_monitor) {
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                            VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
>
> -               ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                                VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
>         } else {
> -               HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                          HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +               HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                          HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                            ~(VC4_HDMI_RAM_PACKET_ENABLE));
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                            ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
>
> -               ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                                  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
> @@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_encoder->hdmi_monitor) {
>                 u32 drift;
>
> -               WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                           VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                            VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
>
> -               HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> +               HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
>                            VC4_HDMI_RAM_PACKET_ENABLE);
>
>                 vc4_hdmi_set_infoframes(encoder);
>
> -               drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
> +               drift = HDMI_READ(HDMI_FIFO_CTL);
>                 drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
>
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift | VC4_HDMI_FIFO_CTL_RECENTER);
>                 usleep_range(1000, 1100);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift | VC4_HDMI_FIFO_CTL_RECENTER);
>
> -               ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
> +               ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
>                                VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> @@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
>                                      VC4_HD_MAI_SMP_M_SHIFT) + 1,
>                                     &n, &m);
>
> -       HD_WRITE(VC4_HD_MAI_SMP,
> -                VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
> -                VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
> +       HDMI_WRITE(HDMI_MAI_SMP,
> +                  VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
> +                  VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
>  }
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
> @@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
>         do_div(tmp, 128 * samplerate);
>         cts = tmp;
>
> -       HDMI_WRITE(VC4_HDMI_CRP_CFG,
> +       HDMI_WRITE(HDMI_CRP_CFG,
>                    VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
>                    VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
>
> @@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
>          * providing a CTS_1 value.  The two CTS values are alternated
>          * between based on the period fields
>          */
> -       HDMI_WRITE(VC4_HDMI_CTS_0, cts);
> -       HDMI_WRITE(VC4_HDMI_CTS_1, cts);
> +       HDMI_WRITE(HDMI_CTS_0, cts);
> +       HDMI_WRITE(HDMI_CTS_1, cts);
>  }
>
>  static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
> @@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>          * If the HDMI encoder hasn't probed, or the encoder is
>          * currently in DVI mode, treat the codec dai as missing.
>          */
> -       if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +       if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> @@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
>         if (ret)
>                 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
>
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
>  }
>
>  static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
> @@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>         vc4_hdmi->audio.channels = params_channels(params);
>         vc4_hdmi->audio.samplerate = params_rate(params);
>
> -       HD_WRITE(VC4_HD_MAI_CTL,
> -                VC4_HD_MAI_CTL_RESET |
> -                VC4_HD_MAI_CTL_FLUSH |
> -                VC4_HD_MAI_CTL_DLATE |
> -                VC4_HD_MAI_CTL_ERRORE |
> -                VC4_HD_MAI_CTL_ERRORF);
> +       HDMI_WRITE(HDMI_MAI_CTL,
> +                  VC4_HD_MAI_CTL_RESET |
> +                  VC4_HD_MAI_CTL_FLUSH |
> +                  VC4_HD_MAI_CTL_DLATE |
> +                  VC4_HD_MAI_CTL_ERRORE |
> +                  VC4_HD_MAI_CTL_ERRORF);
>
>         vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
>
> @@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>
>         /* Set the MAI threshold.  This logic mimics the firmware's. */
>         if (vc4_hdmi->audio.samplerate > 96000) {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
>         } else if (vc4_hdmi->audio.samplerate > 48000) {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
>         } else {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
>         }
>
> -       HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
> +       HDMI_WRITE(HDMI_MAI_CONFIG,
>                    VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
>                    VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
>
> @@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                         channel_map |= i << (3 * i);
>         }
>
> -       HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
> -       HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
> +       HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
> +       HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
>         vc4_hdmi_set_n_cts(vc4_hdmi);
>
>         return 0;
> @@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 vc4_hdmi_set_audio_infoframe(encoder);
> -               HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
> -                          HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
> +               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                          HDMI_READ(HDMI_TX_PHY_CTL_0) &
>                            ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> -               HD_WRITE(VC4_HD_MAI_CTL,
> -                        VC4_SET_FIELD(vc4_hdmi->audio.channels,
> -                                      VC4_HD_MAI_CTL_CHNUM) |
> -                        VC4_HD_MAI_CTL_ENABLE);
> +
> +               HDMI_WRITE(HDMI_MAI_CTL,
> +                          VC4_SET_FIELD(vc4_hdmi->audio.channels,
> +                                        VC4_HD_MAI_CTL_CHNUM) |
> +                          VC4_HD_MAI_CTL_ENABLE);
>                 break;
>         case SNDRV_PCM_TRIGGER_STOP:
> -               HD_WRITE(VC4_HD_MAI_CTL,
> -                        VC4_HD_MAI_CTL_DLATE |
> -                        VC4_HD_MAI_CTL_ERRORE |
> -                        VC4_HD_MAI_CTL_ERRORF);
> -               HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
> -                          HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
> +               HDMI_WRITE(HDMI_MAI_CTL,
> +                          VC4_HD_MAI_CTL_DLATE |
> +                          VC4_HD_MAI_CTL_ERRORE |
> +                          VC4_HD_MAI_CTL_ERRORF);
> +               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                          HDMI_READ(HDMI_TX_PHY_CTL_0) |
>                            VC4_HDMI_TX_PHY_RNG_PWRDN);
>                 break;
>         default:
> @@ -946,6 +902,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
>
>  static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>  {
> +       const struct vc4_hdmi_register *mai_data =
> +               &vc4_hdmi->variant->registers[HDMI_MAI_DATA];
>         struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
>         struct snd_soc_card *card = &vc4_hdmi->audio.card;
>         struct device *dev = &vc4_hdmi->pdev->dev;
> @@ -958,6 +916,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>                 return 0;
>         }
>
> +       if (mai_data->reg != VC4_HD) {
> +               WARN_ONCE(true, "MAI isn't in the HD block\n");
> +               return -EINVAL;
> +       }
> +
>         /*
>          * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve
>          * the bus address specified in the DT, because the physical address
> @@ -966,7 +929,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>          * This VC/MMU should probably be exposed to avoid this kind of hacks.
>          */
>         addr = of_get_address(dev->of_node, 1, NULL, NULL);
> -       vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
> +       vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
>         vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
>         vc4_hdmi->audio.dma_data.maxburst = 2;
>
> @@ -1058,7 +1021,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
>         msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
>                                         VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
>         for (i = 0; i < msg->len; i += 4) {
> -               u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
> +               u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i);
>
>                 msg->msg[i] = val & 0xff;
>                 msg->msg[i + 1] = (val >> 8) & 0xff;
> @@ -1070,26 +1033,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
>  static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
>  {
>         struct vc4_hdmi *vc4_hdmi = priv;
> -       u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
> +       u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
>         u32 cntrl1, cntrl5;
>
>         if (!(stat & VC4_HDMI_CPU_CEC))
>                 return IRQ_NONE;
>         vc4_hdmi->cec_rx_msg.len = 0;
> -       cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> -       cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
> +       cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
> +       cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
>         vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
>         if (vc4_hdmi->cec_irq_was_rx) {
>                 vc4_cec_read_msg(vc4_hdmi, cntrl1);
>                 cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
>                 cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
>         } else {
>                 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
>                 cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
>         }
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
> -       HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
> +       HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
>
>         return IRQ_WAKE_THREAD;
>  }
> @@ -1099,7 +1062,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
>         struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
>         /* clock period in microseconds */
>         const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
> -       u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
> +       u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
>
>         val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
>                  VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
> @@ -1108,30 +1071,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
>                ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
>
>         if (enable) {
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
>                            VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
> -                        ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
> -                        ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
> -                        ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
> -                        ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
> -                        ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
> -                        ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
> -                        ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
> -                        ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
> -                        ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
> -                        ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
> -                        ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
> -                        ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
> -                        ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
> -
> -               HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_2,
> +                          ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
> +                          ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
> +                          ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
> +                          ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
> +                          ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
> +               HDMI_WRITE(HDMI_CEC_CNTRL_3,
> +                          ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
> +                          ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
> +                          ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
> +                          ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
> +               HDMI_WRITE(HDMI_CEC_CNTRL_4,
> +                          ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
> +                          ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
> +                          ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
> +                          ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
> +
> +               HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
>         } else {
> -               HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
> +               HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
>                            VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
>         }
>         return 0;
> @@ -1141,8 +1104,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
>  {
>         struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
>
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
> -                  (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1,
> +                  (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
>                    (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
>         return 0;
>  }
> @@ -1155,20 +1118,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
>         unsigned int i;
>
>         for (i = 0; i < msg->len; i += 4)
> -               HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
> +               HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i,
>                            (msg->msg[i]) |
>                            (msg->msg[i + 1] << 8) |
>                            (msg->msg[i + 2] << 16) |
>                            (msg->msg[i + 3] << 24));
>
> -       val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> +       val = HDMI_READ(HDMI_CEC_CNTRL_1);
>         val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
>         val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
>         val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
>         val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
>
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
>         return 0;
>  }
>
> @@ -1179,6 +1142,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>  };
>  #endif
>
> +static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
> +                                struct debugfs_regset32 *regset,
> +                                enum vc4_hdmi_regs reg)
> +{
> +       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> +       struct debugfs_reg32 *regs, *new_regs;
> +       unsigned int count = 0;
> +       unsigned int i;
> +
> +       regs = kcalloc(variant->num_registers, sizeof(*regs),
> +                      GFP_KERNEL);
> +       if (!regs)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < variant->num_registers; i++) {
> +               const struct vc4_hdmi_register *field = &variant->registers[i];
> +
> +               if (field->reg != reg)
> +                       continue;
> +
> +               regs[count].name = field->name;
> +               regs[count].offset = field->offset;
> +               count++;
> +       }
> +
> +       new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
> +       if (!new_regs)
> +               return -ENOMEM;
> +
> +       regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
> +       regset->regs = new_regs;
> +       regset->nregs = count;
> +
> +       return 0;
> +}
> +
>  static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>  {
>         struct platform_device *pdev = vc4_hdmi->pdev;
> @@ -1193,13 +1192,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>         if (IS_ERR(vc4_hdmi->hd_regs))
>                 return PTR_ERR(vc4_hdmi->hd_regs);
>
> -       vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
> -       vc4_hdmi->hdmi_regset.regs = hdmi_regs;
> -       vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
> +       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
> +       if (ret)
> +               return ret;
>
> -       vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
> -       vc4_hdmi->hd_regset.regs = hd_regs;
> -       vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
> +       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
> +       if (ret)
> +               return ret;
>
>         vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
>         if (IS_ERR(vc4_hdmi->pixel_clock)) {
> @@ -1294,12 +1293,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>
>         /* HDMI core must be enabled. */
> -       if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
> -               HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
> +       if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
> +               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
>                 udelay(1);
> -               HD_WRITE(VC4_HD_M_CTL, 0);
> +               HDMI_WRITE(HDMI_M_CTL, 0);
>
> -               HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
> +               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
>         }
>         pm_runtime_enable(dev);
>
> @@ -1322,8 +1321,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
>         cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
>
> -       HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> -       value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> +       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> +       value = HDMI_READ(HDMI_CEC_CNTRL_1);
>         value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
>         /*
>          * Set the logical address to Unregistered and set the clock
> @@ -1332,7 +1331,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>          */
>         value |= VC4_HDMI_CEC_ADDR_MASK |
>                  (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
>         ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
>                                         vc4_cec_irq_handler,
>                                         vc4_cec_irq_handler_thread, 0,
> @@ -1395,6 +1394,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
>         vc4_hdmi = dev_get_drvdata(dev);
>
> +       kfree(vc4_hdmi->hdmi_regset.regs);
> +       kfree(vc4_hdmi->hd_regset.regs);
> +
>         cec_unregister_adapter(vc4_hdmi->cec_adap);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
> @@ -1422,6 +1424,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  }
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .registers              = vc4_hdmi_fields,
> +       .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
> +
>         .init_resources         = vc4_hdmi_init_resources,
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0eaf979fe811..b36e0210671f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_hdmi;
> +struct vc4_hdmi_register;
>
>  struct vc4_hdmi_variant {
> +       /* List of the registers available on that variant */
> +       const struct vc4_hdmi_register *registers;
> +
> +       /* Number of registers on that variant */
> +       unsigned int num_registers;
> +
>         /* Callback to get the resources (memory region, interrupts,
>          * clocks, etc) for that variant.
>          */
> @@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>         return container_of(_encoder, struct vc4_hdmi, encoder);
>  }
>
> -#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
> -#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
> -#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
> -#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
> -
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> new file mode 100644
> index 000000000000..bc47cc9bc883
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -0,0 +1,241 @@
> +#ifndef _VC4_HDMI_REGS_H_
> +#define _VC4_HDMI_REGS_H_
> +
> +#include "vc4_hdmi.h"
> +
> +#define VC4_HDMI_PACKET_STRIDE                 0x24
> +
> +enum vc4_hdmi_regs {
> +       VC4_INVALID = 0,
> +       VC4_HDMI,
> +       VC4_HD,
> +};
> +
> +enum vc4_hdmi_field {
> +       HDMI_AUDIO_PACKET_CONFIG,
> +       HDMI_CEC_CNTRL_1,
> +       HDMI_CEC_CNTRL_2,
> +       HDMI_CEC_CNTRL_3,
> +       HDMI_CEC_CNTRL_4,
> +       HDMI_CEC_CNTRL_5,
> +       HDMI_CEC_CPU_CLEAR,
> +       HDMI_CEC_CPU_MASK_CLEAR,
> +       HDMI_CEC_CPU_MASK_SET,
> +       HDMI_CEC_CPU_MASK_STATUS,
> +       HDMI_CEC_CPU_STATUS,
> +
> +       /*
> +        * Transmit data, first byte is low byte of the 32-bit reg.
> +        * MSB of each byte transmitted first.
> +        */
> +       HDMI_CEC_RX_DATA_1,
> +       HDMI_CEC_RX_DATA_2,
> +       HDMI_CEC_RX_DATA_3,
> +       HDMI_CEC_RX_DATA_4,
> +       HDMI_CEC_TX_DATA_1,
> +       HDMI_CEC_TX_DATA_2,
> +       HDMI_CEC_TX_DATA_3,
> +       HDMI_CEC_TX_DATA_4,
> +       HDMI_CORE_REV,
> +       HDMI_CRP_CFG,
> +       HDMI_CSC_12_11,
> +       HDMI_CSC_14_13,
> +       HDMI_CSC_22_21,
> +       HDMI_CSC_24_23,
> +       HDMI_CSC_32_31,
> +       HDMI_CSC_34_33,
> +       HDMI_CSC_CTL,
> +
> +       /*
> +        * 20-bit fields containing CTS values to be transmitted if
> +        * !EXTERNAL_CTS_EN
> +        */
> +       HDMI_CTS_0,
> +       HDMI_CTS_1,
> +       HDMI_FIFO_CTL,
> +       HDMI_FRAME_COUNT,
> +       HDMI_HORZA,
> +       HDMI_HORZB,
> +       HDMI_HOTPLUG,
> +       HDMI_HOTPLUG_INT,
> +
> +       /*
> +        * 3 bits per field, where each field maps from that
> +        * corresponding MAI bus channel to the given HDMI channel.
> +        */
> +       HDMI_MAI_CHANNEL_MAP,
> +       HDMI_MAI_CONFIG,
> +       HDMI_MAI_CTL,
> +
> +       /*
> +        * Register for DMAing in audio data to be transported over
> +        * the MAI bus to the Falcon core.
> +        */
> +       HDMI_MAI_DATA,
> +
> +       /* Format header to be placed on the MAI data. Unused. */
> +       HDMI_MAI_FMT,
> +
> +       /* Last received format word on the MAI bus. */
> +       HDMI_MAI_FORMAT,
> +       HDMI_MAI_SMP,
> +       HDMI_MAI_THR,
> +       HDMI_M_CTL,
> +       HDMI_RAM_PACKET_CONFIG,
> +       HDMI_RAM_PACKET_START,
> +       HDMI_RAM_PACKET_STATUS,
> +       HDMI_SCHEDULER_CONTROL,
> +       HDMI_SW_RESET_CONTROL,
> +       HDMI_TX_PHY_CTL_0,
> +       HDMI_TX_PHY_RESET_CTL,
> +       HDMI_VERTA0,
> +       HDMI_VERTA1,
> +       HDMI_VERTB0,
> +       HDMI_VERTB1,
> +       HDMI_VID_CTL,
> +};
> +
> +struct vc4_hdmi_register {
> +       char *name;
> +       enum vc4_hdmi_regs reg;
> +       unsigned int offset;
> +};
> +
> +#define _VC4_REG(_base, _reg, _offset) \
> +       [_reg] = {                              \
> +               .name = #_reg,                  \
> +               .reg = _base,                   \
> +               .offset = _offset,              \
> +       }
> +
> +#define VC4_HD_REG(reg, offset)                _VC4_REG(VC4_HD, reg, offset)
> +#define VC4_HDMI_REG(reg, offset)      _VC4_REG(VC4_HDMI, reg, offset)
> +
> +static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
> +       VC4_HD_REG(HDMI_M_CTL, 0x000c),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0018),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x001c),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x0020),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x002c),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0038),
> +       VC4_HD_REG(HDMI_CSC_CTL, 0x0040),
> +       VC4_HD_REG(HDMI_CSC_12_11, 0x0044),
> +       VC4_HD_REG(HDMI_CSC_14_13, 0x0048),
> +       VC4_HD_REG(HDMI_CSC_22_21, 0x004c),
> +       VC4_HD_REG(HDMI_CSC_24_23, 0x0050),
> +       VC4_HD_REG(HDMI_CSC_32_31, 0x0054),
> +       VC4_HD_REG(HDMI_CSC_34_33, 0x0058),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068),
> +
> +       VC4_HDMI_REG(HDMI_CORE_REV, 0x0000),
> +       VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004),
> +       VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c),
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094),
> +       VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x00ac),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x00b0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x00c4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x00c8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x00cc),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x00d0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x00d4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x00d8),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118),
> +       VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0),
> +       VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
> +};
> +
> +static inline
> +void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
> +                                       enum vc4_hdmi_regs reg)
> +{
> +       switch (reg) {
> +       case VC4_HD:
> +               return hdmi->hd_regs;
> +
> +       case VC4_HDMI:
> +               return hdmi->hdmicore_regs;
> +
> +       default:
> +               return NULL;
> +       }
> +
> +       return NULL;
> +}
> +
> +static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
> +                               enum vc4_hdmi_regs reg)
> +{
> +       const struct vc4_hdmi_register *field;
> +       const struct vc4_hdmi_variant *variant = hdmi->variant;
> +       void __iomem *base;
> +
> +       if (reg > variant->num_registers) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Invalid register ID %u\n", reg);
> +               return 0;
> +       }
> +
> +       field = &variant->registers[reg];
> +       base = __vc4_hdmi_get_field_base(hdmi, field->reg);
> +       if (!base) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Unknown register ID %u\n", reg);
> +               return 0;
> +       }
> +
> +       return readl(base + field->offset);
> +}
> +#define HDMI_READ(reg)         vc4_hdmi_read(vc4_hdmi, reg)
> +
> +static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
> +                                 enum vc4_hdmi_regs reg,
> +                                 u32 value)
> +{
> +       const struct vc4_hdmi_register *field;
> +       const struct vc4_hdmi_variant *variant = hdmi->variant;
> +       void __iomem *base;
> +
> +       if (reg > variant->num_registers) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Invalid register ID %u\n", reg);
> +               return;
> +       }
> +
> +       field = &variant->registers[reg];
> +       base = __vc4_hdmi_get_field_base(hdmi, field->reg);
> +       if (!base)
> +               return;
> +
> +       writel(value, base + field->offset);
> +}
> +#define HDMI_WRITE(reg, val)   vc4_hdmi_write(vc4_hdmi, reg, val)
> +
> +#endif /* _VC4_HDMI_REGS_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index c0031ab19689..d1e8961edaa0 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -493,32 +493,16 @@
>
>  #define SCALER5_DLIST_START                    0x00004000
>
> -#define VC4_HDMI_CORE_REV                      0x000
> -
> -#define VC4_HDMI_SW_RESET_CONTROL              0x004
>  # define VC4_HDMI_SW_RESET_FORMAT_DETECT       BIT(1)
>  # define VC4_HDMI_SW_RESET_HDMI                        BIT(0)
>
> -#define VC4_HDMI_HOTPLUG_INT                   0x008
> -
> -#define VC4_HDMI_HOTPLUG                       0x00c
>  # define VC4_HDMI_HOTPLUG_CONNECTED            BIT(0)
>
> -/* 3 bits per field, where each field maps from that corresponding MAI
> - * bus channel to the given HDMI channel.
> - */
> -#define VC4_HDMI_MAI_CHANNEL_MAP               0x090
> -
> -#define VC4_HDMI_MAI_CONFIG                    0x094
>  # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE            BIT(27)
>  # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE               BIT(26)
>  # define VC4_HDMI_MAI_CHANNEL_MASK_MASK                        VC4_MASK(15, 0)
>  # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT               0
>
> -/* Last received format word on the MAI bus. */
> -#define VC4_HDMI_MAI_FORMAT                    0x098
> -
> -#define VC4_HDMI_AUDIO_PACKET_CONFIG           0x09c
>  # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT                BIT(29)
>  # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS  BIT(24)
>  # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT            BIT(19)
> @@ -532,12 +516,8 @@
>  # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK                   VC4_MASK(7, 0)
>  # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT                  0
>
> -#define VC4_HDMI_RAM_PACKET_CONFIG             0x0a0
>  # define VC4_HDMI_RAM_PACKET_ENABLE            BIT(16)
>
> -#define VC4_HDMI_RAM_PACKET_STATUS             0x0a4
> -
> -#define VC4_HDMI_CRP_CFG                       0x0a8
>  /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
>   * of pixel clock.
>   */
> @@ -551,23 +531,12 @@
>  # define VC4_HDMI_CRP_CFG_N_MASK               VC4_MASK(19, 0)
>  # define VC4_HDMI_CRP_CFG_N_SHIFT              0
>
> -/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */
> -#define VC4_HDMI_CTS_0                         0x0ac
> -#define VC4_HDMI_CTS_1                         0x0b0
> -/* 20-bit fields containing number of clocks to send CTS0/1 before
> - * switching to the other one.
> - */
> -#define VC4_HDMI_CTS_PERIOD_0                  0x0b4
> -#define VC4_HDMI_CTS_PERIOD_1                  0x0b8
> -
> -#define VC4_HDMI_HORZA                         0x0c4
>  # define VC4_HDMI_HORZA_VPOS                   BIT(14)
>  # define VC4_HDMI_HORZA_HPOS                   BIT(13)
>  /* Horizontal active pixels (hdisplay). */
>  # define VC4_HDMI_HORZA_HAP_MASK               VC4_MASK(12, 0)
>  # define VC4_HDMI_HORZA_HAP_SHIFT              0
>
> -#define VC4_HDMI_HORZB                         0x0c8
>  /* Horizontal pack porch (htotal - hsync_end). */
>  # define VC4_HDMI_HORZB_HBP_MASK               VC4_MASK(29, 20)
>  # define VC4_HDMI_HORZB_HBP_SHIFT              20
> @@ -578,7 +547,6 @@
>  # define VC4_HDMI_HORZB_HFP_MASK               VC4_MASK(9, 0)
>  # define VC4_HDMI_HORZB_HFP_SHIFT              0
>
> -#define VC4_HDMI_FIFO_CTL                      0x05c
>  # define VC4_HDMI_FIFO_CTL_RECENTER_DONE       BIT(14)
>  # define VC4_HDMI_FIFO_CTL_USE_EMPTY           BIT(13)
>  # define VC4_HDMI_FIFO_CTL_ON_VB               BIT(7)
> @@ -591,15 +559,12 @@
>  # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N      BIT(0)
>  # define VC4_HDMI_FIFO_VALID_WRITE_MASK                0xefff
>
> -#define VC4_HDMI_SCHEDULER_CONTROL             0x0c0
>  # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
>  # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
>  # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT        BIT(3)
>  # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE        BIT(1)
>  # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI  BIT(0)
>
> -#define VC4_HDMI_VERTA0                                0x0cc
> -#define VC4_HDMI_VERTA1                                0x0d4
>  /* Vertical sync pulse (vsync_end - vsync_start). */
>  # define VC4_HDMI_VERTA_VSP_MASK               VC4_MASK(24, 20)
>  # define VC4_HDMI_VERTA_VSP_SHIFT              20
> @@ -610,8 +575,6 @@
>  # define VC4_HDMI_VERTA_VAL_MASK               VC4_MASK(12, 0)
>  # define VC4_HDMI_VERTA_VAL_SHIFT              0
>
> -#define VC4_HDMI_VERTB0                                0x0d0
> -#define VC4_HDMI_VERTB1                                0x0d8
>  /* Vertical sync pulse offset (for interlaced) */
>  # define VC4_HDMI_VERTB_VSPO_MASK              VC4_MASK(21, 9)
>  # define VC4_HDMI_VERTB_VSPO_SHIFT             9
> @@ -619,7 +582,6 @@
>  # define VC4_HDMI_VERTB_VBP_MASK               VC4_MASK(8, 0)
>  # define VC4_HDMI_VERTB_VBP_SHIFT              0
>
> -#define VC4_HDMI_CEC_CNTRL_1                   0x0e8
>  /* Set when the transmission has ended. */
>  # define VC4_HDMI_CEC_TX_EOM                   BIT(31)
>  /* If set, transmission was acked on the 1st or 2nd attempt (only one
> @@ -660,7 +622,6 @@
>  /* Set these fields to how many bit clock cycles get to that many
>   * microseconds.
>   */
> -#define VC4_HDMI_CEC_CNTRL_2                   0x0ec
>  # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK      VC4_MASK(30, 24)
>  # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK      VC4_MASK(23, 17)
> @@ -672,7 +633,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_400_US_MASK       VC4_MASK(4, 0)
>  # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT      0
>
> -#define VC4_HDMI_CEC_CNTRL_3                   0x0f0
>  # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK      VC4_MASK(31, 24)
>  # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK      VC4_MASK(23, 16)
> @@ -682,7 +642,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT     0
>
> -#define VC4_HDMI_CEC_CNTRL_4                   0x0f4
>  # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK      VC4_MASK(31, 24)
>  # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK      VC4_MASK(23, 16)
> @@ -692,7 +651,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT     0
>
> -#define VC4_HDMI_CEC_CNTRL_5                   0x0f8
>  # define VC4_HDMI_CEC_TX_SW_RESET              BIT(27)
>  # define VC4_HDMI_CEC_RX_SW_RESET              BIT(26)
>  # define VC4_HDMI_CEC_PAD_SW_RESET             BIT(25)
> @@ -705,39 +663,11 @@
>  # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT     0
>
> -/* Transmit data, first byte is low byte of the 32-bit reg.  MSB of
> - * each byte transmitted first.
> - */
> -#define VC4_HDMI_CEC_TX_DATA_1                 0x0fc
> -#define VC4_HDMI_CEC_TX_DATA_2                 0x100
> -#define VC4_HDMI_CEC_TX_DATA_3                 0x104
> -#define VC4_HDMI_CEC_TX_DATA_4                 0x108
> -#define VC4_HDMI_CEC_RX_DATA_1                 0x10c
> -#define VC4_HDMI_CEC_RX_DATA_2                 0x110
> -#define VC4_HDMI_CEC_RX_DATA_3                 0x114
> -#define VC4_HDMI_CEC_RX_DATA_4                 0x118
> -
> -#define VC4_HDMI_TX_PHY_RESET_CTL              0x2c0
> -
> -#define VC4_HDMI_TX_PHY_CTL0                   0x2c4
>  # define VC4_HDMI_TX_PHY_RNG_PWRDN             BIT(25)
>
> -/* Interrupt status bits */
> -#define VC4_HDMI_CPU_STATUS                    0x340
> -#define VC4_HDMI_CPU_SET                       0x344
> -#define VC4_HDMI_CPU_CLEAR                     0x348
>  # define VC4_HDMI_CPU_CEC                      BIT(6)
>  # define VC4_HDMI_CPU_HOTPLUG                  BIT(0)
>
> -#define VC4_HDMI_CPU_MASK_STATUS               0x34c
> -#define VC4_HDMI_CPU_MASK_SET                  0x350
> -#define VC4_HDMI_CPU_MASK_CLEAR                        0x354
> -
> -#define VC4_HDMI_GCP(x)                                (0x400 + ((x) * 0x4))
> -#define VC4_HDMI_RAM_PACKET(x)                 (0x400 + ((x) * 0x24))
> -#define VC4_HDMI_PACKET_STRIDE                 0x24
> -
> -#define VC4_HD_M_CTL                           0x00c
>  /* Debug: Current receive value on the CEC pad. */
>  # define VC4_HD_CECRXD                         BIT(9)
>  /* Debug: Override CEC output to 0. */
> @@ -747,7 +677,6 @@
>  # define VC4_HD_M_SW_RST                       BIT(2)
>  # define VC4_HD_M_ENABLE                       BIT(0)
>
> -#define VC4_HD_MAI_CTL                         0x014
>  /* Set when audio stream is received at a slower rate than the
>   * sampling period, so MAI fifo goes empty.  Write 1 to clear.
>   */
> @@ -772,7 +701,6 @@
>  /* Single-shot reset bit.  Read value is undefined. */
>  # define VC4_HD_MAI_CTL_RESET                  BIT(0)
>
> -#define VC4_HD_MAI_THR                         0x018
>  # define VC4_HD_MAI_THR_PANICHIGH_MASK         VC4_MASK(29, 24)
>  # define VC4_HD_MAI_THR_PANICHIGH_SHIFT                24
>  # define VC4_HD_MAI_THR_PANICLOW_MASK          VC4_MASK(21, 16)
> @@ -782,31 +710,20 @@
>  # define VC4_HD_MAI_THR_DREQLOW_MASK           VC4_MASK(5, 0)
>  # define VC4_HD_MAI_THR_DREQLOW_SHIFT          0
>
> -/* Format header to be placed on the MAI data. Unused. */
> -#define VC4_HD_MAI_FMT                         0x01c
> -
> -/* Register for DMAing in audio data to be transported over the MAI
> - * bus to the Falcon core.
> - */
> -#define VC4_HD_MAI_DATA                                0x020
> -
>  /* Divider from HDMI HSM clock to MAI serial clock.  Sampling period
>   * converges to N / (M + 1) cycles.
>   */
> -#define VC4_HD_MAI_SMP                         0x02c
>  # define VC4_HD_MAI_SMP_N_MASK                 VC4_MASK(31, 8)
>  # define VC4_HD_MAI_SMP_N_SHIFT                        8
>  # define VC4_HD_MAI_SMP_M_MASK                 VC4_MASK(7, 0)
>  # define VC4_HD_MAI_SMP_M_SHIFT                        0
>
> -#define VC4_HD_VID_CTL                         0x038
>  # define VC4_HD_VID_CTL_ENABLE                 BIT(31)
>  # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE       BIT(30)
>  # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET    BIT(29)
>  # define VC4_HD_VID_CTL_VSYNC_LOW              BIT(28)
>  # define VC4_HD_VID_CTL_HSYNC_LOW              BIT(27)
>
> -#define VC4_HD_CSC_CTL                         0x040
>  # define VC4_HD_CSC_CTL_ORDER_MASK             VC4_MASK(7, 5)
>  # define VC4_HD_CSC_CTL_ORDER_SHIFT            5
>  # define VC4_HD_CSC_CTL_ORDER_RGB              0
> @@ -824,15 +741,6 @@
>  # define VC4_HD_CSC_CTL_RGB2YCC                        BIT(1)
>  # define VC4_HD_CSC_CTL_ENABLE                 BIT(0)
>
> -#define VC4_HD_CSC_12_11                       0x044
> -#define VC4_HD_CSC_14_13                       0x048
> -#define VC4_HD_CSC_22_21                       0x04c
> -#define VC4_HD_CSC_24_23                       0x050
> -#define VC4_HD_CSC_32_31                       0x054
> -#define VC4_HD_CSC_34_33                       0x058
> -
> -#define VC4_HD_FRAME_COUNT                     0x068
> -
>  /* HVS display list information. */
>  #define HVS_BOOTLOADER_DLIST_END                32
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction
@ 2020-07-28 12:59       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 12:59 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI controllers found in the BCM2711 have most of the registers
> reorganized in multiple registers areas and at different offsets than
> previously found.
>
> The logic however remains pretty much the same, so it doesn't really make
> sense to create a whole new driver and we should share the code as much as
> possible.
>
> Let's implement some indirection to wrap around a register and depending on
> the variant will lookup the associated register on that particular variant.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c      | 427 ++++++++++++++---------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h      |  12 +-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 241 ++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h      |  92 +------
>  4 files changed, 464 insertions(+), 308 deletions(-)
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ac021e07a8cb..a4fed1439bf3 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -50,62 +50,13 @@
>  #include "media/cec.h"
>  #include "vc4_drv.h"
>  #include "vc4_hdmi.h"
> +#include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
>  #define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>  #define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
>
> -static const struct debugfs_reg32 hdmi_regs[] = {
> -       VC4_REG32(VC4_HDMI_CORE_REV),
> -       VC4_REG32(VC4_HDMI_SW_RESET_CONTROL),
> -       VC4_REG32(VC4_HDMI_HOTPLUG_INT),
> -       VC4_REG32(VC4_HDMI_HOTPLUG),
> -       VC4_REG32(VC4_HDMI_MAI_CHANNEL_MAP),
> -       VC4_REG32(VC4_HDMI_MAI_CONFIG),
> -       VC4_REG32(VC4_HDMI_MAI_FORMAT),
> -       VC4_REG32(VC4_HDMI_AUDIO_PACKET_CONFIG),
> -       VC4_REG32(VC4_HDMI_RAM_PACKET_CONFIG),
> -       VC4_REG32(VC4_HDMI_HORZA),
> -       VC4_REG32(VC4_HDMI_HORZB),
> -       VC4_REG32(VC4_HDMI_FIFO_CTL),
> -       VC4_REG32(VC4_HDMI_SCHEDULER_CONTROL),
> -       VC4_REG32(VC4_HDMI_VERTA0),
> -       VC4_REG32(VC4_HDMI_VERTA1),
> -       VC4_REG32(VC4_HDMI_VERTB0),
> -       VC4_REG32(VC4_HDMI_VERTB1),
> -       VC4_REG32(VC4_HDMI_TX_PHY_RESET_CTL),
> -       VC4_REG32(VC4_HDMI_TX_PHY_CTL0),
> -
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_1),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_2),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_3),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_4),
> -       VC4_REG32(VC4_HDMI_CEC_CNTRL_5),
> -       VC4_REG32(VC4_HDMI_CPU_STATUS),
> -       VC4_REG32(VC4_HDMI_CPU_MASK_STATUS),
> -
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_1),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_2),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_3),
> -       VC4_REG32(VC4_HDMI_CEC_RX_DATA_4),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_1),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_2),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_3),
> -       VC4_REG32(VC4_HDMI_CEC_TX_DATA_4),
> -};
> -
> -static const struct debugfs_reg32 hd_regs[] = {
> -       VC4_REG32(VC4_HD_M_CTL),
> -       VC4_REG32(VC4_HD_MAI_CTL),
> -       VC4_REG32(VC4_HD_MAI_THR),
> -       VC4_REG32(VC4_HD_MAI_FMT),
> -       VC4_REG32(VC4_HD_MAI_SMP),
> -       VC4_REG32(VC4_HD_VID_CTL),
> -       VC4_REG32(VC4_HD_CSC_CTL),
> -       VC4_REG32(VC4_HD_FRAME_COUNT),
> -};
> -
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>  {
>         struct drm_info_node *node = (struct drm_info_node *)m->private;
> @@ -134,7 +85,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>         if (drm_probe_ddc(vc4_hdmi->ddc))
>                 return connector_status_connected;
>
> -       if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
> +       if (HDMI_READ(HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED)
>                 return connector_status_connected;
>         cec_phys_addr_invalidate(vc4_hdmi->cec_adap);
>         return connector_status_disconnected;
> @@ -223,10 +174,10 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         u32 packet_id = type - 0x80;
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                  HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                  HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
>
> -       return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
> +       return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
>                           BIT(packet_id)), 100);
>  }
>
> @@ -235,12 +186,16 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
>  {
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         u32 packet_id = frame->any.type - 0x80;
> -       u32 packet_reg = VC4_HDMI_RAM_PACKET(packet_id);
> +       const struct vc4_hdmi_register *ram_packet_start =
> +               &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
> +       u32 packet_reg = ram_packet_start->offset + VC4_HDMI_PACKET_STRIDE * packet_id;
> +       void __iomem *base = __vc4_hdmi_get_field_base(vc4_hdmi,
> +                                                      ram_packet_start->reg);
>         uint8_t buffer[VC4_HDMI_PACKET_STRIDE];
>         ssize_t len, i;
>         int ret;
>
> -       WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +       WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                     VC4_HDMI_RAM_PACKET_ENABLE),
>                   "Packet RAM has to be on to store the packet.");
>
> @@ -255,23 +210,23 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
>         }
>
>         for (i = 0; i < len; i += 7) {
> -               HDMI_WRITE(packet_reg,
> -                          buffer[i + 0] << 0 |
> -                          buffer[i + 1] << 8 |
> -                          buffer[i + 2] << 16);
> +               writel(buffer[i + 0] << 0 |
> +                      buffer[i + 1] << 8 |
> +                      buffer[i + 2] << 16,
> +                      base + packet_reg);
>                 packet_reg += 4;
>
> -               HDMI_WRITE(packet_reg,
> -                          buffer[i + 3] << 0 |
> -                          buffer[i + 4] << 8 |
> -                          buffer[i + 5] << 16 |
> -                          buffer[i + 6] << 24);
> +               writel(buffer[i + 3] << 0 |
> +                      buffer[i + 4] << 8 |
> +                      buffer[i + 5] << 16 |
> +                      buffer[i + 6] << 24,
> +                      base + packet_reg);
>                 packet_reg += 4;
>         }
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                  HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
> -       ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) &
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                  HDMI_READ(HDMI_RAM_PACKET_CONFIG) | BIT(packet_id));
> +       ret = wait_for((HDMI_READ(HDMI_RAM_PACKET_STATUS) &
>                         BIT(packet_id)), 100);
>         if (ret)
>                 DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
> @@ -349,11 +304,11 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         int ret;
>
> -       HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0);
> +       HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
>
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
>         clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
> @@ -408,18 +363,18 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL,
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
>                    VC4_HDMI_SW_RESET_HDMI |
>                    VC4_HDMI_SW_RESET_FORMAT_DETECT);
>
> -       HDMI_WRITE(VC4_HDMI_SW_RESET_CONTROL, 0);
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
>
>         /* PHY should be in reset, like
>          * vc4_hdmi_encoder_disable() does.
>          */
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
>
> -       HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -429,20 +384,20 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 drm_print_regset32(&p, &vc4_hdmi->hd_regset);
>         }
>
> -       HD_WRITE(VC4_HD_VID_CTL, 0);
> +       HDMI_WRITE(HDMI_VID_CTL, 0);
>
> -       HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                  HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +       HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                  HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
>                    VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
>
> -       HDMI_WRITE(VC4_HDMI_HORZA,
> +       HDMI_WRITE(HDMI_HORZA,
>                    (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
>                    (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
>                    VC4_SET_FIELD(mode->hdisplay * pixel_rep,
>                                  VC4_HDMI_HORZA_HAP));
>
> -       HDMI_WRITE(VC4_HDMI_HORZB,
> +       HDMI_WRITE(HDMI_HORZB,
>                    VC4_SET_FIELD((mode->htotal -
>                                   mode->hsync_end) * pixel_rep,
>                                  VC4_HDMI_HORZB_HBP) |
> @@ -453,15 +408,15 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                                   mode->hdisplay) * pixel_rep,
>                                  VC4_HDMI_HORZB_HFP));
>
> -       HDMI_WRITE(VC4_HDMI_VERTA0, verta);
> -       HDMI_WRITE(VC4_HDMI_VERTA1, verta);
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
>
> -       HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even);
> -       HDMI_WRITE(VC4_HDMI_VERTB1, vertb);
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
>
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
>         csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
>                                 VC4_HD_CSC_CTL_ORDER);
> @@ -484,21 +439,21 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
>                                          VC4_HD_CSC_CTL_MODE);
>
> -               HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0);
> -               HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000);
> -               HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0);
> -               HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
>                 vc4_encoder->limited_rgb_range = true;
>         } else {
>                 vc4_encoder->limited_rgb_range = false;
>         }
>
>         /* The RGB order applies even when CSC is disabled. */
> -       HD_WRITE(VC4_HD_CSC_CTL, csc_ctl);
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
>
> -       HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
> +       HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -508,30 +463,30 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 drm_print_regset32(&p, &vc4_hdmi->hd_regset);
>         }
>
> -       HD_WRITE(VC4_HD_VID_CTL,
> -                HD_READ(VC4_HD_VID_CTL) |
> -                VC4_HD_VID_CTL_ENABLE |
> -                VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> -                VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) |
> +                  VC4_HD_VID_CTL_ENABLE |
> +                  VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> +                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
>
>         if (vc4_encoder->hdmi_monitor) {
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                            VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
>
> -               ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               ret = wait_for(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                                VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
>         } else {
> -               HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> -                          HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +               HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
> +                          HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                            ~(VC4_HDMI_RAM_PACKET_ENABLE));
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                            ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI);
>
> -               ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               ret = wait_for(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                                  VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n");
> @@ -540,31 +495,31 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_encoder->hdmi_monitor) {
>                 u32 drift;
>
> -               WARN_ON(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) &
> +               WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                           VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
> -               HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL,
> -                          HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) |
> +               HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> +                          HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                            VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT);
>
> -               HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG,
> +               HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
>                            VC4_HDMI_RAM_PACKET_ENABLE);
>
>                 vc4_hdmi_set_infoframes(encoder);
>
> -               drift = HDMI_READ(VC4_HDMI_FIFO_CTL);
> +               drift = HDMI_READ(HDMI_FIFO_CTL);
>                 drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
>
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift | VC4_HDMI_FIFO_CTL_RECENTER);
>                 usleep_range(1000, 1100);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(VC4_HDMI_FIFO_CTL,
> +               HDMI_WRITE(HDMI_FIFO_CTL,
>                            drift | VC4_HDMI_FIFO_CTL_RECENTER);
>
> -               ret = wait_for(HDMI_READ(VC4_HDMI_FIFO_CTL) &
> +               ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
>                                VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
>                 WARN_ONCE(ret, "Timeout waiting for "
>                           "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> @@ -616,9 +571,9 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
>                                      VC4_HD_MAI_SMP_M_SHIFT) + 1,
>                                     &n, &m);
>
> -       HD_WRITE(VC4_HD_MAI_SMP,
> -                VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
> -                VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
> +       HDMI_WRITE(HDMI_MAI_SMP,
> +                  VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
> +                  VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
>  }
>
>  static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
> @@ -635,7 +590,7 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
>         do_div(tmp, 128 * samplerate);
>         cts = tmp;
>
> -       HDMI_WRITE(VC4_HDMI_CRP_CFG,
> +       HDMI_WRITE(HDMI_CRP_CFG,
>                    VC4_HDMI_CRP_CFG_EXTERNAL_CTS_EN |
>                    VC4_SET_FIELD(n, VC4_HDMI_CRP_CFG_N));
>
> @@ -644,8 +599,8 @@ static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
>          * providing a CTS_1 value.  The two CTS values are alternated
>          * between based on the period fields
>          */
> -       HDMI_WRITE(VC4_HDMI_CTS_0, cts);
> -       HDMI_WRITE(VC4_HDMI_CTS_1, cts);
> +       HDMI_WRITE(HDMI_CTS_0, cts);
> +       HDMI_WRITE(HDMI_CTS_1, cts);
>  }
>
>  static inline struct vc4_hdmi *dai_to_hdmi(struct snd_soc_dai *dai)
> @@ -672,7 +627,7 @@ static int vc4_hdmi_audio_startup(struct snd_pcm_substream *substream,
>          * If the HDMI encoder hasn't probed, or the encoder is
>          * currently in DVI mode, treat the codec dai as missing.
>          */
> -       if (!encoder->crtc || !(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) &
> +       if (!encoder->crtc || !(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
>                                 VC4_HDMI_RAM_PACKET_ENABLE))
>                 return -ENODEV;
>
> @@ -698,9 +653,9 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
>         if (ret)
>                 dev_err(dev, "Failed to stop audio infoframe: %d\n", ret);
>
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_RESET);
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
> -       HD_WRITE(VC4_HD_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_RESET);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_ERRORF);
> +       HDMI_WRITE(HDMI_MAI_CTL, VC4_HD_MAI_CTL_FLUSH);
>  }
>
>  static void vc4_hdmi_audio_shutdown(struct snd_pcm_substream *substream,
> @@ -736,12 +691,12 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>         vc4_hdmi->audio.channels = params_channels(params);
>         vc4_hdmi->audio.samplerate = params_rate(params);
>
> -       HD_WRITE(VC4_HD_MAI_CTL,
> -                VC4_HD_MAI_CTL_RESET |
> -                VC4_HD_MAI_CTL_FLUSH |
> -                VC4_HD_MAI_CTL_DLATE |
> -                VC4_HD_MAI_CTL_ERRORE |
> -                VC4_HD_MAI_CTL_ERRORF);
> +       HDMI_WRITE(HDMI_MAI_CTL,
> +                  VC4_HD_MAI_CTL_RESET |
> +                  VC4_HD_MAI_CTL_FLUSH |
> +                  VC4_HD_MAI_CTL_DLATE |
> +                  VC4_HD_MAI_CTL_ERRORE |
> +                  VC4_HD_MAI_CTL_ERRORF);
>
>         vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
>
> @@ -756,22 +711,22 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>
>         /* Set the MAI threshold.  This logic mimics the firmware's. */
>         if (vc4_hdmi->audio.samplerate > 96000) {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
>         } else if (vc4_hdmi->audio.samplerate > 48000) {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x14, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x12, VC4_HD_MAI_THR_DREQLOW));
>         } else {
> -               HD_WRITE(VC4_HD_MAI_THR,
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
> -                        VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
> +               HDMI_WRITE(HDMI_MAI_THR,
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICHIGH) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_PANICLOW) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQHIGH) |
> +                          VC4_SET_FIELD(0x10, VC4_HD_MAI_THR_DREQLOW));
>         }
>
> -       HDMI_WRITE(VC4_HDMI_MAI_CONFIG,
> +       HDMI_WRITE(HDMI_MAI_CONFIG,
>                    VC4_HDMI_MAI_CONFIG_BIT_REVERSE |
>                    VC4_SET_FIELD(channel_mask, VC4_HDMI_MAI_CHANNEL_MASK));
>
> @@ -781,8 +736,8 @@ static int vc4_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
>                         channel_map |= i << (3 * i);
>         }
>
> -       HDMI_WRITE(VC4_HDMI_MAI_CHANNEL_MAP, channel_map);
> -       HDMI_WRITE(VC4_HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
> +       HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
> +       HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
>         vc4_hdmi_set_n_cts(vc4_hdmi);
>
>         return 0;
> @@ -797,21 +752,22 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 vc4_hdmi_set_audio_infoframe(encoder);
> -               HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
> -                          HDMI_READ(VC4_HDMI_TX_PHY_CTL0) &
> +               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                          HDMI_READ(HDMI_TX_PHY_CTL_0) &
>                            ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> -               HD_WRITE(VC4_HD_MAI_CTL,
> -                        VC4_SET_FIELD(vc4_hdmi->audio.channels,
> -                                      VC4_HD_MAI_CTL_CHNUM) |
> -                        VC4_HD_MAI_CTL_ENABLE);
> +
> +               HDMI_WRITE(HDMI_MAI_CTL,
> +                          VC4_SET_FIELD(vc4_hdmi->audio.channels,
> +                                        VC4_HD_MAI_CTL_CHNUM) |
> +                          VC4_HD_MAI_CTL_ENABLE);
>                 break;
>         case SNDRV_PCM_TRIGGER_STOP:
> -               HD_WRITE(VC4_HD_MAI_CTL,
> -                        VC4_HD_MAI_CTL_DLATE |
> -                        VC4_HD_MAI_CTL_ERRORE |
> -                        VC4_HD_MAI_CTL_ERRORF);
> -               HDMI_WRITE(VC4_HDMI_TX_PHY_CTL0,
> -                          HDMI_READ(VC4_HDMI_TX_PHY_CTL0) |
> +               HDMI_WRITE(HDMI_MAI_CTL,
> +                          VC4_HD_MAI_CTL_DLATE |
> +                          VC4_HD_MAI_CTL_ERRORE |
> +                          VC4_HD_MAI_CTL_ERRORF);
> +               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                          HDMI_READ(HDMI_TX_PHY_CTL_0) |
>                            VC4_HDMI_TX_PHY_RNG_PWRDN);
>                 break;
>         default:
> @@ -946,6 +902,8 @@ static const struct snd_dmaengine_pcm_config pcm_conf = {
>
>  static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>  {
> +       const struct vc4_hdmi_register *mai_data =
> +               &vc4_hdmi->variant->registers[HDMI_MAI_DATA];
>         struct snd_soc_dai_link *dai_link = &vc4_hdmi->audio.link;
>         struct snd_soc_card *card = &vc4_hdmi->audio.card;
>         struct device *dev = &vc4_hdmi->pdev->dev;
> @@ -958,6 +916,11 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>                 return 0;
>         }
>
> +       if (mai_data->reg != VC4_HD) {
> +               WARN_ONCE(true, "MAI isn't in the HD block\n");
> +               return -EINVAL;
> +       }
> +
>         /*
>          * Get the physical address of VC4_HD_MAI_DATA. We need to retrieve
>          * the bus address specified in the DT, because the physical address
> @@ -966,7 +929,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>          * This VC/MMU should probably be exposed to avoid this kind of hacks.
>          */
>         addr = of_get_address(dev->of_node, 1, NULL, NULL);
> -       vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + VC4_HD_MAI_DATA;
> +       vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
>         vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
>         vc4_hdmi->audio.dma_data.maxburst = 2;
>
> @@ -1058,7 +1021,7 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
>         msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >>
>                                         VC4_HDMI_CEC_REC_WRD_CNT_SHIFT);
>         for (i = 0; i < msg->len; i += 4) {
> -               u32 val = HDMI_READ(VC4_HDMI_CEC_RX_DATA_1 + i);
> +               u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i);
>
>                 msg->msg[i] = val & 0xff;
>                 msg->msg[i + 1] = (val >> 8) & 0xff;
> @@ -1070,26 +1033,26 @@ static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1)
>  static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
>  {
>         struct vc4_hdmi *vc4_hdmi = priv;
> -       u32 stat = HDMI_READ(VC4_HDMI_CPU_STATUS);
> +       u32 stat = HDMI_READ(HDMI_CEC_CPU_STATUS);
>         u32 cntrl1, cntrl5;
>
>         if (!(stat & VC4_HDMI_CPU_CEC))
>                 return IRQ_NONE;
>         vc4_hdmi->cec_rx_msg.len = 0;
> -       cntrl1 = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> -       cntrl5 = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
> +       cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
> +       cntrl5 = HDMI_READ(HDMI_CEC_CNTRL_5);
>         vc4_hdmi->cec_irq_was_rx = cntrl5 & VC4_HDMI_CEC_RX_CEC_INT;
>         if (vc4_hdmi->cec_irq_was_rx) {
>                 vc4_cec_read_msg(vc4_hdmi, cntrl1);
>                 cntrl1 |= VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
>                 cntrl1 &= ~VC4_HDMI_CEC_CLEAR_RECEIVE_OFF;
>         } else {
>                 vc4_hdmi->cec_tx_ok = cntrl1 & VC4_HDMI_CEC_TX_STATUS_GOOD;
>                 cntrl1 &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
>         }
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, cntrl1);
> -       HDMI_WRITE(VC4_HDMI_CPU_CLEAR, VC4_HDMI_CPU_CEC);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, cntrl1);
> +       HDMI_WRITE(HDMI_CEC_CPU_CLEAR, VC4_HDMI_CPU_CEC);
>
>         return IRQ_WAKE_THREAD;
>  }
> @@ -1099,7 +1062,7 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
>         struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
>         /* clock period in microseconds */
>         const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
> -       u32 val = HDMI_READ(VC4_HDMI_CEC_CNTRL_5);
> +       u32 val = HDMI_READ(HDMI_CEC_CNTRL_5);
>
>         val &= ~(VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET |
>                  VC4_HDMI_CEC_CNT_TO_4700_US_MASK |
> @@ -1108,30 +1071,30 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
>                ((4500 / usecs) << VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT);
>
>         if (enable) {
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
>                            VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_2,
> -                        ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
> -                        ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
> -                        ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
> -                        ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
> -                        ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_3,
> -                        ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
> -                        ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
> -                        ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
> -                        ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_4,
> -                        ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
> -                        ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
> -                        ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
> -                        ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
> -
> -               HDMI_WRITE(VC4_HDMI_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_2,
> +                          ((1500 / usecs) << VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT) |
> +                          ((1300 / usecs) << VC4_HDMI_CEC_CNT_TO_1300_US_SHIFT) |
> +                          ((800 / usecs) << VC4_HDMI_CEC_CNT_TO_800_US_SHIFT) |
> +                          ((600 / usecs) << VC4_HDMI_CEC_CNT_TO_600_US_SHIFT) |
> +                          ((400 / usecs) << VC4_HDMI_CEC_CNT_TO_400_US_SHIFT));
> +               HDMI_WRITE(HDMI_CEC_CNTRL_3,
> +                          ((2750 / usecs) << VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT) |
> +                          ((2400 / usecs) << VC4_HDMI_CEC_CNT_TO_2400_US_SHIFT) |
> +                          ((2050 / usecs) << VC4_HDMI_CEC_CNT_TO_2050_US_SHIFT) |
> +                          ((1700 / usecs) << VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT));
> +               HDMI_WRITE(HDMI_CEC_CNTRL_4,
> +                          ((4300 / usecs) << VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT) |
> +                          ((3900 / usecs) << VC4_HDMI_CEC_CNT_TO_3900_US_SHIFT) |
> +                          ((3600 / usecs) << VC4_HDMI_CEC_CNT_TO_3600_US_SHIFT) |
> +                          ((3500 / usecs) << VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT));
> +
> +               HDMI_WRITE(HDMI_CEC_CPU_MASK_CLEAR, VC4_HDMI_CPU_CEC);
>         } else {
> -               HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
> -               HDMI_WRITE(VC4_HDMI_CEC_CNTRL_5, val |
> +               HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, VC4_HDMI_CPU_CEC);
> +               HDMI_WRITE(HDMI_CEC_CNTRL_5, val |
>                            VC4_HDMI_CEC_TX_SW_RESET | VC4_HDMI_CEC_RX_SW_RESET);
>         }
>         return 0;
> @@ -1141,8 +1104,8 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
>  {
>         struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
>
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1,
> -                  (HDMI_READ(VC4_HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1,
> +                  (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
>                    (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
>         return 0;
>  }
> @@ -1155,20 +1118,20 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
>         unsigned int i;
>
>         for (i = 0; i < msg->len; i += 4)
> -               HDMI_WRITE(VC4_HDMI_CEC_TX_DATA_1 + i,
> +               HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i,
>                            (msg->msg[i]) |
>                            (msg->msg[i + 1] << 8) |
>                            (msg->msg[i + 2] << 16) |
>                            (msg->msg[i + 3] << 24));
>
> -       val = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> +       val = HDMI_READ(HDMI_CEC_CNTRL_1);
>         val &= ~VC4_HDMI_CEC_START_XMIT_BEGIN;
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
>         val &= ~VC4_HDMI_CEC_MESSAGE_LENGTH_MASK;
>         val |= (msg->len - 1) << VC4_HDMI_CEC_MESSAGE_LENGTH_SHIFT;
>         val |= VC4_HDMI_CEC_START_XMIT_BEGIN;
>
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, val);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, val);
>         return 0;
>  }
>
> @@ -1179,6 +1142,42 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>  };
>  #endif
>
> +static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
> +                                struct debugfs_regset32 *regset,
> +                                enum vc4_hdmi_regs reg)
> +{
> +       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> +       struct debugfs_reg32 *regs, *new_regs;
> +       unsigned int count = 0;
> +       unsigned int i;
> +
> +       regs = kcalloc(variant->num_registers, sizeof(*regs),
> +                      GFP_KERNEL);
> +       if (!regs)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < variant->num_registers; i++) {
> +               const struct vc4_hdmi_register *field = &variant->registers[i];
> +
> +               if (field->reg != reg)
> +                       continue;
> +
> +               regs[count].name = field->name;
> +               regs[count].offset = field->offset;
> +               count++;
> +       }
> +
> +       new_regs = krealloc(regs, count * sizeof(*regs), GFP_KERNEL);
> +       if (!new_regs)
> +               return -ENOMEM;
> +
> +       regset->base = __vc4_hdmi_get_field_base(vc4_hdmi, reg);
> +       regset->regs = new_regs;
> +       regset->nregs = count;
> +
> +       return 0;
> +}
> +
>  static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>  {
>         struct platform_device *pdev = vc4_hdmi->pdev;
> @@ -1193,13 +1192,13 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>         if (IS_ERR(vc4_hdmi->hd_regs))
>                 return PTR_ERR(vc4_hdmi->hd_regs);
>
> -       vc4_hdmi->hdmi_regset.base = vc4_hdmi->hdmicore_regs;
> -       vc4_hdmi->hdmi_regset.regs = hdmi_regs;
> -       vc4_hdmi->hdmi_regset.nregs = ARRAY_SIZE(hdmi_regs);
> +       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
> +       if (ret)
> +               return ret;
>
> -       vc4_hdmi->hd_regset.base = vc4_hdmi->hd_regs;
> -       vc4_hdmi->hd_regset.regs = hd_regs;
> -       vc4_hdmi->hd_regset.nregs = ARRAY_SIZE(hd_regs);
> +       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
> +       if (ret)
> +               return ret;
>
>         vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
>         if (IS_ERR(vc4_hdmi->pixel_clock)) {
> @@ -1294,12 +1293,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         }
>
>         /* HDMI core must be enabled. */
> -       if (!(HD_READ(VC4_HD_M_CTL) & VC4_HD_M_ENABLE)) {
> -               HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_SW_RST);
> +       if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
> +               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
>                 udelay(1);
> -               HD_WRITE(VC4_HD_M_CTL, 0);
> +               HDMI_WRITE(HDMI_M_CTL, 0);
>
> -               HD_WRITE(VC4_HD_M_CTL, VC4_HD_M_ENABLE);
> +               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
>         }
>         pm_runtime_enable(dev);
>
> @@ -1322,8 +1321,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
>         cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
>
> -       HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
> -       value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
> +       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> +       value = HDMI_READ(HDMI_CEC_CNTRL_1);
>         value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
>         /*
>          * Set the logical address to Unregistered and set the clock
> @@ -1332,7 +1331,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>          */
>         value |= VC4_HDMI_CEC_ADDR_MASK |
>                  (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> -       HDMI_WRITE(VC4_HDMI_CEC_CNTRL_1, value);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
>         ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
>                                         vc4_cec_irq_handler,
>                                         vc4_cec_irq_handler_thread, 0,
> @@ -1395,6 +1394,9 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
>         vc4_hdmi = dev_get_drvdata(dev);
>
> +       kfree(vc4_hdmi->hdmi_regset.regs);
> +       kfree(vc4_hdmi->hd_regset.regs);
> +
>         cec_unregister_adapter(vc4_hdmi->cec_adap);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
> @@ -1422,6 +1424,9 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  }
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .registers              = vc4_hdmi_fields,
> +       .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
> +
>         .init_resources         = vc4_hdmi_init_resources,
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0eaf979fe811..b36e0210671f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -22,8 +22,15 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_hdmi;
> +struct vc4_hdmi_register;
>
>  struct vc4_hdmi_variant {
> +       /* List of the registers available on that variant */
> +       const struct vc4_hdmi_register *registers;
> +
> +       /* Number of registers on that variant */
> +       unsigned int num_registers;
> +
>         /* Callback to get the resources (memory region, interrupts,
>          * clocks, etc) for that variant.
>          */
> @@ -85,9 +92,4 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>         return container_of(_encoder, struct vc4_hdmi, encoder);
>  }
>
> -#define HDMI_READ(offset) readl(vc4_hdmi->hdmicore_regs + offset)
> -#define HDMI_WRITE(offset, val) writel(val, vc4_hdmi->hdmicore_regs + offset)
> -#define HD_READ(offset) readl(vc4_hdmi->hd_regs + offset)
> -#define HD_WRITE(offset, val) writel(val, vc4_hdmi->hd_regs + offset)
> -
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> new file mode 100644
> index 000000000000..bc47cc9bc883
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -0,0 +1,241 @@
> +#ifndef _VC4_HDMI_REGS_H_
> +#define _VC4_HDMI_REGS_H_
> +
> +#include "vc4_hdmi.h"
> +
> +#define VC4_HDMI_PACKET_STRIDE                 0x24
> +
> +enum vc4_hdmi_regs {
> +       VC4_INVALID = 0,
> +       VC4_HDMI,
> +       VC4_HD,
> +};
> +
> +enum vc4_hdmi_field {
> +       HDMI_AUDIO_PACKET_CONFIG,
> +       HDMI_CEC_CNTRL_1,
> +       HDMI_CEC_CNTRL_2,
> +       HDMI_CEC_CNTRL_3,
> +       HDMI_CEC_CNTRL_4,
> +       HDMI_CEC_CNTRL_5,
> +       HDMI_CEC_CPU_CLEAR,
> +       HDMI_CEC_CPU_MASK_CLEAR,
> +       HDMI_CEC_CPU_MASK_SET,
> +       HDMI_CEC_CPU_MASK_STATUS,
> +       HDMI_CEC_CPU_STATUS,
> +
> +       /*
> +        * Transmit data, first byte is low byte of the 32-bit reg.
> +        * MSB of each byte transmitted first.
> +        */
> +       HDMI_CEC_RX_DATA_1,
> +       HDMI_CEC_RX_DATA_2,
> +       HDMI_CEC_RX_DATA_3,
> +       HDMI_CEC_RX_DATA_4,
> +       HDMI_CEC_TX_DATA_1,
> +       HDMI_CEC_TX_DATA_2,
> +       HDMI_CEC_TX_DATA_3,
> +       HDMI_CEC_TX_DATA_4,
> +       HDMI_CORE_REV,
> +       HDMI_CRP_CFG,
> +       HDMI_CSC_12_11,
> +       HDMI_CSC_14_13,
> +       HDMI_CSC_22_21,
> +       HDMI_CSC_24_23,
> +       HDMI_CSC_32_31,
> +       HDMI_CSC_34_33,
> +       HDMI_CSC_CTL,
> +
> +       /*
> +        * 20-bit fields containing CTS values to be transmitted if
> +        * !EXTERNAL_CTS_EN
> +        */
> +       HDMI_CTS_0,
> +       HDMI_CTS_1,
> +       HDMI_FIFO_CTL,
> +       HDMI_FRAME_COUNT,
> +       HDMI_HORZA,
> +       HDMI_HORZB,
> +       HDMI_HOTPLUG,
> +       HDMI_HOTPLUG_INT,
> +
> +       /*
> +        * 3 bits per field, where each field maps from that
> +        * corresponding MAI bus channel to the given HDMI channel.
> +        */
> +       HDMI_MAI_CHANNEL_MAP,
> +       HDMI_MAI_CONFIG,
> +       HDMI_MAI_CTL,
> +
> +       /*
> +        * Register for DMAing in audio data to be transported over
> +        * the MAI bus to the Falcon core.
> +        */
> +       HDMI_MAI_DATA,
> +
> +       /* Format header to be placed on the MAI data. Unused. */
> +       HDMI_MAI_FMT,
> +
> +       /* Last received format word on the MAI bus. */
> +       HDMI_MAI_FORMAT,
> +       HDMI_MAI_SMP,
> +       HDMI_MAI_THR,
> +       HDMI_M_CTL,
> +       HDMI_RAM_PACKET_CONFIG,
> +       HDMI_RAM_PACKET_START,
> +       HDMI_RAM_PACKET_STATUS,
> +       HDMI_SCHEDULER_CONTROL,
> +       HDMI_SW_RESET_CONTROL,
> +       HDMI_TX_PHY_CTL_0,
> +       HDMI_TX_PHY_RESET_CTL,
> +       HDMI_VERTA0,
> +       HDMI_VERTA1,
> +       HDMI_VERTB0,
> +       HDMI_VERTB1,
> +       HDMI_VID_CTL,
> +};
> +
> +struct vc4_hdmi_register {
> +       char *name;
> +       enum vc4_hdmi_regs reg;
> +       unsigned int offset;
> +};
> +
> +#define _VC4_REG(_base, _reg, _offset) \
> +       [_reg] = {                              \
> +               .name = #_reg,                  \
> +               .reg = _base,                   \
> +               .offset = _offset,              \
> +       }
> +
> +#define VC4_HD_REG(reg, offset)                _VC4_REG(VC4_HD, reg, offset)
> +#define VC4_HDMI_REG(reg, offset)      _VC4_REG(VC4_HDMI, reg, offset)
> +
> +static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
> +       VC4_HD_REG(HDMI_M_CTL, 0x000c),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0014),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0018),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x001c),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x0020),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x002c),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0038),
> +       VC4_HD_REG(HDMI_CSC_CTL, 0x0040),
> +       VC4_HD_REG(HDMI_CSC_12_11, 0x0044),
> +       VC4_HD_REG(HDMI_CSC_14_13, 0x0048),
> +       VC4_HD_REG(HDMI_CSC_22_21, 0x004c),
> +       VC4_HD_REG(HDMI_CSC_24_23, 0x0050),
> +       VC4_HD_REG(HDMI_CSC_32_31, 0x0054),
> +       VC4_HD_REG(HDMI_CSC_34_33, 0x0058),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0068),
> +
> +       VC4_HDMI_REG(HDMI_CORE_REV, 0x0000),
> +       VC4_HDMI_REG(HDMI_SW_RESET_CONTROL, 0x0004),
> +       VC4_HDMI_REG(HDMI_HOTPLUG_INT, 0x0008),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x000c),
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x005c),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x0090),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0094),
> +       VC4_HDMI_REG(HDMI_MAI_FORMAT, 0x0098),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x009c),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x00a0),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x00a4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x00a8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x00ac),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x00b0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x00c0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x00c4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x00c8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x00cc),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x00d0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x00d4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x00d8),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_1, 0x00e8),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_2, 0x00ec),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_3, 0x00f0),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_4, 0x00f4),
> +       VC4_HDMI_REG(HDMI_CEC_CNTRL_5, 0x00f8),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_1, 0x00fc),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_2, 0x0100),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_3, 0x0104),
> +       VC4_HDMI_REG(HDMI_CEC_TX_DATA_4, 0x0108),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_1, 0x010c),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_2, 0x0110),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_3, 0x0114),
> +       VC4_HDMI_REG(HDMI_CEC_RX_DATA_4, 0x0118),
> +       VC4_HDMI_REG(HDMI_TX_PHY_RESET_CTL, 0x02c0),
> +       VC4_HDMI_REG(HDMI_TX_PHY_CTL_0, 0x02c4),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_STATUS, 0x0340),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_CLEAR, 0x0348),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_STATUS, 0x034c),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_SET, 0x034c),
> +       VC4_HDMI_REG(HDMI_CEC_CPU_MASK_CLEAR, 0x0354),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
> +};
> +
> +static inline
> +void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
> +                                       enum vc4_hdmi_regs reg)
> +{
> +       switch (reg) {
> +       case VC4_HD:
> +               return hdmi->hd_regs;
> +
> +       case VC4_HDMI:
> +               return hdmi->hdmicore_regs;
> +
> +       default:
> +               return NULL;
> +       }
> +
> +       return NULL;
> +}
> +
> +static inline u32 vc4_hdmi_read(struct vc4_hdmi *hdmi,
> +                               enum vc4_hdmi_regs reg)
> +{
> +       const struct vc4_hdmi_register *field;
> +       const struct vc4_hdmi_variant *variant = hdmi->variant;
> +       void __iomem *base;
> +
> +       if (reg > variant->num_registers) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Invalid register ID %u\n", reg);
> +               return 0;
> +       }
> +
> +       field = &variant->registers[reg];
> +       base = __vc4_hdmi_get_field_base(hdmi, field->reg);
> +       if (!base) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Unknown register ID %u\n", reg);
> +               return 0;
> +       }
> +
> +       return readl(base + field->offset);
> +}
> +#define HDMI_READ(reg)         vc4_hdmi_read(vc4_hdmi, reg)
> +
> +static inline void vc4_hdmi_write(struct vc4_hdmi *hdmi,
> +                                 enum vc4_hdmi_regs reg,
> +                                 u32 value)
> +{
> +       const struct vc4_hdmi_register *field;
> +       const struct vc4_hdmi_variant *variant = hdmi->variant;
> +       void __iomem *base;
> +
> +       if (reg > variant->num_registers) {
> +               dev_warn(&hdmi->pdev->dev,
> +                        "Invalid register ID %u\n", reg);
> +               return;
> +       }
> +
> +       field = &variant->registers[reg];
> +       base = __vc4_hdmi_get_field_base(hdmi, field->reg);
> +       if (!base)
> +               return;
> +
> +       writel(value, base + field->offset);
> +}
> +#define HDMI_WRITE(reg, val)   vc4_hdmi_write(vc4_hdmi, reg, val)
> +
> +#endif /* _VC4_HDMI_REGS_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index c0031ab19689..d1e8961edaa0 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -493,32 +493,16 @@
>
>  #define SCALER5_DLIST_START                    0x00004000
>
> -#define VC4_HDMI_CORE_REV                      0x000
> -
> -#define VC4_HDMI_SW_RESET_CONTROL              0x004
>  # define VC4_HDMI_SW_RESET_FORMAT_DETECT       BIT(1)
>  # define VC4_HDMI_SW_RESET_HDMI                        BIT(0)
>
> -#define VC4_HDMI_HOTPLUG_INT                   0x008
> -
> -#define VC4_HDMI_HOTPLUG                       0x00c
>  # define VC4_HDMI_HOTPLUG_CONNECTED            BIT(0)
>
> -/* 3 bits per field, where each field maps from that corresponding MAI
> - * bus channel to the given HDMI channel.
> - */
> -#define VC4_HDMI_MAI_CHANNEL_MAP               0x090
> -
> -#define VC4_HDMI_MAI_CONFIG                    0x094
>  # define VC4_HDMI_MAI_CONFIG_FORMAT_REVERSE            BIT(27)
>  # define VC4_HDMI_MAI_CONFIG_BIT_REVERSE               BIT(26)
>  # define VC4_HDMI_MAI_CHANNEL_MASK_MASK                        VC4_MASK(15, 0)
>  # define VC4_HDMI_MAI_CHANNEL_MASK_SHIFT               0
>
> -/* Last received format word on the MAI bus. */
> -#define VC4_HDMI_MAI_FORMAT                    0x098
> -
> -#define VC4_HDMI_AUDIO_PACKET_CONFIG           0x09c
>  # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_SAMPLE_FLAT                BIT(29)
>  # define VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS  BIT(24)
>  # define VC4_HDMI_AUDIO_PACKET_FORCE_SAMPLE_PRESENT            BIT(19)
> @@ -532,12 +516,8 @@
>  # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_MASK                   VC4_MASK(7, 0)
>  # define VC4_HDMI_AUDIO_PACKET_CEA_MASK_SHIFT                  0
>
> -#define VC4_HDMI_RAM_PACKET_CONFIG             0x0a0
>  # define VC4_HDMI_RAM_PACKET_ENABLE            BIT(16)
>
> -#define VC4_HDMI_RAM_PACKET_STATUS             0x0a4
> -
> -#define VC4_HDMI_CRP_CFG                       0x0a8
>  /* When set, the CTS_PERIOD counts based on MAI bus sync pulse instead
>   * of pixel clock.
>   */
> @@ -551,23 +531,12 @@
>  # define VC4_HDMI_CRP_CFG_N_MASK               VC4_MASK(19, 0)
>  # define VC4_HDMI_CRP_CFG_N_SHIFT              0
>
> -/* 20-bit fields containing CTS values to be transmitted if !EXTERNAL_CTS_EN */
> -#define VC4_HDMI_CTS_0                         0x0ac
> -#define VC4_HDMI_CTS_1                         0x0b0
> -/* 20-bit fields containing number of clocks to send CTS0/1 before
> - * switching to the other one.
> - */
> -#define VC4_HDMI_CTS_PERIOD_0                  0x0b4
> -#define VC4_HDMI_CTS_PERIOD_1                  0x0b8
> -
> -#define VC4_HDMI_HORZA                         0x0c4
>  # define VC4_HDMI_HORZA_VPOS                   BIT(14)
>  # define VC4_HDMI_HORZA_HPOS                   BIT(13)
>  /* Horizontal active pixels (hdisplay). */
>  # define VC4_HDMI_HORZA_HAP_MASK               VC4_MASK(12, 0)
>  # define VC4_HDMI_HORZA_HAP_SHIFT              0
>
> -#define VC4_HDMI_HORZB                         0x0c8
>  /* Horizontal pack porch (htotal - hsync_end). */
>  # define VC4_HDMI_HORZB_HBP_MASK               VC4_MASK(29, 20)
>  # define VC4_HDMI_HORZB_HBP_SHIFT              20
> @@ -578,7 +547,6 @@
>  # define VC4_HDMI_HORZB_HFP_MASK               VC4_MASK(9, 0)
>  # define VC4_HDMI_HORZB_HFP_SHIFT              0
>
> -#define VC4_HDMI_FIFO_CTL                      0x05c
>  # define VC4_HDMI_FIFO_CTL_RECENTER_DONE       BIT(14)
>  # define VC4_HDMI_FIFO_CTL_USE_EMPTY           BIT(13)
>  # define VC4_HDMI_FIFO_CTL_ON_VB               BIT(7)
> @@ -591,15 +559,12 @@
>  # define VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N      BIT(0)
>  # define VC4_HDMI_FIFO_VALID_WRITE_MASK                0xefff
>
> -#define VC4_HDMI_SCHEDULER_CONTROL             0x0c0
>  # define VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT BIT(15)
>  # define VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS BIT(5)
>  # define VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT        BIT(3)
>  # define VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE        BIT(1)
>  # define VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI  BIT(0)
>
> -#define VC4_HDMI_VERTA0                                0x0cc
> -#define VC4_HDMI_VERTA1                                0x0d4
>  /* Vertical sync pulse (vsync_end - vsync_start). */
>  # define VC4_HDMI_VERTA_VSP_MASK               VC4_MASK(24, 20)
>  # define VC4_HDMI_VERTA_VSP_SHIFT              20
> @@ -610,8 +575,6 @@
>  # define VC4_HDMI_VERTA_VAL_MASK               VC4_MASK(12, 0)
>  # define VC4_HDMI_VERTA_VAL_SHIFT              0
>
> -#define VC4_HDMI_VERTB0                                0x0d0
> -#define VC4_HDMI_VERTB1                                0x0d8
>  /* Vertical sync pulse offset (for interlaced) */
>  # define VC4_HDMI_VERTB_VSPO_MASK              VC4_MASK(21, 9)
>  # define VC4_HDMI_VERTB_VSPO_SHIFT             9
> @@ -619,7 +582,6 @@
>  # define VC4_HDMI_VERTB_VBP_MASK               VC4_MASK(8, 0)
>  # define VC4_HDMI_VERTB_VBP_SHIFT              0
>
> -#define VC4_HDMI_CEC_CNTRL_1                   0x0e8
>  /* Set when the transmission has ended. */
>  # define VC4_HDMI_CEC_TX_EOM                   BIT(31)
>  /* If set, transmission was acked on the 1st or 2nd attempt (only one
> @@ -660,7 +622,6 @@
>  /* Set these fields to how many bit clock cycles get to that many
>   * microseconds.
>   */
> -#define VC4_HDMI_CEC_CNTRL_2                   0x0ec
>  # define VC4_HDMI_CEC_CNT_TO_1500_US_MASK      VC4_MASK(30, 24)
>  # define VC4_HDMI_CEC_CNT_TO_1500_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_1300_US_MASK      VC4_MASK(23, 17)
> @@ -672,7 +633,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_400_US_MASK       VC4_MASK(4, 0)
>  # define VC4_HDMI_CEC_CNT_TO_400_US_SHIFT      0
>
> -#define VC4_HDMI_CEC_CNTRL_3                   0x0f0
>  # define VC4_HDMI_CEC_CNT_TO_2750_US_MASK      VC4_MASK(31, 24)
>  # define VC4_HDMI_CEC_CNT_TO_2750_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_2400_US_MASK      VC4_MASK(23, 16)
> @@ -682,7 +642,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_1700_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_1700_US_SHIFT     0
>
> -#define VC4_HDMI_CEC_CNTRL_4                   0x0f4
>  # define VC4_HDMI_CEC_CNT_TO_4300_US_MASK      VC4_MASK(31, 24)
>  # define VC4_HDMI_CEC_CNT_TO_4300_US_SHIFT     24
>  # define VC4_HDMI_CEC_CNT_TO_3900_US_MASK      VC4_MASK(23, 16)
> @@ -692,7 +651,6 @@
>  # define VC4_HDMI_CEC_CNT_TO_3500_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_3500_US_SHIFT     0
>
> -#define VC4_HDMI_CEC_CNTRL_5                   0x0f8
>  # define VC4_HDMI_CEC_TX_SW_RESET              BIT(27)
>  # define VC4_HDMI_CEC_RX_SW_RESET              BIT(26)
>  # define VC4_HDMI_CEC_PAD_SW_RESET             BIT(25)
> @@ -705,39 +663,11 @@
>  # define VC4_HDMI_CEC_CNT_TO_4500_US_MASK      VC4_MASK(7, 0)
>  # define VC4_HDMI_CEC_CNT_TO_4500_US_SHIFT     0
>
> -/* Transmit data, first byte is low byte of the 32-bit reg.  MSB of
> - * each byte transmitted first.
> - */
> -#define VC4_HDMI_CEC_TX_DATA_1                 0x0fc
> -#define VC4_HDMI_CEC_TX_DATA_2                 0x100
> -#define VC4_HDMI_CEC_TX_DATA_3                 0x104
> -#define VC4_HDMI_CEC_TX_DATA_4                 0x108
> -#define VC4_HDMI_CEC_RX_DATA_1                 0x10c
> -#define VC4_HDMI_CEC_RX_DATA_2                 0x110
> -#define VC4_HDMI_CEC_RX_DATA_3                 0x114
> -#define VC4_HDMI_CEC_RX_DATA_4                 0x118
> -
> -#define VC4_HDMI_TX_PHY_RESET_CTL              0x2c0
> -
> -#define VC4_HDMI_TX_PHY_CTL0                   0x2c4
>  # define VC4_HDMI_TX_PHY_RNG_PWRDN             BIT(25)
>
> -/* Interrupt status bits */
> -#define VC4_HDMI_CPU_STATUS                    0x340
> -#define VC4_HDMI_CPU_SET                       0x344
> -#define VC4_HDMI_CPU_CLEAR                     0x348
>  # define VC4_HDMI_CPU_CEC                      BIT(6)
>  # define VC4_HDMI_CPU_HOTPLUG                  BIT(0)
>
> -#define VC4_HDMI_CPU_MASK_STATUS               0x34c
> -#define VC4_HDMI_CPU_MASK_SET                  0x350
> -#define VC4_HDMI_CPU_MASK_CLEAR                        0x354
> -
> -#define VC4_HDMI_GCP(x)                                (0x400 + ((x) * 0x4))
> -#define VC4_HDMI_RAM_PACKET(x)                 (0x400 + ((x) * 0x24))
> -#define VC4_HDMI_PACKET_STRIDE                 0x24
> -
> -#define VC4_HD_M_CTL                           0x00c
>  /* Debug: Current receive value on the CEC pad. */
>  # define VC4_HD_CECRXD                         BIT(9)
>  /* Debug: Override CEC output to 0. */
> @@ -747,7 +677,6 @@
>  # define VC4_HD_M_SW_RST                       BIT(2)
>  # define VC4_HD_M_ENABLE                       BIT(0)
>
> -#define VC4_HD_MAI_CTL                         0x014
>  /* Set when audio stream is received at a slower rate than the
>   * sampling period, so MAI fifo goes empty.  Write 1 to clear.
>   */
> @@ -772,7 +701,6 @@
>  /* Single-shot reset bit.  Read value is undefined. */
>  # define VC4_HD_MAI_CTL_RESET                  BIT(0)
>
> -#define VC4_HD_MAI_THR                         0x018
>  # define VC4_HD_MAI_THR_PANICHIGH_MASK         VC4_MASK(29, 24)
>  # define VC4_HD_MAI_THR_PANICHIGH_SHIFT                24
>  # define VC4_HD_MAI_THR_PANICLOW_MASK          VC4_MASK(21, 16)
> @@ -782,31 +710,20 @@
>  # define VC4_HD_MAI_THR_DREQLOW_MASK           VC4_MASK(5, 0)
>  # define VC4_HD_MAI_THR_DREQLOW_SHIFT          0
>
> -/* Format header to be placed on the MAI data. Unused. */
> -#define VC4_HD_MAI_FMT                         0x01c
> -
> -/* Register for DMAing in audio data to be transported over the MAI
> - * bus to the Falcon core.
> - */
> -#define VC4_HD_MAI_DATA                                0x020
> -
>  /* Divider from HDMI HSM clock to MAI serial clock.  Sampling period
>   * converges to N / (M + 1) cycles.
>   */
> -#define VC4_HD_MAI_SMP                         0x02c
>  # define VC4_HD_MAI_SMP_N_MASK                 VC4_MASK(31, 8)
>  # define VC4_HD_MAI_SMP_N_SHIFT                        8
>  # define VC4_HD_MAI_SMP_M_MASK                 VC4_MASK(7, 0)
>  # define VC4_HD_MAI_SMP_M_SHIFT                        0
>
> -#define VC4_HD_VID_CTL                         0x038
>  # define VC4_HD_VID_CTL_ENABLE                 BIT(31)
>  # define VC4_HD_VID_CTL_UNDERFLOW_ENABLE       BIT(30)
>  # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET    BIT(29)
>  # define VC4_HD_VID_CTL_VSYNC_LOW              BIT(28)
>  # define VC4_HD_VID_CTL_HSYNC_LOW              BIT(27)
>
> -#define VC4_HD_CSC_CTL                         0x040
>  # define VC4_HD_CSC_CTL_ORDER_MASK             VC4_MASK(7, 5)
>  # define VC4_HD_CSC_CTL_ORDER_SHIFT            5
>  # define VC4_HD_CSC_CTL_ORDER_RGB              0
> @@ -824,15 +741,6 @@
>  # define VC4_HD_CSC_CTL_RGB2YCC                        BIT(1)
>  # define VC4_HD_CSC_CTL_ENABLE                 BIT(0)
>
> -#define VC4_HD_CSC_12_11                       0x044
> -#define VC4_HD_CSC_14_13                       0x048
> -#define VC4_HD_CSC_22_21                       0x04c
> -#define VC4_HD_CSC_24_23                       0x050
> -#define VC4_HD_CSC_32_31                       0x054
> -#define VC4_HD_CSC_34_33                       0x058
> -
> -#define VC4_HD_FRAME_COUNT                     0x068
> -
>  /* HVS display list information. */
>  #define HVS_BOOTLOADER_DLIST_END                32
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:00       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The BCM2711 and BCM283x HDMI controllers use a slightly different reset
> sequence, so let's add a callback to reset the controller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++-------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
>  2 files changed, 21 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a4fed1439bf3..80bc3dd9d4a8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>         return 0;
>  }
>
> +static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
> +       udelay(1);
> +       HDMI_WRITE(HDMI_M_CTL, 0);
> +
> +       HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
> +
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
> +                  VC4_HDMI_SW_RESET_HDMI |
> +                  VC4_HDMI_SW_RESET_FORMAT_DETECT);
> +
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
> +}
> +
>  static enum drm_connector_status
>  vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
> -                  VC4_HDMI_SW_RESET_HDMI |
> -                  VC4_HDMI_SW_RESET_FORMAT_DETECT);
> -
> -       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
> +       if (vc4_hdmi->variant->reset)
> +               vc4_hdmi->variant->reset(vc4_hdmi);
>
>         /* PHY should be in reset, like
>          * vc4_hdmi_encoder_disable() does.
> @@ -1292,14 +1304,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                 vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
>         }
>
> -       /* HDMI core must be enabled. */
> -       if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
> -               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
> -               udelay(1);
> -               HDMI_WRITE(HDMI_M_CTL, 0);
> -
> -               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
> -       }
>         pm_runtime_enable(dev);
>
>         drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> @@ -1428,6 +1432,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
>         .init_resources         = vc4_hdmi_init_resources,
> +       .reset                  = vc4_hdmi_reset,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index b36e0210671f..17a30589f39c 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -35,6 +35,9 @@ struct vc4_hdmi_variant {
>          * clocks, etc) for that variant.
>          */
>         int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to reset the HDMI block */
> +       void (*reset)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> --
> git-series 0.9.1

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

* Re: [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback
@ 2020-07-28 13:00       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The BCM2711 and BCM283x HDMI controllers use a slightly different reset
> sequence, so let's add a callback to reset the controller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++-------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
>  2 files changed, 21 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a4fed1439bf3..80bc3dd9d4a8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>         return 0;
>  }
>
> +static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
> +       udelay(1);
> +       HDMI_WRITE(HDMI_M_CTL, 0);
> +
> +       HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
> +
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
> +                  VC4_HDMI_SW_RESET_HDMI |
> +                  VC4_HDMI_SW_RESET_FORMAT_DETECT);
> +
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
> +}
> +
>  static enum drm_connector_status
>  vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
> -                  VC4_HDMI_SW_RESET_HDMI |
> -                  VC4_HDMI_SW_RESET_FORMAT_DETECT);
> -
> -       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
> +       if (vc4_hdmi->variant->reset)
> +               vc4_hdmi->variant->reset(vc4_hdmi);
>
>         /* PHY should be in reset, like
>          * vc4_hdmi_encoder_disable() does.
> @@ -1292,14 +1304,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                 vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
>         }
>
> -       /* HDMI core must be enabled. */
> -       if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
> -               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
> -               udelay(1);
> -               HDMI_WRITE(HDMI_M_CTL, 0);
> -
> -               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
> -       }
>         pm_runtime_enable(dev);
>
>         drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> @@ -1428,6 +1432,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
>         .init_resources         = vc4_hdmi_init_resources,
> +       .reset                  = vc4_hdmi_reset,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index b36e0210671f..17a30589f39c 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -35,6 +35,9 @@ struct vc4_hdmi_variant {
>          * clocks, etc) for that variant.
>          */
>         int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to reset the HDMI block */
> +       void (*reset)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback
@ 2020-07-28 13:00       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The BCM2711 and BCM283x HDMI controllers use a slightly different reset
> sequence, so let's add a callback to reset the controller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 31 ++++++++++++++++++-------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +++
>  2 files changed, 21 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a4fed1439bf3..80bc3dd9d4a8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -69,6 +69,21 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>         return 0;
>  }
>
> +static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
> +       udelay(1);
> +       HDMI_WRITE(HDMI_M_CTL, 0);
> +
> +       HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
> +
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
> +                  VC4_HDMI_SW_RESET_HDMI |
> +                  VC4_HDMI_SW_RESET_FORMAT_DETECT);
> +
> +       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
> +}
> +
>  static enum drm_connector_status
>  vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -363,11 +378,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       HDMI_WRITE(HDMI_SW_RESET_CONTROL,
> -                  VC4_HDMI_SW_RESET_HDMI |
> -                  VC4_HDMI_SW_RESET_FORMAT_DETECT);
> -
> -       HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
> +       if (vc4_hdmi->variant->reset)
> +               vc4_hdmi->variant->reset(vc4_hdmi);
>
>         /* PHY should be in reset, like
>          * vc4_hdmi_encoder_disable() does.
> @@ -1292,14 +1304,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                 vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW;
>         }
>
> -       /* HDMI core must be enabled. */
> -       if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) {
> -               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST);
> -               udelay(1);
> -               HDMI_WRITE(HDMI_M_CTL, 0);
> -
> -               HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE);
> -       }
>         pm_runtime_enable(dev);
>
>         drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
> @@ -1428,6 +1432,7 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
>         .init_resources         = vc4_hdmi_init_resources,
> +       .reset                  = vc4_hdmi_reset,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index b36e0210671f..17a30589f39c 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -35,6 +35,9 @@ struct vc4_hdmi_variant {
>          * clocks, etc) for that variant.
>          */
>         int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to reset the HDMI block */
> +       void (*reset)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:03       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI PHY in the BCM2711 HDMI controller is significantly more
> complicated to setup than in the older BCM283x SoCs.
>
> Let's add hooks to enable and disable the PHY.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/Makefile       |  1 +
>  drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++-------
>  drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
>  4 files changed, 46 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>
> diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
> index b303703bc7f3..d0163e18e9ca 100644
> --- a/drivers/gpu/drm/vc4/Makefile
> +++ b/drivers/gpu/drm/vc4/Makefile
> @@ -12,6 +12,7 @@ vc4-y := \
>         vc4_kms.o \
>         vc4_gem.o \
>         vc4_hdmi.o \
> +       vc4_hdmi_phy.o \
>         vc4_vec.o \
>         vc4_hvs.o \
>         vc4_irq.o \
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 80bc3dd9d4a8..068041145d1c 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
>
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       if (vc4_hdmi->variant->phy_disable)
> +               vc4_hdmi->variant->phy_disable(vc4_hdmi);
> +
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
> @@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->reset)
>                 vc4_hdmi->variant->reset(vc4_hdmi);
>
> -       /* PHY should be in reset, like
> -        * vc4_hdmi_encoder_disable() does.
> -        */
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> -
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
> +       if (vc4_hdmi->variant->phy_init)
> +               vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -1433,6 +1431,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>
>         .init_resources         = vc4_hdmi_init_resources,
>         .reset                  = vc4_hdmi_reset,
> +       .phy_init               = vc4_hdmi_phy_init,
> +       .phy_disable            = vc4_hdmi_phy_disable,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 17a30589f39c..32c80161c786 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>         return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>  }
>
> +struct drm_display_mode;
> +
>  struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
> @@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
>
>         /* Callback to reset the HDMI block */
>         void (*reset)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to initialize the PHY according to the mode */
> +       void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
> +                        struct drm_display_mode *mode);
> +
> +       /* Callback to disable the PHY */
> +       void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> @@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>         return container_of(_encoder, struct vc4_hdmi, encoder);
>  }
>
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +                      struct drm_display_mode *mode);
> +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> new file mode 100644
> index 000000000000..5a1746877bb5
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2015 Broadcom
> + * Copyright (c) 2014 The Linux Foundation. All rights reserved.
> + * Copyright (C) 2013 Red Hat
> + * Author: Rob Clark <robdclark@gmail.com>
> + */
> +
> +#include "vc4_hdmi.h"
> +#include "vc4_hdmi_regs.h"
> +
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +{
> +       /* PHY should be in reset, like
> +        * vc4_hdmi_encoder_disable() does.
> +        */
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
> +}
> +
> +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +}
> --
> git-series 0.9.1

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

* Re: [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function
@ 2020-07-28 13:03       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI PHY in the BCM2711 HDMI controller is significantly more
> complicated to setup than in the older BCM283x SoCs.
>
> Let's add hooks to enable and disable the PHY.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/Makefile       |  1 +
>  drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++-------
>  drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
>  4 files changed, 46 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>
> diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
> index b303703bc7f3..d0163e18e9ca 100644
> --- a/drivers/gpu/drm/vc4/Makefile
> +++ b/drivers/gpu/drm/vc4/Makefile
> @@ -12,6 +12,7 @@ vc4-y := \
>         vc4_kms.o \
>         vc4_gem.o \
>         vc4_hdmi.o \
> +       vc4_hdmi_phy.o \
>         vc4_vec.o \
>         vc4_hvs.o \
>         vc4_irq.o \
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 80bc3dd9d4a8..068041145d1c 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
>
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       if (vc4_hdmi->variant->phy_disable)
> +               vc4_hdmi->variant->phy_disable(vc4_hdmi);
> +
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
> @@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->reset)
>                 vc4_hdmi->variant->reset(vc4_hdmi);
>
> -       /* PHY should be in reset, like
> -        * vc4_hdmi_encoder_disable() does.
> -        */
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> -
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
> +       if (vc4_hdmi->variant->phy_init)
> +               vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -1433,6 +1431,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>
>         .init_resources         = vc4_hdmi_init_resources,
>         .reset                  = vc4_hdmi_reset,
> +       .phy_init               = vc4_hdmi_phy_init,
> +       .phy_disable            = vc4_hdmi_phy_disable,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 17a30589f39c..32c80161c786 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>         return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>  }
>
> +struct drm_display_mode;
> +
>  struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
> @@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
>
>         /* Callback to reset the HDMI block */
>         void (*reset)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to initialize the PHY according to the mode */
> +       void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
> +                        struct drm_display_mode *mode);
> +
> +       /* Callback to disable the PHY */
> +       void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> @@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>         return container_of(_encoder, struct vc4_hdmi, encoder);
>  }
>
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +                      struct drm_display_mode *mode);
> +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> new file mode 100644
> index 000000000000..5a1746877bb5
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2015 Broadcom
> + * Copyright (c) 2014 The Linux Foundation. All rights reserved.
> + * Copyright (C) 2013 Red Hat
> + * Author: Rob Clark <robdclark@gmail.com>
> + */
> +
> +#include "vc4_hdmi.h"
> +#include "vc4_hdmi_regs.h"
> +
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +{
> +       /* PHY should be in reset, like
> +        * vc4_hdmi_encoder_disable() does.
> +        */
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
> +}
> +
> +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +}
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function
@ 2020-07-28 13:03       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI PHY in the BCM2711 HDMI controller is significantly more
> complicated to setup than in the older BCM283x SoCs.
>
> Let's add hooks to enable and disable the PHY.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/Makefile       |  1 +
>  drivers/gpu/drm/vc4/vc4_hdmi.c     | 14 +++++++-------
>  drivers/gpu/drm/vc4/vc4_hdmi.h     | 13 +++++++++++++
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 25 +++++++++++++++++++++++++
>  4 files changed, 46 insertions(+), 7 deletions(-)
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>
> diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile
> index b303703bc7f3..d0163e18e9ca 100644
> --- a/drivers/gpu/drm/vc4/Makefile
> +++ b/drivers/gpu/drm/vc4/Makefile
> @@ -12,6 +12,7 @@ vc4-y := \
>         vc4_kms.o \
>         vc4_gem.o \
>         vc4_hdmi.o \
> +       vc4_hdmi_phy.o \
>         vc4_vec.o \
>         vc4_hvs.o \
>         vc4_irq.o \
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 80bc3dd9d4a8..068041145d1c 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -321,7 +321,9 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
>
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       if (vc4_hdmi->variant->phy_disable)
> +               vc4_hdmi->variant->phy_disable(vc4_hdmi);
> +
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
> @@ -381,12 +383,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->reset)
>                 vc4_hdmi->variant->reset(vc4_hdmi);
>
> -       /* PHY should be in reset, like
> -        * vc4_hdmi_encoder_disable() does.
> -        */
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> -
> -       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
> +       if (vc4_hdmi->variant->phy_init)
> +               vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
>         if (debug_dump_regs) {
>                 struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> @@ -1433,6 +1431,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>
>         .init_resources         = vc4_hdmi_init_resources,
>         .reset                  = vc4_hdmi_reset,
> +       .phy_init               = vc4_hdmi_phy_init,
> +       .phy_disable            = vc4_hdmi_phy_disable,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 17a30589f39c..32c80161c786 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -21,6 +21,8 @@ to_vc4_hdmi_encoder(struct drm_encoder *encoder)
>         return container_of(encoder, struct vc4_hdmi_encoder, base.base);
>  }
>
> +struct drm_display_mode;
> +
>  struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
> @@ -38,6 +40,13 @@ struct vc4_hdmi_variant {
>
>         /* Callback to reset the HDMI block */
>         void (*reset)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to initialize the PHY according to the mode */
> +       void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
> +                        struct drm_display_mode *mode);
> +
> +       /* Callback to disable the PHY */
> +       void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> @@ -95,4 +104,8 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>         return container_of(_encoder, struct vc4_hdmi, encoder);
>  }
>
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +                      struct drm_display_mode *mode);
> +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> new file mode 100644
> index 000000000000..5a1746877bb5
> --- /dev/null
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2015 Broadcom
> + * Copyright (c) 2014 The Linux Foundation. All rights reserved.
> + * Copyright (C) 2013 Red Hat
> + * Author: Rob Clark <robdclark@gmail.com>
> + */
> +
> +#include "vc4_hdmi.h"
> +#include "vc4_hdmi_regs.h"
> +
> +void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +{
> +       /* PHY should be in reset, like
> +        * vc4_hdmi_encoder_disable() does.
> +        */
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0);
> +}
> +
> +void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
> +}
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / disable function
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:04       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Let's continue the implementation of hooks for the parts that change in the
> BCM2711 SoC with the PHY RNG setup.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c     | 15 +++++++++------
>  drivers/gpu/drm/vc4/vc4_hdmi.h     |  8 ++++++++
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++
>  3 files changed, 32 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 068041145d1c..19897d6525ac 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 vc4_hdmi_set_audio_infoframe(encoder);
> -               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> -                          HDMI_READ(HDMI_TX_PHY_CTL_0) &
> -                          ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> +
> +               if (vc4_hdmi->variant->phy_rng_enable)
> +                       vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
>
>                 HDMI_WRITE(HDMI_MAI_CTL,
>                            VC4_SET_FIELD(vc4_hdmi->audio.channels,
> @@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                            VC4_HD_MAI_CTL_DLATE |
>                            VC4_HD_MAI_CTL_ERRORE |
>                            VC4_HD_MAI_CTL_ERRORF);
> -               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> -                          HDMI_READ(HDMI_TX_PHY_CTL_0) |
> -                          VC4_HDMI_TX_PHY_RNG_PWRDN);
> +
> +               if (vc4_hdmi->variant->phy_rng_disable)
> +                       vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
> +
>                 break;
>         default:
>                 break;
> @@ -1433,6 +1434,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .reset                  = vc4_hdmi_reset,
>         .phy_init               = vc4_hdmi_phy_init,
>         .phy_disable            = vc4_hdmi_phy_disable,
> +       .phy_rng_enable         = vc4_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc4_hdmi_phy_rng_disable,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 32c80161c786..950accbc44e4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -47,6 +47,12 @@ struct vc4_hdmi_variant {
>
>         /* Callback to disable the PHY */
>         void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to enable the RNG in the PHY */
> +       void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to disable the RNG in the PHY */
> +       void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> @@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
>                        struct drm_display_mode *mode);
>  void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
> +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 5a1746877bb5..93287e24d7d1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -7,6 +7,7 @@
>   */
>
>  #include "vc4_hdmi.h"
> +#include "vc4_regs.h"
>  #include "vc4_hdmi_regs.h"
>
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> @@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
>  {
>         HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
>  }
> +
> +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_0) &
> +                  ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> +}
> +
> +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_0) |
> +                  VC4_HDMI_TX_PHY_RNG_PWRDN);
> +}
> --
> git-series 0.9.1

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

* Re: [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / disable function
@ 2020-07-28 13:04       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Let's continue the implementation of hooks for the parts that change in the
> BCM2711 SoC with the PHY RNG setup.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c     | 15 +++++++++------
>  drivers/gpu/drm/vc4/vc4_hdmi.h     |  8 ++++++++
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++
>  3 files changed, 32 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 068041145d1c..19897d6525ac 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 vc4_hdmi_set_audio_infoframe(encoder);
> -               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> -                          HDMI_READ(HDMI_TX_PHY_CTL_0) &
> -                          ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> +
> +               if (vc4_hdmi->variant->phy_rng_enable)
> +                       vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
>
>                 HDMI_WRITE(HDMI_MAI_CTL,
>                            VC4_SET_FIELD(vc4_hdmi->audio.channels,
> @@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                            VC4_HD_MAI_CTL_DLATE |
>                            VC4_HD_MAI_CTL_ERRORE |
>                            VC4_HD_MAI_CTL_ERRORF);
> -               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> -                          HDMI_READ(HDMI_TX_PHY_CTL_0) |
> -                          VC4_HDMI_TX_PHY_RNG_PWRDN);
> +
> +               if (vc4_hdmi->variant->phy_rng_disable)
> +                       vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
> +
>                 break;
>         default:
>                 break;
> @@ -1433,6 +1434,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .reset                  = vc4_hdmi_reset,
>         .phy_init               = vc4_hdmi_phy_init,
>         .phy_disable            = vc4_hdmi_phy_disable,
> +       .phy_rng_enable         = vc4_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc4_hdmi_phy_rng_disable,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 32c80161c786..950accbc44e4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -47,6 +47,12 @@ struct vc4_hdmi_variant {
>
>         /* Callback to disable the PHY */
>         void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to enable the RNG in the PHY */
> +       void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to disable the RNG in the PHY */
> +       void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> @@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
>                        struct drm_display_mode *mode);
>  void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
> +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 5a1746877bb5..93287e24d7d1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -7,6 +7,7 @@
>   */
>
>  #include "vc4_hdmi.h"
> +#include "vc4_regs.h"
>  #include "vc4_hdmi_regs.h"
>
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> @@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
>  {
>         HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
>  }
> +
> +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_0) &
> +                  ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> +}
> +
> +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_0) |
> +                  VC4_HDMI_TX_PHY_RNG_PWRDN);
> +}
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / disable function
@ 2020-07-28 13:04       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Let's continue the implementation of hooks for the parts that change in the
> BCM2711 SoC with the PHY RNG setup.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c     | 15 +++++++++------
>  drivers/gpu/drm/vc4/vc4_hdmi.h     |  8 ++++++++
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 15 +++++++++++++++
>  3 files changed, 32 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 068041145d1c..19897d6525ac 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -762,9 +762,9 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>         switch (cmd) {
>         case SNDRV_PCM_TRIGGER_START:
>                 vc4_hdmi_set_audio_infoframe(encoder);
> -               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> -                          HDMI_READ(HDMI_TX_PHY_CTL_0) &
> -                          ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> +
> +               if (vc4_hdmi->variant->phy_rng_enable)
> +                       vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
>
>                 HDMI_WRITE(HDMI_MAI_CTL,
>                            VC4_SET_FIELD(vc4_hdmi->audio.channels,
> @@ -776,9 +776,10 @@ static int vc4_hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
>                            VC4_HD_MAI_CTL_DLATE |
>                            VC4_HD_MAI_CTL_ERRORE |
>                            VC4_HD_MAI_CTL_ERRORF);
> -               HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> -                          HDMI_READ(HDMI_TX_PHY_CTL_0) |
> -                          VC4_HDMI_TX_PHY_RNG_PWRDN);
> +
> +               if (vc4_hdmi->variant->phy_rng_disable)
> +                       vc4_hdmi->variant->phy_rng_disable(vc4_hdmi);
> +
>                 break;
>         default:
>                 break;
> @@ -1433,6 +1434,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .reset                  = vc4_hdmi_reset,
>         .phy_init               = vc4_hdmi_phy_init,
>         .phy_disable            = vc4_hdmi_phy_disable,
> +       .phy_rng_enable         = vc4_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc4_hdmi_phy_rng_disable,
>  };
>
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 32c80161c786..950accbc44e4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -47,6 +47,12 @@ struct vc4_hdmi_variant {
>
>         /* Callback to disable the PHY */
>         void (*phy_disable)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to enable the RNG in the PHY */
> +       void (*phy_rng_enable)(struct vc4_hdmi *vc4_hdmi);
> +
> +       /* Callback to disable the RNG in the PHY */
> +       void (*phy_rng_disable)(struct vc4_hdmi *vc4_hdmi);
>  };
>
>  /* HDMI audio information */
> @@ -107,5 +113,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder)
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
>                        struct drm_display_mode *mode);
>  void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
> +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 5a1746877bb5..93287e24d7d1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -7,6 +7,7 @@
>   */
>
>  #include "vc4_hdmi.h"
> +#include "vc4_regs.h"
>  #include "vc4_hdmi_regs.h"
>
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> @@ -23,3 +24,17 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi)
>  {
>         HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0xf << 16);
>  }
> +
> +void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_0) &
> +                  ~VC4_HDMI_TX_PHY_RNG_PWRDN);
> +}
> +
> +void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_0) |
> +                  VC4_HDMI_TX_PHY_RNG_PWRDN);
> +}
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:12       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Similarly to the previous patches, the CSC setup is slightly different in
> the BCM2711 than in the previous generations. Let's add a callback for it.

We've gained the set_timings callback in this patch as well as
csc_setup. Was that an accidental squash as we had them as independent
commits in v1.

  Dave

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 142 +++++++++++++++++++---------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |   7 ++-
>  2 files changed, 89 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 19897d6525ac..a50220bfd5dd 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -334,12 +334,44 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>                 DRM_ERROR("Failed to release power domain: %d\n", ret);
>  }
>
> -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> +{
> +       u32 csc_ctl;
> +
> +       csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
> +                               VC4_HD_CSC_CTL_ORDER);
> +
> +       if (enable) {
> +               /* CEA VICs other than #1 requre limited range RGB
> +                * output unless overridden by an AVI infoframe.
> +                * Apply a colorspace conversion to squash 0-255 down
> +                * to 16-235.  The matrix here is:
> +                *
> +                * [ 0      0      0.8594 16]
> +                * [ 0      0.8594 0      16]
> +                * [ 0.8594 0      0      16]
> +                * [ 0      0      0       1]
> +                */
> +               csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
> +               csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
> +               csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
> +                                        VC4_HD_CSC_CTL_MODE);
> +
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
> +       }
> +
> +       /* The RGB order applies even when CSC is disabled. */
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> +}
> +
> +static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
> +                                struct drm_display_mode *mode)
>  {
> -       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> -       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
> -       bool debug_dump_regs = false;
>         bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
>         bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>         bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> @@ -357,7 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                                         mode->crtc_vsync_end -
>                                         interlaced,
>                                         VC4_HDMI_VERTB_VBP));
> -       u32 csc_ctl;
> +
> +       HDMI_WRITE(HDMI_HORZA,
> +                  (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
> +                  (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
> +                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> +                                VC4_HDMI_HORZA_HAP));
> +
> +       HDMI_WRITE(HDMI_HORZB,
> +                  VC4_SET_FIELD((mode->htotal -
> +                                 mode->hsync_end) * pixel_rep,
> +                                VC4_HDMI_HORZB_HBP) |
> +                  VC4_SET_FIELD((mode->hsync_end -
> +                                 mode->hsync_start) * pixel_rep,
> +                                VC4_HDMI_HORZB_HSP) |
> +                  VC4_SET_FIELD((mode->hsync_start -
> +                                 mode->hdisplay) * pixel_rep,
> +                                VC4_HDMI_HORZB_HFP));
> +
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
> +
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
> +
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> +}
> +
> +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       bool debug_dump_regs = false;
>         int ret;
>
>         ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -401,68 +467,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
>                    VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
>
> -       HDMI_WRITE(HDMI_HORZA,
> -                  (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
> -                  (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
> -                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> -                                VC4_HDMI_HORZA_HAP));
> -
> -       HDMI_WRITE(HDMI_HORZB,
> -                  VC4_SET_FIELD((mode->htotal -
> -                                 mode->hsync_end) * pixel_rep,
> -                                VC4_HDMI_HORZB_HBP) |
> -                  VC4_SET_FIELD((mode->hsync_end -
> -                                 mode->hsync_start) * pixel_rep,
> -                                VC4_HDMI_HORZB_HSP) |
> -                  VC4_SET_FIELD((mode->hsync_start -
> -                                 mode->hdisplay) * pixel_rep,
> -                                VC4_HDMI_HORZB_HFP));
> -
> -       HDMI_WRITE(HDMI_VERTA0, verta);
> -       HDMI_WRITE(HDMI_VERTA1, verta);
> -
> -       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> -       HDMI_WRITE(HDMI_VERTB1, vertb);
> -
> -       HDMI_WRITE(HDMI_VID_CTL,
> -                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> -
> -       csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
> -                               VC4_HD_CSC_CTL_ORDER);
> +       if (vc4_hdmi->variant->set_timings)
> +               vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
>
>         if (vc4_encoder->hdmi_monitor &&
> -           drm_default_rgb_quant_range(mode) ==
> -           HDMI_QUANTIZATION_RANGE_LIMITED) {
> -               /* CEA VICs other than #1 requre limited range RGB
> -                * output unless overridden by an AVI infoframe.
> -                * Apply a colorspace conversion to squash 0-255 down
> -                * to 16-235.  The matrix here is:
> -                *
> -                * [ 0      0      0.8594 16]
> -                * [ 0      0.8594 0      16]
> -                * [ 0.8594 0      0      16]
> -                * [ 0      0      0       1]
> -                */
> -               csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
> -               csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
> -               csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
> -                                        VC4_HD_CSC_CTL_MODE);
> +           drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
> +               if (vc4_hdmi->variant->csc_setup)
> +                       vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
>
> -               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> -               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> -               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
>                 vc4_encoder->limited_rgb_range = true;
>         } else {
> +               if (vc4_hdmi->variant->csc_setup)
> +                       vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
> +
>                 vc4_encoder->limited_rgb_range = false;
>         }
>
> -       /* The RGB order applies even when CSC is disabled. */
> -       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> -
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
>         if (debug_dump_regs) {
> @@ -1431,7 +1451,9 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
>         .init_resources         = vc4_hdmi_init_resources,
> +       .csc_setup              = vc4_hdmi_csc_setup,
>         .reset                  = vc4_hdmi_reset,
> +       .set_timings            = vc4_hdmi_set_timings,
>         .phy_init               = vc4_hdmi_phy_init,
>         .phy_disable            = vc4_hdmi_phy_disable,
>         .phy_rng_enable         = vc4_hdmi_phy_rng_enable,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 950accbc44e4..0c32dc46d289 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -41,6 +41,13 @@ struct vc4_hdmi_variant {
>         /* Callback to reset the HDMI block */
>         void (*reset)(struct vc4_hdmi *vc4_hdmi);
>
> +       /* Callback to enable / disable the CSC */
> +       void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
> +
> +       /* Callback to configure the video timings in the HDMI block */
> +       void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
> +                           struct drm_display_mode *mode);
> +
>         /* Callback to initialize the PHY according to the mode */
>         void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
>                          struct drm_display_mode *mode);
> --
> git-series 0.9.1

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

* Re: [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback
@ 2020-07-28 13:12       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Similarly to the previous patches, the CSC setup is slightly different in
> the BCM2711 than in the previous generations. Let's add a callback for it.

We've gained the set_timings callback in this patch as well as
csc_setup. Was that an accidental squash as we had them as independent
commits in v1.

  Dave

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 142 +++++++++++++++++++---------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |   7 ++-
>  2 files changed, 89 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 19897d6525ac..a50220bfd5dd 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -334,12 +334,44 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>                 DRM_ERROR("Failed to release power domain: %d\n", ret);
>  }
>
> -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> +{
> +       u32 csc_ctl;
> +
> +       csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
> +                               VC4_HD_CSC_CTL_ORDER);
> +
> +       if (enable) {
> +               /* CEA VICs other than #1 requre limited range RGB
> +                * output unless overridden by an AVI infoframe.
> +                * Apply a colorspace conversion to squash 0-255 down
> +                * to 16-235.  The matrix here is:
> +                *
> +                * [ 0      0      0.8594 16]
> +                * [ 0      0.8594 0      16]
> +                * [ 0.8594 0      0      16]
> +                * [ 0      0      0       1]
> +                */
> +               csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
> +               csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
> +               csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
> +                                        VC4_HD_CSC_CTL_MODE);
> +
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
> +       }
> +
> +       /* The RGB order applies even when CSC is disabled. */
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> +}
> +
> +static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
> +                                struct drm_display_mode *mode)
>  {
> -       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> -       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
> -       bool debug_dump_regs = false;
>         bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
>         bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>         bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> @@ -357,7 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                                         mode->crtc_vsync_end -
>                                         interlaced,
>                                         VC4_HDMI_VERTB_VBP));
> -       u32 csc_ctl;
> +
> +       HDMI_WRITE(HDMI_HORZA,
> +                  (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
> +                  (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
> +                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> +                                VC4_HDMI_HORZA_HAP));
> +
> +       HDMI_WRITE(HDMI_HORZB,
> +                  VC4_SET_FIELD((mode->htotal -
> +                                 mode->hsync_end) * pixel_rep,
> +                                VC4_HDMI_HORZB_HBP) |
> +                  VC4_SET_FIELD((mode->hsync_end -
> +                                 mode->hsync_start) * pixel_rep,
> +                                VC4_HDMI_HORZB_HSP) |
> +                  VC4_SET_FIELD((mode->hsync_start -
> +                                 mode->hdisplay) * pixel_rep,
> +                                VC4_HDMI_HORZB_HFP));
> +
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
> +
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
> +
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> +}
> +
> +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       bool debug_dump_regs = false;
>         int ret;
>
>         ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -401,68 +467,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
>                    VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
>
> -       HDMI_WRITE(HDMI_HORZA,
> -                  (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
> -                  (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
> -                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> -                                VC4_HDMI_HORZA_HAP));
> -
> -       HDMI_WRITE(HDMI_HORZB,
> -                  VC4_SET_FIELD((mode->htotal -
> -                                 mode->hsync_end) * pixel_rep,
> -                                VC4_HDMI_HORZB_HBP) |
> -                  VC4_SET_FIELD((mode->hsync_end -
> -                                 mode->hsync_start) * pixel_rep,
> -                                VC4_HDMI_HORZB_HSP) |
> -                  VC4_SET_FIELD((mode->hsync_start -
> -                                 mode->hdisplay) * pixel_rep,
> -                                VC4_HDMI_HORZB_HFP));
> -
> -       HDMI_WRITE(HDMI_VERTA0, verta);
> -       HDMI_WRITE(HDMI_VERTA1, verta);
> -
> -       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> -       HDMI_WRITE(HDMI_VERTB1, vertb);
> -
> -       HDMI_WRITE(HDMI_VID_CTL,
> -                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> -
> -       csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
> -                               VC4_HD_CSC_CTL_ORDER);
> +       if (vc4_hdmi->variant->set_timings)
> +               vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
>
>         if (vc4_encoder->hdmi_monitor &&
> -           drm_default_rgb_quant_range(mode) ==
> -           HDMI_QUANTIZATION_RANGE_LIMITED) {
> -               /* CEA VICs other than #1 requre limited range RGB
> -                * output unless overridden by an AVI infoframe.
> -                * Apply a colorspace conversion to squash 0-255 down
> -                * to 16-235.  The matrix here is:
> -                *
> -                * [ 0      0      0.8594 16]
> -                * [ 0      0.8594 0      16]
> -                * [ 0.8594 0      0      16]
> -                * [ 0      0      0       1]
> -                */
> -               csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
> -               csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
> -               csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
> -                                        VC4_HD_CSC_CTL_MODE);
> +           drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
> +               if (vc4_hdmi->variant->csc_setup)
> +                       vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
>
> -               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> -               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> -               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
>                 vc4_encoder->limited_rgb_range = true;
>         } else {
> +               if (vc4_hdmi->variant->csc_setup)
> +                       vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
> +
>                 vc4_encoder->limited_rgb_range = false;
>         }
>
> -       /* The RGB order applies even when CSC is disabled. */
> -       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> -
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
>         if (debug_dump_regs) {
> @@ -1431,7 +1451,9 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
>         .init_resources         = vc4_hdmi_init_resources,
> +       .csc_setup              = vc4_hdmi_csc_setup,
>         .reset                  = vc4_hdmi_reset,
> +       .set_timings            = vc4_hdmi_set_timings,
>         .phy_init               = vc4_hdmi_phy_init,
>         .phy_disable            = vc4_hdmi_phy_disable,
>         .phy_rng_enable         = vc4_hdmi_phy_rng_enable,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 950accbc44e4..0c32dc46d289 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -41,6 +41,13 @@ struct vc4_hdmi_variant {
>         /* Callback to reset the HDMI block */
>         void (*reset)(struct vc4_hdmi *vc4_hdmi);
>
> +       /* Callback to enable / disable the CSC */
> +       void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
> +
> +       /* Callback to configure the video timings in the HDMI block */
> +       void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
> +                           struct drm_display_mode *mode);
> +
>         /* Callback to initialize the PHY according to the mode */
>         void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
>                          struct drm_display_mode *mode);
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback
@ 2020-07-28 13:12       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Similarly to the previous patches, the CSC setup is slightly different in
> the BCM2711 than in the previous generations. Let's add a callback for it.

We've gained the set_timings callback in this patch as well as
csc_setup. Was that an accidental squash as we had them as independent
commits in v1.

  Dave

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 142 +++++++++++++++++++---------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |   7 ++-
>  2 files changed, 89 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 19897d6525ac..a50220bfd5dd 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -334,12 +334,44 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>                 DRM_ERROR("Failed to release power domain: %d\n", ret);
>  }
>
> -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> +{
> +       u32 csc_ctl;
> +
> +       csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
> +                               VC4_HD_CSC_CTL_ORDER);
> +
> +       if (enable) {
> +               /* CEA VICs other than #1 requre limited range RGB
> +                * output unless overridden by an AVI infoframe.
> +                * Apply a colorspace conversion to squash 0-255 down
> +                * to 16-235.  The matrix here is:
> +                *
> +                * [ 0      0      0.8594 16]
> +                * [ 0      0.8594 0      16]
> +                * [ 0.8594 0      0      16]
> +                * [ 0      0      0       1]
> +                */
> +               csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
> +               csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
> +               csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
> +                                        VC4_HD_CSC_CTL_MODE);
> +
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
> +       }
> +
> +       /* The RGB order applies even when CSC is disabled. */
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> +}
> +
> +static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
> +                                struct drm_display_mode *mode)
>  {
> -       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> -       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       struct vc4_hdmi_encoder *vc4_encoder = &vc4_hdmi->encoder;
> -       bool debug_dump_regs = false;
>         bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
>         bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>         bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> @@ -357,7 +389,41 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                                         mode->crtc_vsync_end -
>                                         interlaced,
>                                         VC4_HDMI_VERTB_VBP));
> -       u32 csc_ctl;
> +
> +       HDMI_WRITE(HDMI_HORZA,
> +                  (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
> +                  (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
> +                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> +                                VC4_HDMI_HORZA_HAP));
> +
> +       HDMI_WRITE(HDMI_HORZB,
> +                  VC4_SET_FIELD((mode->htotal -
> +                                 mode->hsync_end) * pixel_rep,
> +                                VC4_HDMI_HORZB_HBP) |
> +                  VC4_SET_FIELD((mode->hsync_end -
> +                                 mode->hsync_start) * pixel_rep,
> +                                VC4_HDMI_HORZB_HSP) |
> +                  VC4_SET_FIELD((mode->hsync_start -
> +                                 mode->hdisplay) * pixel_rep,
> +                                VC4_HDMI_HORZB_HFP));
> +
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
> +
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
> +
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> +}
> +
> +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       bool debug_dump_regs = false;
>         int ret;
>
>         ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -401,68 +467,22 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
>                    VC4_HDMI_SCHEDULER_CONTROL_IGNORE_VSYNC_PREDICTS);
>
> -       HDMI_WRITE(HDMI_HORZA,
> -                  (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) |
> -                  (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) |
> -                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> -                                VC4_HDMI_HORZA_HAP));
> -
> -       HDMI_WRITE(HDMI_HORZB,
> -                  VC4_SET_FIELD((mode->htotal -
> -                                 mode->hsync_end) * pixel_rep,
> -                                VC4_HDMI_HORZB_HBP) |
> -                  VC4_SET_FIELD((mode->hsync_end -
> -                                 mode->hsync_start) * pixel_rep,
> -                                VC4_HDMI_HORZB_HSP) |
> -                  VC4_SET_FIELD((mode->hsync_start -
> -                                 mode->hdisplay) * pixel_rep,
> -                                VC4_HDMI_HORZB_HFP));
> -
> -       HDMI_WRITE(HDMI_VERTA0, verta);
> -       HDMI_WRITE(HDMI_VERTA1, verta);
> -
> -       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> -       HDMI_WRITE(HDMI_VERTB1, vertb);
> -
> -       HDMI_WRITE(HDMI_VID_CTL,
> -                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
> -
> -       csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR,
> -                               VC4_HD_CSC_CTL_ORDER);
> +       if (vc4_hdmi->variant->set_timings)
> +               vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
>
>         if (vc4_encoder->hdmi_monitor &&
> -           drm_default_rgb_quant_range(mode) ==
> -           HDMI_QUANTIZATION_RANGE_LIMITED) {
> -               /* CEA VICs other than #1 requre limited range RGB
> -                * output unless overridden by an AVI infoframe.
> -                * Apply a colorspace conversion to squash 0-255 down
> -                * to 16-235.  The matrix here is:
> -                *
> -                * [ 0      0      0.8594 16]
> -                * [ 0      0.8594 0      16]
> -                * [ 0.8594 0      0      16]
> -                * [ 0      0      0       1]
> -                */
> -               csc_ctl |= VC4_HD_CSC_CTL_ENABLE;
> -               csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC;
> -               csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
> -                                        VC4_HD_CSC_CTL_MODE);
> +           drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
> +               if (vc4_hdmi->variant->csc_setup)
> +                       vc4_hdmi->variant->csc_setup(vc4_hdmi, true);
>
> -               HDMI_WRITE(HDMI_CSC_12_11, (0x000 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_14_13, (0x100 << 16) | 0x6e0);
> -               HDMI_WRITE(HDMI_CSC_22_21, (0x6e0 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_24_23, (0x100 << 16) | 0x000);
> -               HDMI_WRITE(HDMI_CSC_32_31, (0x000 << 16) | 0x6e0);
> -               HDMI_WRITE(HDMI_CSC_34_33, (0x100 << 16) | 0x000);
>                 vc4_encoder->limited_rgb_range = true;
>         } else {
> +               if (vc4_hdmi->variant->csc_setup)
> +                       vc4_hdmi->variant->csc_setup(vc4_hdmi, false);
> +
>                 vc4_encoder->limited_rgb_range = false;
>         }
>
> -       /* The RGB order applies even when CSC is disabled. */
> -       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> -
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
>         if (debug_dump_regs) {
> @@ -1431,7 +1451,9 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
>         .init_resources         = vc4_hdmi_init_resources,
> +       .csc_setup              = vc4_hdmi_csc_setup,
>         .reset                  = vc4_hdmi_reset,
> +       .set_timings            = vc4_hdmi_set_timings,
>         .phy_init               = vc4_hdmi_phy_init,
>         .phy_disable            = vc4_hdmi_phy_disable,
>         .phy_rng_enable         = vc4_hdmi_phy_rng_enable,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 950accbc44e4..0c32dc46d289 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -41,6 +41,13 @@ struct vc4_hdmi_variant {
>         /* Callback to reset the HDMI block */
>         void (*reset)(struct vc4_hdmi *vc4_hdmi);
>
> +       /* Callback to enable / disable the CSC */
> +       void (*csc_setup)(struct vc4_hdmi *vc4_hdmi, bool enable);
> +
> +       /* Callback to configure the video timings in the HDMI block */
> +       void (*set_timings)(struct vc4_hdmi *vc4_hdmi,
> +                           struct drm_display_mode *mode);
> +
>         /* Callback to initialize the PHY according to the mode */
>         void (*phy_init)(struct vc4_hdmi *vc4_hdmi,
>                          struct drm_display_mode *mode);
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:18       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:18 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4 CRTC will use the encoder type to control its output clock
> muxing. However, this will be different from HDMI0 to HDMI1, so let's
> store our type in the variant structure so that we can support multiple
> controllers later on.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a50220bfd5dd..c50241170d7e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1268,7 +1268,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
> -       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> +       vc4_hdmi->encoder.base.type = variant->encoder_type;
>         vc4_hdmi->pdev = pdev;
>         vc4_hdmi->variant = variant;
>
> @@ -1447,6 +1447,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  }
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0c32dc46d289..0d529db4b3ab 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -27,6 +27,9 @@ struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
>  struct vc4_hdmi_variant {
> +       /* Encoder Type for that controller */
> +       enum vc4_encoder_type encoder_type;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure
@ 2020-07-28 13:18       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:18 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4 CRTC will use the encoder type to control its output clock
> muxing. However, this will be different from HDMI0 to HDMI1, so let's
> store our type in the variant structure so that we can support multiple
> controllers later on.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a50220bfd5dd..c50241170d7e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1268,7 +1268,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
> -       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> +       vc4_hdmi->encoder.base.type = variant->encoder_type;
>         vc4_hdmi->pdev = pdev;
>         vc4_hdmi->variant = variant;
>
> @@ -1447,6 +1447,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  }
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0c32dc46d289..0d529db4b3ab 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -27,6 +27,9 @@ struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
>  struct vc4_hdmi_variant {
> +       /* Encoder Type for that controller */
> +       enum vc4_encoder_type encoder_type;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure
@ 2020-07-28 13:18       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:18 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4 CRTC will use the encoder type to control its output clock
> muxing. However, this will be different from HDMI0 to HDMI1, so let's
> store our type in the variant structure so that we can support multiple
> controllers later on.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a50220bfd5dd..c50241170d7e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1268,7 +1268,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
> -       vc4_hdmi->encoder.base.type = VC4_ENCODER_TYPE_HDMI0;
> +       vc4_hdmi->encoder.base.type = variant->encoder_type;
>         vc4_hdmi->pdev = pdev;
>         vc4_hdmi->variant = variant;
>
> @@ -1447,6 +1447,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  }
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0c32dc46d289..0d529db4b3ab 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -27,6 +27,9 @@ struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
>  struct vc4_hdmi_variant {
> +       /* Encoder Type for that controller */
> +       enum vc4_encoder_type encoder_type;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:20       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:20 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI driver was registering a single debugfs file so far with the name
> hdmi_regs.
>
> Obviously, this is not going to work anymore when will have multiple HDMI
> controllers since we will end up trying to register two files with the same
> name.
>
> Let's use the variant to avoid that name conflict.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index c50241170d7e..ef51eedaf75a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1370,7 +1370,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret)
>                 goto err_destroy_encoder;
>
> -       vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
> +       vc4_debugfs_add_file(drm, variant->debugfs_name,
> +                            vc4_hdmi_debugfs_regs,
> +                            vc4_hdmi);
>
>         return 0;
>
> @@ -1448,6 +1450,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
> +       .debugfs_name           = "hdmi_regs",
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0d529db4b3ab..794216f3228d 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
>
> +       /* Filename to expose the registers in debugfs */
> +       const char *debugfs_name;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files
@ 2020-07-28 13:20       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:20 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI driver was registering a single debugfs file so far with the name
> hdmi_regs.
>
> Obviously, this is not going to work anymore when will have multiple HDMI
> controllers since we will end up trying to register two files with the same
> name.
>
> Let's use the variant to avoid that name conflict.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index c50241170d7e..ef51eedaf75a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1370,7 +1370,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret)
>                 goto err_destroy_encoder;
>
> -       vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
> +       vc4_debugfs_add_file(drm, variant->debugfs_name,
> +                            vc4_hdmi_debugfs_regs,
> +                            vc4_hdmi);
>
>         return 0;
>
> @@ -1448,6 +1450,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
> +       .debugfs_name           = "hdmi_regs",
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0d529db4b3ab..794216f3228d 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
>
> +       /* Filename to expose the registers in debugfs */
> +       const char *debugfs_name;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files
@ 2020-07-28 13:20       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:20 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI driver was registering a single debugfs file so far with the name
> hdmi_regs.
>
> Obviously, this is not going to work anymore when will have multiple HDMI
> controllers since we will end up trying to register two files with the same
> name.
>
> Let's use the variant to avoid that name conflict.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index c50241170d7e..ef51eedaf75a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1370,7 +1370,9 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret)
>                 goto err_destroy_encoder;
>
> -       vc4_debugfs_add_file(drm, "hdmi_regs", vc4_hdmi_debugfs_regs, vc4_hdmi);
> +       vc4_debugfs_add_file(drm, variant->debugfs_name,
> +                            vc4_hdmi_debugfs_regs,
> +                            vc4_hdmi);
>
>         return 0;
>
> @@ -1448,6 +1450,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
> +       .debugfs_name           = "hdmi_regs",
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 0d529db4b3ab..794216f3228d 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
>
> +       /* Filename to expose the registers in debugfs */
> +       const char *debugfs_name;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:23       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:23 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The CEC init code was put directly into the bind function, which was quite
> inconsistent with how the audio support was done, and would prevent us from
> further changes to skip that initialisation entirely.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 108 +++++++++++++++++++++-------------
>  1 file changed, 67 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ef51eedaf75a..8cd08b541c14 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1171,6 +1171,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>         .adap_log_addr = vc4_hdmi_cec_adap_log_addr,
>         .adap_transmit = vc4_hdmi_cec_adap_transmit,
>  };
> +
> +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
> +{
> +       struct cec_connector_info conn_info;
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       u32 value;
> +       int ret;
> +
> +       vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
> +                                                 vc4_hdmi, "vc4",
> +                                                 CEC_CAP_DEFAULTS |
> +                                                 CEC_CAP_CONNECTOR_INFO, 1);
> +       ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
> +       if (ret < 0)
> +               return ret;
> +
> +       cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
> +       cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
> +
> +       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> +       value = HDMI_READ(HDMI_CEC_CNTRL_1);
> +       value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
> +       /*
> +        * Set the logical address to Unregistered and set the clock
> +        * divider: the hsm_clock rate and this divider setting will
> +        * give a 40 kHz CEC clock.
> +        */
> +       value |= VC4_HDMI_CEC_ADDR_MASK |
> +                (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
> +       ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
> +                                       vc4_cec_irq_handler,
> +                                       vc4_cec_irq_handler_thread, 0,
> +                                       "vc4 hdmi cec", vc4_hdmi);
> +       if (ret)
> +               goto err_delete_cec_adap;
> +
> +       ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
> +       if (ret < 0)
> +               goto err_delete_cec_adap;
> +
> +       return 0;
> +
> +err_delete_cec_adap:
> +       cec_delete_adapter(vc4_hdmi->cec_adap);
> +
> +       return ret;
> +}
> +
> +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
> +{
> +       cec_unregister_adapter(vc4_hdmi->cec_adap);
> +}
> +#else
> +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
> +{
> +       return 0;
> +}
> +
> +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
> +
>  #endif
>
>  static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
> @@ -1250,9 +1311,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>
>  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  {
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       struct cec_connector_info conn_info;
> -#endif
>         const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
>         struct platform_device *pdev = to_platform_device(dev);
>         struct drm_device *drm = dev_get_drvdata(master);
> @@ -1332,43 +1390,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret)
>                 goto err_destroy_encoder;
>
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
> -                                                 vc4_hdmi, "vc4",
> -                                                 CEC_CAP_DEFAULTS |
> -                                                 CEC_CAP_CONNECTOR_INFO, 1);
> -       ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
> -       if (ret < 0)
> -               goto err_destroy_conn;
> -
> -       cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
> -       cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
> -
> -       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> -       value = HDMI_READ(HDMI_CEC_CNTRL_1);
> -       value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
> -       /*
> -        * Set the logical address to Unregistered and set the clock
> -        * divider: the hsm_clock rate and this divider setting will
> -        * give a 40 kHz CEC clock.
> -        */
> -       value |= VC4_HDMI_CEC_ADDR_MASK |
> -                (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> -       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
> -       ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
> -                                       vc4_cec_irq_handler,
> -                                       vc4_cec_irq_handler_thread, 0,
> -                                       "vc4 hdmi cec", vc4_hdmi);
> +       ret = vc4_hdmi_cec_init(vc4_hdmi);
>         if (ret)
> -               goto err_delete_cec_adap;
> -       ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
> -       if (ret < 0)
> -               goto err_delete_cec_adap;
> -#endif
> +               goto err_destroy_conn;
>
>         ret = vc4_hdmi_audio_init(vc4_hdmi);
>         if (ret)
> -               goto err_destroy_encoder;
> +               goto err_free_cec;
>
>         vc4_debugfs_add_file(drm, variant->debugfs_name,
>                              vc4_hdmi_debugfs_regs,
> @@ -1376,12 +1404,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         return 0;
>
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -err_delete_cec_adap:
> -       cec_delete_adapter(vc4_hdmi->cec_adap);
> +err_free_cec:
> +       vc4_hdmi_cec_exit(vc4_hdmi);
>  err_destroy_conn:
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
> -#endif
>  err_destroy_encoder:
>         drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> @@ -1422,7 +1448,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         kfree(vc4_hdmi->hdmi_regset.regs);
>         kfree(vc4_hdmi->hd_regset.regs);
>
> -       cec_unregister_adapter(vc4_hdmi->cec_adap);
> +       vc4_hdmi_cec_exit(vc4_hdmi);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function
@ 2020-07-28 13:23       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:23 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The CEC init code was put directly into the bind function, which was quite
> inconsistent with how the audio support was done, and would prevent us from
> further changes to skip that initialisation entirely.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 108 +++++++++++++++++++++-------------
>  1 file changed, 67 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ef51eedaf75a..8cd08b541c14 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1171,6 +1171,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>         .adap_log_addr = vc4_hdmi_cec_adap_log_addr,
>         .adap_transmit = vc4_hdmi_cec_adap_transmit,
>  };
> +
> +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
> +{
> +       struct cec_connector_info conn_info;
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       u32 value;
> +       int ret;
> +
> +       vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
> +                                                 vc4_hdmi, "vc4",
> +                                                 CEC_CAP_DEFAULTS |
> +                                                 CEC_CAP_CONNECTOR_INFO, 1);
> +       ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
> +       if (ret < 0)
> +               return ret;
> +
> +       cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
> +       cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
> +
> +       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> +       value = HDMI_READ(HDMI_CEC_CNTRL_1);
> +       value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
> +       /*
> +        * Set the logical address to Unregistered and set the clock
> +        * divider: the hsm_clock rate and this divider setting will
> +        * give a 40 kHz CEC clock.
> +        */
> +       value |= VC4_HDMI_CEC_ADDR_MASK |
> +                (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
> +       ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
> +                                       vc4_cec_irq_handler,
> +                                       vc4_cec_irq_handler_thread, 0,
> +                                       "vc4 hdmi cec", vc4_hdmi);
> +       if (ret)
> +               goto err_delete_cec_adap;
> +
> +       ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
> +       if (ret < 0)
> +               goto err_delete_cec_adap;
> +
> +       return 0;
> +
> +err_delete_cec_adap:
> +       cec_delete_adapter(vc4_hdmi->cec_adap);
> +
> +       return ret;
> +}
> +
> +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
> +{
> +       cec_unregister_adapter(vc4_hdmi->cec_adap);
> +}
> +#else
> +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
> +{
> +       return 0;
> +}
> +
> +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
> +
>  #endif
>
>  static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
> @@ -1250,9 +1311,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>
>  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  {
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       struct cec_connector_info conn_info;
> -#endif
>         const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
>         struct platform_device *pdev = to_platform_device(dev);
>         struct drm_device *drm = dev_get_drvdata(master);
> @@ -1332,43 +1390,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret)
>                 goto err_destroy_encoder;
>
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
> -                                                 vc4_hdmi, "vc4",
> -                                                 CEC_CAP_DEFAULTS |
> -                                                 CEC_CAP_CONNECTOR_INFO, 1);
> -       ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
> -       if (ret < 0)
> -               goto err_destroy_conn;
> -
> -       cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
> -       cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
> -
> -       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> -       value = HDMI_READ(HDMI_CEC_CNTRL_1);
> -       value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
> -       /*
> -        * Set the logical address to Unregistered and set the clock
> -        * divider: the hsm_clock rate and this divider setting will
> -        * give a 40 kHz CEC clock.
> -        */
> -       value |= VC4_HDMI_CEC_ADDR_MASK |
> -                (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> -       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
> -       ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
> -                                       vc4_cec_irq_handler,
> -                                       vc4_cec_irq_handler_thread, 0,
> -                                       "vc4 hdmi cec", vc4_hdmi);
> +       ret = vc4_hdmi_cec_init(vc4_hdmi);
>         if (ret)
> -               goto err_delete_cec_adap;
> -       ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
> -       if (ret < 0)
> -               goto err_delete_cec_adap;
> -#endif
> +               goto err_destroy_conn;
>
>         ret = vc4_hdmi_audio_init(vc4_hdmi);
>         if (ret)
> -               goto err_destroy_encoder;
> +               goto err_free_cec;
>
>         vc4_debugfs_add_file(drm, variant->debugfs_name,
>                              vc4_hdmi_debugfs_regs,
> @@ -1376,12 +1404,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         return 0;
>
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -err_delete_cec_adap:
> -       cec_delete_adapter(vc4_hdmi->cec_adap);
> +err_free_cec:
> +       vc4_hdmi_cec_exit(vc4_hdmi);
>  err_destroy_conn:
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
> -#endif
>  err_destroy_encoder:
>         drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> @@ -1422,7 +1448,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         kfree(vc4_hdmi->hdmi_regset.regs);
>         kfree(vc4_hdmi->hd_regset.regs);
>
> -       cec_unregister_adapter(vc4_hdmi->cec_adap);
> +       vc4_hdmi_cec_exit(vc4_hdmi);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function
@ 2020-07-28 13:23       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:23 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The CEC init code was put directly into the bind function, which was quite
> inconsistent with how the audio support was done, and would prevent us from
> further changes to skip that initialisation entirely.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 108 +++++++++++++++++++++-------------
>  1 file changed, 67 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ef51eedaf75a..8cd08b541c14 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1171,6 +1171,67 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
>         .adap_log_addr = vc4_hdmi_cec_adap_log_addr,
>         .adap_transmit = vc4_hdmi_cec_adap_transmit,
>  };
> +
> +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
> +{
> +       struct cec_connector_info conn_info;
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       u32 value;
> +       int ret;
> +
> +       vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
> +                                                 vc4_hdmi, "vc4",
> +                                                 CEC_CAP_DEFAULTS |
> +                                                 CEC_CAP_CONNECTOR_INFO, 1);
> +       ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
> +       if (ret < 0)
> +               return ret;
> +
> +       cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
> +       cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
> +
> +       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> +       value = HDMI_READ(HDMI_CEC_CNTRL_1);
> +       value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
> +       /*
> +        * Set the logical address to Unregistered and set the clock
> +        * divider: the hsm_clock rate and this divider setting will
> +        * give a 40 kHz CEC clock.
> +        */
> +       value |= VC4_HDMI_CEC_ADDR_MASK |
> +                (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> +       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
> +       ret = devm_request_threaded_irq(&pdev->dev, platform_get_irq(pdev, 0),
> +                                       vc4_cec_irq_handler,
> +                                       vc4_cec_irq_handler_thread, 0,
> +                                       "vc4 hdmi cec", vc4_hdmi);
> +       if (ret)
> +               goto err_delete_cec_adap;
> +
> +       ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
> +       if (ret < 0)
> +               goto err_delete_cec_adap;
> +
> +       return 0;
> +
> +err_delete_cec_adap:
> +       cec_delete_adapter(vc4_hdmi->cec_adap);
> +
> +       return ret;
> +}
> +
> +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
> +{
> +       cec_unregister_adapter(vc4_hdmi->cec_adap);
> +}
> +#else
> +static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
> +{
> +       return 0;
> +}
> +
> +static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
> +
>  #endif
>
>  static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
> @@ -1250,9 +1311,6 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>
>  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  {
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       struct cec_connector_info conn_info;
> -#endif
>         const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
>         struct platform_device *pdev = to_platform_device(dev);
>         struct drm_device *drm = dev_get_drvdata(master);
> @@ -1332,43 +1390,13 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         if (ret)
>                 goto err_destroy_encoder;
>
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -       vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
> -                                                 vc4_hdmi, "vc4",
> -                                                 CEC_CAP_DEFAULTS |
> -                                                 CEC_CAP_CONNECTOR_INFO, 1);
> -       ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
> -       if (ret < 0)
> -               goto err_destroy_conn;
> -
> -       cec_fill_conn_info_from_drm(&conn_info, &vc4_hdmi->connector);
> -       cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
> -
> -       HDMI_WRITE(HDMI_CEC_CPU_MASK_SET, 0xffffffff);
> -       value = HDMI_READ(HDMI_CEC_CNTRL_1);
> -       value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
> -       /*
> -        * Set the logical address to Unregistered and set the clock
> -        * divider: the hsm_clock rate and this divider setting will
> -        * give a 40 kHz CEC clock.
> -        */
> -       value |= VC4_HDMI_CEC_ADDR_MASK |
> -                (4091 << VC4_HDMI_CEC_DIV_CLK_CNT_SHIFT);
> -       HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
> -       ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
> -                                       vc4_cec_irq_handler,
> -                                       vc4_cec_irq_handler_thread, 0,
> -                                       "vc4 hdmi cec", vc4_hdmi);
> +       ret = vc4_hdmi_cec_init(vc4_hdmi);
>         if (ret)
> -               goto err_delete_cec_adap;
> -       ret = cec_register_adapter(vc4_hdmi->cec_adap, dev);
> -       if (ret < 0)
> -               goto err_delete_cec_adap;
> -#endif
> +               goto err_destroy_conn;
>
>         ret = vc4_hdmi_audio_init(vc4_hdmi);
>         if (ret)
> -               goto err_destroy_encoder;
> +               goto err_free_cec;
>
>         vc4_debugfs_add_file(drm, variant->debugfs_name,
>                              vc4_hdmi_debugfs_regs,
> @@ -1376,12 +1404,10 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>
>         return 0;
>
> -#ifdef CONFIG_DRM_VC4_HDMI_CEC
> -err_delete_cec_adap:
> -       cec_delete_adapter(vc4_hdmi->cec_adap);
> +err_free_cec:
> +       vc4_hdmi_cec_exit(vc4_hdmi);
>  err_destroy_conn:
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
> -#endif
>  err_destroy_encoder:
>         drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> @@ -1422,7 +1448,7 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         kfree(vc4_hdmi->hdmi_regset.regs);
>         kfree(vc4_hdmi->hd_regset.regs);
>
> -       cec_unregister_adapter(vc4_hdmi->cec_adap);
> +       vc4_hdmi_cec_exit(vc4_hdmi);
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:25       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Similarly to the audio support, CEC support is not there yet for the
> BCM2711, so let's skip entirely the CEC initialization through a variant
> flag.

CEC is sorted now, but it's easier & cleaner to keep this patch and
add a new patchset that enables CEC at a later date.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 8cd08b541c14..86e21de6c578 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1179,6 +1179,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
>         u32 value;
>         int ret;
>
> +       if (!vc4_hdmi->variant->cec_available)
> +               return 0;
> +
>         vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                                   vc4_hdmi, "vc4",
>                                                   CEC_CAP_DEFAULTS |
> @@ -1477,6 +1480,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 794216f3228d..3f07aebe89f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -33,6 +33,9 @@ struct vc4_hdmi_variant {
>         /* Filename to expose the registers in debugfs */
>         const char *debugfs_name;
>
> +       /* Set to true when the CEC support is available */
> +       bool cec_available;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag
@ 2020-07-28 13:25       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Similarly to the audio support, CEC support is not there yet for the
> BCM2711, so let's skip entirely the CEC initialization through a variant
> flag.

CEC is sorted now, but it's easier & cleaner to keep this patch and
add a new patchset that enables CEC at a later date.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 8cd08b541c14..86e21de6c578 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1179,6 +1179,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
>         u32 value;
>         int ret;
>
> +       if (!vc4_hdmi->variant->cec_available)
> +               return 0;
> +
>         vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                                   vc4_hdmi, "vc4",
>                                                   CEC_CAP_DEFAULTS |
> @@ -1477,6 +1480,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 794216f3228d..3f07aebe89f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -33,6 +33,9 @@ struct vc4_hdmi_variant {
>         /* Filename to expose the registers in debugfs */
>         const char *debugfs_name;
>
> +       /* Set to true when the CEC support is available */
> +       bool cec_available;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag
@ 2020-07-28 13:25       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:25 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Similarly to the audio support, CEC support is not there yet for the
> BCM2711, so let's skip entirely the CEC initialization through a variant
> flag.

CEC is sorted now, but it's easier & cleaner to keep this patch and
add a new patchset that enables CEC at a later date.

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 4 ++++
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 7 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 8cd08b541c14..86e21de6c578 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1179,6 +1179,9 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
>         u32 value;
>         int ret;
>
> +       if (!vc4_hdmi->variant->cec_available)
> +               return 0;
> +
>         vc4_hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
>                                                   vc4_hdmi, "vc4",
>                                                   CEC_CAP_DEFAULTS |
> @@ -1477,6 +1480,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 794216f3228d..3f07aebe89f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -33,6 +33,9 @@ struct vc4_hdmi_variant {
>         /* Filename to expose the registers in debugfs */
>         const char *debugfs_name;
>
> +       /* Set to true when the CEC support is available */
> +       bool cec_available;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 13:26       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:26 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove
> it.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 86e21de6c578..a01562a49bf0 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -55,7 +55,6 @@
>
>  #define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
> -#define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>  {
> --
> git-series 0.9.1

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

* Re: [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
@ 2020-07-28 13:26       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:26 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove
> it.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 86e21de6c578..a01562a49bf0 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -55,7 +55,6 @@
>
>  #define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
> -#define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>  {
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
@ 2020-07-28 13:26       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 13:26 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The CEC_CLOCK_DIV define is not used anywhere in the driver, let's remove
> it.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 86e21de6c578..a01562a49bf0 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -55,7 +55,6 @@
>
>  #define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
> -#define CEC_CLOCK_DIV  (HSM_CLOCK_FREQ / CEC_CLOCK_FREQ)
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>  {
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 14:45       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The mode_valid hook on the encoder uses a pointer to a drm_encoder called
> crtc, which is pretty confusing. Let's rename it to encoder to make it
> clear what it is.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a01562a49bf0..17797b14cde4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  }
>
>  static enum drm_mode_status
> -vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
> +vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
>  {
>         /*
> --
> git-series 0.9.1

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

* Re: [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
@ 2020-07-28 14:45       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The mode_valid hook on the encoder uses a pointer to a drm_encoder called
> crtc, which is pretty confusing. Let's rename it to encoder to make it
> clear what it is.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a01562a49bf0..17797b14cde4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  }
>
>  static enum drm_mode_status
> -vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
> +vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
>  {
>         /*
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
@ 2020-07-28 14:45       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The mode_valid hook on the encoder uses a pointer to a drm_encoder called
> crtc, which is pretty confusing. Let's rename it to encoder to make it
> clear what it is.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index a01562a49bf0..17797b14cde4 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -556,7 +556,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  }
>
>  static enum drm_mode_status
> -vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
> +vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
>  {
>         /*
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 14:56       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:56 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HSM clock needs to be setup at around 101% of the pixel rate. This
> was done previously by setting the clock rate to 163.7MHz at probe time and
> only check in mode_valid whether the mode pixel clock was under the pixel
> clock +1% or not.
>
> However, with 4k we need to change that frequency to a higher frequency
> than 163.7MHz, and yet want to have the lowest clock as possible to have a
> decent power saving.
>
> Let's change that logic a bit by setting the clock rate of the HSM clock
> to the pixel rate at encoder_enable time. This would work for the
> BCM2711 that support 4k resolutions and has a clock that can provide it,
> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> that wouldn't be able to use those modes, so let's define the limit in
> the variant.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>  2 files changed, 41 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 17797b14cde4..9f30fab744f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -53,7 +53,6 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
> -#define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
> +       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
>         ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         bool debug_dump_regs = false;
> +       unsigned long pixel_rate, hsm_rate;
>         int ret;
>
>         ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       ret = clk_set_rate(vc4_hdmi->pixel_clock,
> -                          mode->clock * 1000 *
> -                          ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> +       pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> +       ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>         if (ret) {
>                 DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>                 return;
> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> +       /*
> +        * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> +        * be faster than pixel clock, infinitesimally faster, tested in
> +        * simulation. Otherwise, exact value is unimportant for HDMI
> +        * operation." This conflicts with bcm2835's vc4 documentation, which
> +        * states HSM's clock has to be at least 108% of the pixel clock.
> +        *
> +        * Real life tests reveal that vc4's firmware statement holds up, and
> +        * users are able to use pixel clocks closer to HSM's, namely for
> +        * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> +        * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> +        * 162MHz.
> +        *
> +        * Additionally, the AXI clock needs to be at least 25% of
> +        * pixel clock, but HSM ends up being the limiting factor.
> +        */
> +       hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> +       ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +       if (ret) {
> +               DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> +               return;
> +       }
> +
> +       ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> +       if (ret) {
> +               DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> +               clk_disable_unprepare(vc4_hdmi->pixel_clock);
> +               return;
> +       }
> +
>         if (vc4_hdmi->variant->reset)
>                 vc4_hdmi->variant->reset(vc4_hdmi);
>
> @@ -559,23 +589,9 @@ static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
>  {
> -       /*
> -        * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> -        * be faster than pixel clock, infinitesimally faster, tested in
> -        * simulation. Otherwise, exact value is unimportant for HDMI
> -        * operation." This conflicts with bcm2835's vc4 documentation, which
> -        * states HSM's clock has to be at least 108% of the pixel clock.
> -        *
> -        * Real life tests reveal that vc4's firmware statement holds up, and
> -        * users are able to use pixel clocks closer to HSM's, namely for
> -        * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> -        * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> -        * 162MHz.
> -        *
> -        * Additionally, the AXI clock needs to be at least 25% of
> -        * pixel clock, but HSM ends up being the limiting factor.
> -        */
> -       if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +
> +       if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
>                 return MODE_CLOCK_HIGH;
>
>         return MODE_OK;
> @@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                 return -EPROBE_DEFER;
>         }
>
> -       /* This is the rate that is set by the firmware.  The number
> -        * needs to be a bit higher than the pixel clock rate
> -        * (generally 148.5Mhz).
> -        */
> -       ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
> -       if (ret) {
> -               DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> -               goto err_put_i2c;
> -       }
> -
> -       ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> -       if (ret) {
> -               DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
> -                         ret);
> -               goto err_put_i2c;
> -       }
> -
>         /* Only use the GPIO HPD pin if present in the DT, otherwise
>          * we'll use the HDMI core's register.
>          */
> @@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_destroy_encoder:
>         drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> -       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> -err_put_i2c:
>         put_device(&vc4_hdmi->ddc->dev);
>
>         return ret;
> @@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>
> -       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         pm_runtime_disable(dev);
>
>         put_device(&vc4_hdmi->ddc->dev);
> @@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .max_pixel_clock        = 162000000,
>         .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 3f07aebe89f1..342f6e0227a2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
>         /* Set to true when the CEC support is available */
>         bool cec_available;
>
> +       /* Maximum pixel clock supported by the controller (in Hz) */
> +       unsigned long long max_pixel_clock;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-07-28 14:56       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:56 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HSM clock needs to be setup at around 101% of the pixel rate. This
> was done previously by setting the clock rate to 163.7MHz at probe time and
> only check in mode_valid whether the mode pixel clock was under the pixel
> clock +1% or not.
>
> However, with 4k we need to change that frequency to a higher frequency
> than 163.7MHz, and yet want to have the lowest clock as possible to have a
> decent power saving.
>
> Let's change that logic a bit by setting the clock rate of the HSM clock
> to the pixel rate at encoder_enable time. This would work for the
> BCM2711 that support 4k resolutions and has a clock that can provide it,
> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> that wouldn't be able to use those modes, so let's define the limit in
> the variant.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>  2 files changed, 41 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 17797b14cde4..9f30fab744f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -53,7 +53,6 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
> -#define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
> +       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
>         ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         bool debug_dump_regs = false;
> +       unsigned long pixel_rate, hsm_rate;
>         int ret;
>
>         ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       ret = clk_set_rate(vc4_hdmi->pixel_clock,
> -                          mode->clock * 1000 *
> -                          ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> +       pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> +       ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>         if (ret) {
>                 DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>                 return;
> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> +       /*
> +        * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> +        * be faster than pixel clock, infinitesimally faster, tested in
> +        * simulation. Otherwise, exact value is unimportant for HDMI
> +        * operation." This conflicts with bcm2835's vc4 documentation, which
> +        * states HSM's clock has to be at least 108% of the pixel clock.
> +        *
> +        * Real life tests reveal that vc4's firmware statement holds up, and
> +        * users are able to use pixel clocks closer to HSM's, namely for
> +        * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> +        * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> +        * 162MHz.
> +        *
> +        * Additionally, the AXI clock needs to be at least 25% of
> +        * pixel clock, but HSM ends up being the limiting factor.
> +        */
> +       hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> +       ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +       if (ret) {
> +               DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> +               return;
> +       }
> +
> +       ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> +       if (ret) {
> +               DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> +               clk_disable_unprepare(vc4_hdmi->pixel_clock);
> +               return;
> +       }
> +
>         if (vc4_hdmi->variant->reset)
>                 vc4_hdmi->variant->reset(vc4_hdmi);
>
> @@ -559,23 +589,9 @@ static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
>  {
> -       /*
> -        * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> -        * be faster than pixel clock, infinitesimally faster, tested in
> -        * simulation. Otherwise, exact value is unimportant for HDMI
> -        * operation." This conflicts with bcm2835's vc4 documentation, which
> -        * states HSM's clock has to be at least 108% of the pixel clock.
> -        *
> -        * Real life tests reveal that vc4's firmware statement holds up, and
> -        * users are able to use pixel clocks closer to HSM's, namely for
> -        * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> -        * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> -        * 162MHz.
> -        *
> -        * Additionally, the AXI clock needs to be at least 25% of
> -        * pixel clock, but HSM ends up being the limiting factor.
> -        */
> -       if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +
> +       if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
>                 return MODE_CLOCK_HIGH;
>
>         return MODE_OK;
> @@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                 return -EPROBE_DEFER;
>         }
>
> -       /* This is the rate that is set by the firmware.  The number
> -        * needs to be a bit higher than the pixel clock rate
> -        * (generally 148.5Mhz).
> -        */
> -       ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
> -       if (ret) {
> -               DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> -               goto err_put_i2c;
> -       }
> -
> -       ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> -       if (ret) {
> -               DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
> -                         ret);
> -               goto err_put_i2c;
> -       }
> -
>         /* Only use the GPIO HPD pin if present in the DT, otherwise
>          * we'll use the HDMI core's register.
>          */
> @@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_destroy_encoder:
>         drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> -       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> -err_put_i2c:
>         put_device(&vc4_hdmi->ddc->dev);
>
>         return ret;
> @@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>
> -       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         pm_runtime_disable(dev);
>
>         put_device(&vc4_hdmi->ddc->dev);
> @@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .max_pixel_clock        = 162000000,
>         .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 3f07aebe89f1..342f6e0227a2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
>         /* Set to true when the CEC support is available */
>         bool cec_available;
>
> +       /* Maximum pixel clock supported by the controller (in Hz) */
> +       unsigned long long max_pixel_clock;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-07-28 14:56       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:56 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HSM clock needs to be setup at around 101% of the pixel rate. This
> was done previously by setting the clock rate to 163.7MHz at probe time and
> only check in mode_valid whether the mode pixel clock was under the pixel
> clock +1% or not.
>
> However, with 4k we need to change that frequency to a higher frequency
> than 163.7MHz, and yet want to have the lowest clock as possible to have a
> decent power saving.
>
> Let's change that logic a bit by setting the clock rate of the HSM clock
> to the pixel rate at encoder_enable time. This would work for the
> BCM2711 that support 4k resolutions and has a clock that can provide it,
> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> that wouldn't be able to use those modes, so let's define the limit in
> the variant.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>  2 files changed, 41 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 17797b14cde4..9f30fab744f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -53,7 +53,6 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
> -#define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>
> +       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         clk_disable_unprepare(vc4_hdmi->pixel_clock);
>
>         ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         bool debug_dump_regs = false;
> +       unsigned long pixel_rate, hsm_rate;
>         int ret;
>
>         ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> -       ret = clk_set_rate(vc4_hdmi->pixel_clock,
> -                          mode->clock * 1000 *
> -                          ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> +       pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> +       ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>         if (ret) {
>                 DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>                 return;
> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                 return;
>         }
>
> +       /*
> +        * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> +        * be faster than pixel clock, infinitesimally faster, tested in
> +        * simulation. Otherwise, exact value is unimportant for HDMI
> +        * operation." This conflicts with bcm2835's vc4 documentation, which
> +        * states HSM's clock has to be at least 108% of the pixel clock.
> +        *
> +        * Real life tests reveal that vc4's firmware statement holds up, and
> +        * users are able to use pixel clocks closer to HSM's, namely for
> +        * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> +        * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> +        * 162MHz.
> +        *
> +        * Additionally, the AXI clock needs to be at least 25% of
> +        * pixel clock, but HSM ends up being the limiting factor.
> +        */
> +       hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> +       ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +       if (ret) {
> +               DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> +               return;
> +       }
> +
> +       ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> +       if (ret) {
> +               DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> +               clk_disable_unprepare(vc4_hdmi->pixel_clock);
> +               return;
> +       }
> +
>         if (vc4_hdmi->variant->reset)
>                 vc4_hdmi->variant->reset(vc4_hdmi);
>
> @@ -559,23 +589,9 @@ static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
>  {
> -       /*
> -        * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> -        * be faster than pixel clock, infinitesimally faster, tested in
> -        * simulation. Otherwise, exact value is unimportant for HDMI
> -        * operation." This conflicts with bcm2835's vc4 documentation, which
> -        * states HSM's clock has to be at least 108% of the pixel clock.
> -        *
> -        * Real life tests reveal that vc4's firmware statement holds up, and
> -        * users are able to use pixel clocks closer to HSM's, namely for
> -        * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> -        * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> -        * 162MHz.
> -        *
> -        * Additionally, the AXI clock needs to be at least 25% of
> -        * pixel clock, but HSM ends up being the limiting factor.
> -        */
> -       if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +
> +       if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
>                 return MODE_CLOCK_HIGH;
>
>         return MODE_OK;
> @@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>                 return -EPROBE_DEFER;
>         }
>
> -       /* This is the rate that is set by the firmware.  The number
> -        * needs to be a bit higher than the pixel clock rate
> -        * (generally 148.5Mhz).
> -        */
> -       ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
> -       if (ret) {
> -               DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> -               goto err_put_i2c;
> -       }
> -
> -       ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> -       if (ret) {
> -               DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
> -                         ret);
> -               goto err_put_i2c;
> -       }
> -
>         /* Only use the GPIO HPD pin if present in the DT, otherwise
>          * we'll use the HDMI core's register.
>          */
> @@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_destroy_encoder:
>         drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> -       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         pm_runtime_disable(dev);
> -err_put_i2c:
>         put_device(&vc4_hdmi->ddc->dev);
>
>         return ret;
> @@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>         vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>         drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>
> -       clk_disable_unprepare(vc4_hdmi->hsm_clock);
>         pm_runtime_disable(dev);
>
>         put_device(&vc4_hdmi->ddc->dev);
> @@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .max_pixel_clock        = 162000000,
>         .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
>         .num_registers          = ARRAY_SIZE(vc4_hdmi_fields),
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 3f07aebe89f1..342f6e0227a2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
>         /* Set to true when the CEC support is available */
>         bool cec_available;
>
> +       /* Maximum pixel clock supported by the controller (in Hz) */
> +       unsigned long long max_pixel_clock;
> +
>         /* List of the registers available on that variant */
>         const struct vc4_hdmi_register *registers;
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 14:57       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HSM clock needs to be running at 101% the pixel clock of the HDMI
> controller, however it's shared between the two HDMI controllers, which
> means that if the resolutions are different between the two HDMI
> controllers, and the lowest resolution is on the second (in enable order)
> controller, the first HDMI controller will end up with a smaller than
> expected clock rate.
>
> Since we don't really need an exact frequency there, we can simply change
> the minimum rate we expect instead.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 9f30fab744f2..d99188c90ff9 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>          * pixel clock, but HSM ends up being the limiting factor.
>          */
>         hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> -       ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +       ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
>         if (ret) {
>                 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
>                 return;
> --
> git-series 0.9.1

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

* Re: [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead
@ 2020-07-28 14:57       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HSM clock needs to be running at 101% the pixel clock of the HDMI
> controller, however it's shared between the two HDMI controllers, which
> means that if the resolutions are different between the two HDMI
> controllers, and the lowest resolution is on the second (in enable order)
> controller, the first HDMI controller will end up with a smaller than
> expected clock rate.
>
> Since we don't really need an exact frequency there, we can simply change
> the minimum rate we expect instead.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 9f30fab744f2..d99188c90ff9 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>          * pixel clock, but HSM ends up being the limiting factor.
>          */
>         hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> -       ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +       ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
>         if (ret) {
>                 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
>                 return;
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead
@ 2020-07-28 14:57       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 14:57 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HSM clock needs to be running at 101% the pixel clock of the HDMI
> controller, however it's shared between the two HDMI controllers, which
> means that if the resolutions are different between the two HDMI
> controllers, and the lowest resolution is on the second (in enable order)
> controller, the first HDMI controller will end up with a smaller than
> expected clock rate.
>
> Since we don't really need an exact frequency there, we can simply change
> the minimum rate we expect instead.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 9f30fab744f2..d99188c90ff9 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -462,7 +462,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>          * pixel clock, but HSM ends up being the limiting factor.
>          */
>         hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> -       ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +       ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
>         if (ret) {
>                 DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
>                 return;
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:00       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI driver was registering a single ALSA card so far with the name
> vc4-hdmi.
>
> Obviously, this is not going to work anymore when will have multiple HDMI

s/will/we

> controllers since we will end up trying to register two files with the same
> name.
>
> Let's use the variant to avoid that name conflict.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

With that change
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 1b6f51849d6c..0a9a323e03d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1044,7 +1044,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>
>         card->dai_link = dai_link;
>         card->num_links = 1;
> -       card->name = "vc4-hdmi";
> +       card->name = vc4_hdmi->variant->card_name;
>         card->dev = dev;
>
>         /*
> @@ -1503,6 +1503,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .card_name              = "vc4-hdmi",
>         .max_pixel_clock        = 162000000,
>         .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 4aea5ee8a91d..34138e0dd4a6 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
>
> +       /* ALSA card name */
> +       const char *card_name;
> +
>         /* Filename to expose the registers in debugfs */
>         const char *debugfs_name;
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards
@ 2020-07-28 15:00       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI driver was registering a single ALSA card so far with the name
> vc4-hdmi.
>
> Obviously, this is not going to work anymore when will have multiple HDMI

s/will/we

> controllers since we will end up trying to register two files with the same
> name.
>
> Let's use the variant to avoid that name conflict.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

With that change
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 1b6f51849d6c..0a9a323e03d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1044,7 +1044,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>
>         card->dai_link = dai_link;
>         card->num_links = 1;
> -       card->name = "vc4-hdmi";
> +       card->name = vc4_hdmi->variant->card_name;
>         card->dev = dev;
>
>         /*
> @@ -1503,6 +1503,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .card_name              = "vc4-hdmi",
>         .max_pixel_clock        = 162000000,
>         .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 4aea5ee8a91d..34138e0dd4a6 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
>
> +       /* ALSA card name */
> +       const char *card_name;
> +
>         /* Filename to expose the registers in debugfs */
>         const char *debugfs_name;
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards
@ 2020-07-28 15:00       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HDMI driver was registering a single ALSA card so far with the name
> vc4-hdmi.
>
> Obviously, this is not going to work anymore when will have multiple HDMI

s/will/we

> controllers since we will end up trying to register two files with the same
> name.
>
> Let's use the variant to avoid that name conflict.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

With that change
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 3 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h | 3 +++
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 1b6f51849d6c..0a9a323e03d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -1044,7 +1044,7 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
>
>         card->dai_link = dai_link;
>         card->num_links = 1;
> -       card->name = "vc4-hdmi";
> +       card->name = vc4_hdmi->variant->card_name;
>         card->dev = dev;
>
>         /*
> @@ -1503,6 +1503,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>         .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
>         .debugfs_name           = "hdmi_regs",
> +       .card_name              = "vc4-hdmi",
>         .max_pixel_clock        = 162000000,
>         .cec_available          = true,
>         .registers              = vc4_hdmi_fields,
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 4aea5ee8a91d..34138e0dd4a6 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -30,6 +30,9 @@ struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
>
> +       /* ALSA card name */
> +       const char *card_name;
> +
>         /* Filename to expose the registers in debugfs */
>         const char *debugfs_name;
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:01       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The current code has some logic, disabled by default, to dump the register
> setup in the HDMI controller.
>
> However, since we're going to split those functions in multiple, shorter,
> functions that only make sense where they are called in sequence, keeping
> the register dump makes little sense.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 17 -----------------
>  1 file changed, 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 0a9a323e03d8..4058985940e6 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> -       bool debug_dump_regs = false;
>         unsigned long pixel_rate, hsm_rate;
>         int ret;
>
> @@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->phy_init)
>                 vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> -
> -               dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
> -               drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
> -               drm_print_regset32(&p, &vc4_hdmi->hd_regset);
> -       }
> -
>         HDMI_WRITE(HDMI_VID_CTL, 0);
>
>         HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> @@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> -
> -               dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
> -               drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
> -               drm_print_regset32(&p, &vc4_hdmi->hd_regset);
> -       }
> -
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) |
>                    VC4_HD_VID_CTL_ENABLE |
> --
> git-series 0.9.1

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

* Re: [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable
@ 2020-07-28 15:01       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The current code has some logic, disabled by default, to dump the register
> setup in the HDMI controller.
>
> However, since we're going to split those functions in multiple, shorter,
> functions that only make sense where they are called in sequence, keeping
> the register dump makes little sense.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 17 -----------------
>  1 file changed, 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 0a9a323e03d8..4058985940e6 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> -       bool debug_dump_regs = false;
>         unsigned long pixel_rate, hsm_rate;
>         int ret;
>
> @@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->phy_init)
>                 vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> -
> -               dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
> -               drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
> -               drm_print_regset32(&p, &vc4_hdmi->hd_regset);
> -       }
> -
>         HDMI_WRITE(HDMI_VID_CTL, 0);
>
>         HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> @@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> -
> -               dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
> -               drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
> -               drm_print_regset32(&p, &vc4_hdmi->hd_regset);
> -       }
> -
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) |
>                    VC4_HD_VID_CTL_ENABLE |
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable
@ 2020-07-28 15:01       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The current code has some logic, disabled by default, to dump the register
> setup in the HDMI controller.
>
> However, since we're going to split those functions in multiple, shorter,
> functions that only make sense where they are called in sequence, keeping
> the register dump makes little sense.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 17 -----------------
>  1 file changed, 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 0a9a323e03d8..4058985940e6 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -430,7 +430,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> -       bool debug_dump_regs = false;
>         unsigned long pixel_rate, hsm_rate;
>         int ret;
>
> @@ -489,14 +488,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->phy_init)
>                 vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> -
> -               dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n");
> -               drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
> -               drm_print_regset32(&p, &vc4_hdmi->hd_regset);
> -       }
> -
>         HDMI_WRITE(HDMI_VID_CTL, 0);
>
>         HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> @@ -522,14 +513,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
>
> -       if (debug_dump_regs) {
> -               struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev);
> -
> -               dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n");
> -               drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
> -               drm_print_regset32(&p, &vc4_hdmi->hd_regset);
> -       }
> -
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) |
>                    VC4_HD_VID_CTL_ENABLE |
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:03       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid a pixel getting stuck in an unflushable FIFO, we need to
> recenter the FIFO every time we're doing a modeset and not only if we're
> connected to an HDMI monitor.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++----------------
>  1 file changed, 26 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 4058985940e6..00592c1ada73 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>                    (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>  }
>
> +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> +{
> +       u32 drift;
> +       int ret;
> +
> +       drift = HDMI_READ(HDMI_FIFO_CTL);
> +       drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
> +
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift | VC4_HDMI_FIFO_CTL_RECENTER);
> +       usleep_range(1000, 1100);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift | VC4_HDMI_FIFO_CTL_RECENTER);
> +
> +       ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
> +                      VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
> +       WARN_ONCE(ret, "Timeout waiting for "
> +                 "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> +}
> +
>  static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  {
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> @@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         }
>
>         if (vc4_encoder->hdmi_monitor) {
> -               u32 drift;
> -
>                 WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                           VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> @@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                            VC4_HDMI_RAM_PACKET_ENABLE);
>
>                 vc4_hdmi_set_infoframes(encoder);
> -
> -               drift = HDMI_READ(HDMI_FIFO_CTL);
> -               drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
> -
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift | VC4_HDMI_FIFO_CTL_RECENTER);
> -               usleep_range(1000, 1100);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift | VC4_HDMI_FIFO_CTL_RECENTER);
> -
> -               ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
> -                              VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
> -               WARN_ONCE(ret, "Timeout waiting for "
> -                         "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>         }
> +
> +       vc4_hdmi_recenter_fifo(vc4_hdmi);
>  }
>
>  static enum drm_mode_status
> --
> git-series 0.9.1

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

* Re: [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO
@ 2020-07-28 15:03       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid a pixel getting stuck in an unflushable FIFO, we need to
> recenter the FIFO every time we're doing a modeset and not only if we're
> connected to an HDMI monitor.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++----------------
>  1 file changed, 26 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 4058985940e6..00592c1ada73 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>                    (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>  }
>
> +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> +{
> +       u32 drift;
> +       int ret;
> +
> +       drift = HDMI_READ(HDMI_FIFO_CTL);
> +       drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
> +
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift | VC4_HDMI_FIFO_CTL_RECENTER);
> +       usleep_range(1000, 1100);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift | VC4_HDMI_FIFO_CTL_RECENTER);
> +
> +       ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
> +                      VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
> +       WARN_ONCE(ret, "Timeout waiting for "
> +                 "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> +}
> +
>  static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  {
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> @@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         }
>
>         if (vc4_encoder->hdmi_monitor) {
> -               u32 drift;
> -
>                 WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                           VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> @@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                            VC4_HDMI_RAM_PACKET_ENABLE);
>
>                 vc4_hdmi_set_infoframes(encoder);
> -
> -               drift = HDMI_READ(HDMI_FIFO_CTL);
> -               drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
> -
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift | VC4_HDMI_FIFO_CTL_RECENTER);
> -               usleep_range(1000, 1100);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift | VC4_HDMI_FIFO_CTL_RECENTER);
> -
> -               ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
> -                              VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
> -               WARN_ONCE(ret, "Timeout waiting for "
> -                         "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>         }
> +
> +       vc4_hdmi_recenter_fifo(vc4_hdmi);
>  }
>
>  static enum drm_mode_status
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO
@ 2020-07-28 15:03       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:03 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid a pixel getting stuck in an unflushable FIFO, we need to
> recenter the FIFO every time we're doing a modeset and not only if we're
> connected to an HDMI monitor.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 46 +++++++++++++++++++----------------
>  1 file changed, 26 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 4058985940e6..00592c1ada73 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -425,6 +425,30 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>                    (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>  }
>
> +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> +{
> +       u32 drift;
> +       int ret;
> +
> +       drift = HDMI_READ(HDMI_FIFO_CTL);
> +       drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
> +
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift | VC4_HDMI_FIFO_CTL_RECENTER);
> +       usleep_range(1000, 1100);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> +       HDMI_WRITE(HDMI_FIFO_CTL,
> +                  drift | VC4_HDMI_FIFO_CTL_RECENTER);
> +
> +       ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
> +                      VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
> +       WARN_ONCE(ret, "Timeout waiting for "
> +                 "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
> +}
> +
>  static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  {
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> @@ -543,8 +567,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         }
>
>         if (vc4_encoder->hdmi_monitor) {
> -               u32 drift;
> -
>                 WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) &
>                           VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE));
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> @@ -555,25 +577,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>                            VC4_HDMI_RAM_PACKET_ENABLE);
>
>                 vc4_hdmi_set_infoframes(encoder);
> -
> -               drift = HDMI_READ(HDMI_FIFO_CTL);
> -               drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK;
> -
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift | VC4_HDMI_FIFO_CTL_RECENTER);
> -               usleep_range(1000, 1100);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift & ~VC4_HDMI_FIFO_CTL_RECENTER);
> -               HDMI_WRITE(HDMI_FIFO_CTL,
> -                          drift | VC4_HDMI_FIFO_CTL_RECENTER);
> -
> -               ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) &
> -                              VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
> -               WARN_ONCE(ret, "Timeout waiting for "
> -                         "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>         }
> +
> +       vc4_hdmi_recenter_fifo(vc4_hdmi);
>  }
>
>  static enum drm_mode_status
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:04       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to prevent some pixels getting stuck in an unflushable FIFO on
> bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI
> controller (the encoder) in an intertwined way, and with tight delays.
>
> However, the atomic callbacks don't really provide a way to work with
> either constraints, so we need to roll our own callbacks so that we can
> provide those guarantees.
>
> Since those callbacks have been implemented and called in the CRTC code, we
> can just implement them in the HDMI driver now.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++++++++----
>  1 file changed, 35 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 00592c1ada73..bbe521ab000b 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
>                 vc4_hdmi_set_audio_infoframe(encoder);
>  }
>
> -static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>  {
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       int ret;
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
> +}
> +
> +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> +{
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       int ret;
>
>         if (vc4_hdmi->variant->phy_disable)
>                 vc4_hdmi->variant->phy_disable(vc4_hdmi);
> @@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>                 DRM_ERROR("Failed to release power domain: %d\n", ret);
>  }
>
> +static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
>  static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
>  {
>         u32 csc_ctl;
> @@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>                   "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>  }
>
> -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>  {
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         unsigned long pixel_rate, hsm_rate;
>         int ret;
>
> @@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>
>         if (vc4_hdmi->variant->set_timings)
>                 vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
> +}
> +
> +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>
>         if (vc4_encoder->hdmi_monitor &&
>             drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
> @@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         }
>
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
> +}
> +
> +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
> +{
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       int ret;
>
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) |
> @@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         vc4_hdmi_recenter_fifo(vc4_hdmi);
>  }
>
> +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +}
> +
>  static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
> @@ -1362,6 +1388,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
>         vc4_hdmi->encoder.base.type = variant->encoder_type;
> +       vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
> +       vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
> +       vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
> +       vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
> +       vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
>         vc4_hdmi->pdev = pdev;
>         vc4_hdmi->variant = variant;
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks
@ 2020-07-28 15:04       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to prevent some pixels getting stuck in an unflushable FIFO on
> bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI
> controller (the encoder) in an intertwined way, and with tight delays.
>
> However, the atomic callbacks don't really provide a way to work with
> either constraints, so we need to roll our own callbacks so that we can
> provide those guarantees.
>
> Since those callbacks have been implemented and called in the CRTC code, we
> can just implement them in the HDMI driver now.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++++++++----
>  1 file changed, 35 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 00592c1ada73..bbe521ab000b 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
>                 vc4_hdmi_set_audio_infoframe(encoder);
>  }
>
> -static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>  {
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       int ret;
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
> +}
> +
> +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> +{
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       int ret;
>
>         if (vc4_hdmi->variant->phy_disable)
>                 vc4_hdmi->variant->phy_disable(vc4_hdmi);
> @@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>                 DRM_ERROR("Failed to release power domain: %d\n", ret);
>  }
>
> +static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
>  static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
>  {
>         u32 csc_ctl;
> @@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>                   "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>  }
>
> -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>  {
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         unsigned long pixel_rate, hsm_rate;
>         int ret;
>
> @@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>
>         if (vc4_hdmi->variant->set_timings)
>                 vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
> +}
> +
> +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>
>         if (vc4_encoder->hdmi_monitor &&
>             drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
> @@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         }
>
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
> +}
> +
> +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
> +{
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       int ret;
>
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) |
> @@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         vc4_hdmi_recenter_fifo(vc4_hdmi);
>  }
>
> +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +}
> +
>  static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
> @@ -1362,6 +1388,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
>         vc4_hdmi->encoder.base.type = variant->encoder_type;
> +       vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
> +       vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
> +       vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
> +       vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
> +       vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
>         vc4_hdmi->pdev = pdev;
>         vc4_hdmi->variant = variant;
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks
@ 2020-07-28 15:04       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:04 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to prevent some pixels getting stuck in an unflushable FIFO on
> bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI
> controller (the encoder) in an intertwined way, and with tight delays.
>
> However, the atomic callbacks don't really provide a way to work with
> either constraints, so we need to roll our own callbacks so that we can
> provide those guarantees.
>
> Since those callbacks have been implemented and called in the CRTC code, we
> can just implement them in the HDMI driver now.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 39 +++++++++++++++++++++++++++++++----
>  1 file changed, 35 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 00592c1ada73..bbe521ab000b 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -320,12 +320,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder)
>                 vc4_hdmi_set_audio_infoframe(encoder);
>  }
>
> -static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>  {
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       int ret;
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
> +}
> +
> +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> +{
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       int ret;
>
>         if (vc4_hdmi->variant->phy_disable)
>                 vc4_hdmi->variant->phy_disable(vc4_hdmi);
> @@ -341,6 +346,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>                 DRM_ERROR("Failed to release power domain: %d\n", ret);
>  }
>
> +static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> +{
> +}
> +
>  static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
>  {
>         u32 csc_ctl;
> @@ -449,11 +458,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>                   "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
>  }
>
> -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>  {
>         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> -       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>         unsigned long pixel_rate, hsm_rate;
>         int ret;
>
> @@ -521,6 +529,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>
>         if (vc4_hdmi->variant->set_timings)
>                 vc4_hdmi->variant->set_timings(vc4_hdmi, mode);
> +}
> +
> +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
> +{
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>
>         if (vc4_encoder->hdmi_monitor &&
>             drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) {
> @@ -536,6 +551,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         }
>
>         HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
> +}
> +
> +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
> +{
> +       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +       struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       int ret;
>
>         HDMI_WRITE(HDMI_VID_CTL,
>                    HDMI_READ(HDMI_VID_CTL) |
> @@ -582,6 +604,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>         vc4_hdmi_recenter_fifo(vc4_hdmi);
>  }
>
> +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> +{
> +}
> +
>  static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>                             const struct drm_display_mode *mode)
> @@ -1362,6 +1388,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>         dev_set_drvdata(dev, vc4_hdmi);
>         encoder = &vc4_hdmi->encoder.base.base;
>         vc4_hdmi->encoder.base.type = variant->encoder_type;
> +       vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure;
> +       vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable;
> +       vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable;
> +       vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable;
> +       vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown;
>         vc4_hdmi->pdev = pdev;
>         vc4_hdmi->variant = variant;
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:06       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:06 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The VID_CTL setup is done in several places in the driver even though it's
> not really required. Let's simplify it a bit to do the configuration in one
> go.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index bbe521ab000b..f56a718a3643 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>
>         HDMI_WRITE(HDMI_VERTB0, vertb_even);
>         HDMI_WRITE(HDMI_VERTB1, vertb);
> -
> -       HDMI_WRITE(HDMI_VID_CTL,
> -                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>  }
>
>  static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> @@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->phy_init)
>                 vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
> -       HDMI_WRITE(HDMI_VID_CTL, 0);
> -
>         HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>                    HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
> @@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
>
>  static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
>  {
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
> +       bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>         int ret;
>
>         HDMI_WRITE(HDMI_VID_CTL,
> -                  HDMI_READ(HDMI_VID_CTL) |
>                    VC4_HD_VID_CTL_ENABLE |
>                    VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> -                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
> +                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
>         if (vc4_encoder->hdmi_monitor) {
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> --
> git-series 0.9.1

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

* Re: [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once
@ 2020-07-28 15:06       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:06 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The VID_CTL setup is done in several places in the driver even though it's
> not really required. Let's simplify it a bit to do the configuration in one
> go.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index bbe521ab000b..f56a718a3643 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>
>         HDMI_WRITE(HDMI_VERTB0, vertb_even);
>         HDMI_WRITE(HDMI_VERTB1, vertb);
> -
> -       HDMI_WRITE(HDMI_VID_CTL,
> -                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>  }
>
>  static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> @@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->phy_init)
>                 vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
> -       HDMI_WRITE(HDMI_VID_CTL, 0);
> -
>         HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>                    HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
> @@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
>
>  static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
>  {
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
> +       bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>         int ret;
>
>         HDMI_WRITE(HDMI_VID_CTL,
> -                  HDMI_READ(HDMI_VID_CTL) |
>                    VC4_HD_VID_CTL_ENABLE |
>                    VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> -                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
> +                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
>         if (vc4_encoder->hdmi_monitor) {
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once
@ 2020-07-28 15:06       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:06 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The VID_CTL setup is done in several places in the driver even though it's
> not really required. Let's simplify it a bit to do the configuration in one
> go.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
>  1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index bbe521ab000b..f56a718a3643 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -428,10 +428,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>
>         HDMI_WRITE(HDMI_VERTB0, vertb_even);
>         HDMI_WRITE(HDMI_VERTB1, vertb);
> -
> -       HDMI_WRITE(HDMI_VID_CTL,
> -                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> -                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>  }
>
>  static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
> @@ -520,8 +516,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder)
>         if (vc4_hdmi->variant->phy_init)
>                 vc4_hdmi->variant->phy_init(vc4_hdmi, mode);
>
> -       HDMI_WRITE(HDMI_VID_CTL, 0);
> -
>         HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>                    HDMI_READ(HDMI_SCHEDULER_CONTROL) |
>                    VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT |
> @@ -555,15 +549,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder)
>
>  static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
>  {
> +       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>         struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> +       bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
> +       bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
>         int ret;
>
>         HDMI_WRITE(HDMI_VID_CTL,
> -                  HDMI_READ(HDMI_VID_CTL) |
>                    VC4_HD_VID_CTL_ENABLE |
>                    VC4_HD_VID_CTL_UNDERFLOW_ENABLE |
> -                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET);
> +                  VC4_HD_VID_CTL_FRAME_COUNTER_RESET |
> +                  (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
> +                  (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
>         if (vc4_encoder->hdmi_monitor) {
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:09       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid pixels getting stuck in an unflushable FIFO, we need when
> we disable the HDMI controller to switch away from getting our pixels from
> the pixelvalve and instead use blank pixels, and switch back to the
> pixelvalve when we enable the HDMI controller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c |  9 +++++++++
>  drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
>  2 files changed, 12 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index f56a718a3643..37463b016b47 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
> +
> +       HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
> +                  VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
> +
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
>  }
>
>  static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> @@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
>                    (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
>                    (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
> +
>         if (vc4_encoder->hdmi_monitor) {
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>                            HDMI_READ(HDMI_SCHEDULER_CONTROL) |
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index d1e8961edaa0..30af52b406f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -723,6 +723,9 @@
>  # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET    BIT(29)
>  # define VC4_HD_VID_CTL_VSYNC_LOW              BIT(28)
>  # define VC4_HD_VID_CTL_HSYNC_LOW              BIT(27)
> +# define VC4_HD_VID_CTL_CLRSYNC                        BIT(24)
> +# define VC4_HD_VID_CTL_CLRRGB                 BIT(23)
> +# define VC4_HD_VID_CTL_BLANKPIX               BIT(18)
>
>  # define VC4_HD_CSC_CTL_ORDER_MASK             VC4_MASK(7, 5)
>  # define VC4_HD_CSC_CTL_ORDER_SHIFT            5
> --
> git-series 0.9.1

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

* Re: [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled
@ 2020-07-28 15:09       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid pixels getting stuck in an unflushable FIFO, we need when
> we disable the HDMI controller to switch away from getting our pixels from
> the pixelvalve and instead use blank pixels, and switch back to the
> pixelvalve when we enable the HDMI controller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c |  9 +++++++++
>  drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
>  2 files changed, 12 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index f56a718a3643..37463b016b47 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
> +
> +       HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
> +                  VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
> +
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
>  }
>
>  static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> @@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
>                    (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
>                    (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
> +
>         if (vc4_encoder->hdmi_monitor) {
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>                            HDMI_READ(HDMI_SCHEDULER_CONTROL) |
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index d1e8961edaa0..30af52b406f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -723,6 +723,9 @@
>  # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET    BIT(29)
>  # define VC4_HD_VID_CTL_VSYNC_LOW              BIT(28)
>  # define VC4_HD_VID_CTL_HSYNC_LOW              BIT(27)
> +# define VC4_HD_VID_CTL_CLRSYNC                        BIT(24)
> +# define VC4_HD_VID_CTL_CLRRGB                 BIT(23)
> +# define VC4_HD_VID_CTL_BLANKPIX               BIT(18)
>
>  # define VC4_HD_CSC_CTL_ORDER_MASK             VC4_MASK(7, 5)
>  # define VC4_HD_CSC_CTL_ORDER_SHIFT            5
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled
@ 2020-07-28 15:09       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid pixels getting stuck in an unflushable FIFO, we need when
> we disable the HDMI controller to switch away from getting our pixels from
> the pixelvalve and instead use blank pixels, and switch back to the
> pixelvalve when we enable the HDMI controller.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c |  9 +++++++++
>  drivers/gpu/drm/vc4/vc4_regs.h |  3 +++
>  2 files changed, 12 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index f56a718a3643..37463b016b47 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -325,6 +325,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder)
>         struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>
>         HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
> +
> +       HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) |
> +                  VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC);
> +
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
>  }
>
>  static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder)
> @@ -563,6 +569,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder)
>                    (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) |
>                    (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW));
>
> +       HDMI_WRITE(HDMI_VID_CTL,
> +                  HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX);
> +
>         if (vc4_encoder->hdmi_monitor) {
>                 HDMI_WRITE(HDMI_SCHEDULER_CONTROL,
>                            HDMI_READ(HDMI_SCHEDULER_CONTROL) |
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index d1e8961edaa0..30af52b406f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -723,6 +723,9 @@
>  # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET    BIT(29)
>  # define VC4_HD_VID_CTL_VSYNC_LOW              BIT(28)
>  # define VC4_HD_VID_CTL_HSYNC_LOW              BIT(27)
> +# define VC4_HD_VID_CTL_CLRSYNC                        BIT(24)
> +# define VC4_HD_VID_CTL_CLRRGB                 BIT(23)
> +# define VC4_HD_VID_CTL_BLANKPIX               BIT(18)
>
>  # define VC4_HD_CSC_CTL_ORDER_MASK             VC4_MASK(7, 5)
>  # define VC4_HD_CSC_CTL_ORDER_SHIFT            5
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:21       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:21 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that the driver is ready for it, let's bring in the HDMI controllers
> variants for the BCM2711.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c      | 278 +++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h      |  36 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c  | 480 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h      |   2 +-
>  5 files changed, 997 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 37463b016b47..d5ba0b1b73a9 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -43,6 +43,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/rational.h>
> +#include <linux/reset.h>
>  #include <sound/dmaengine_pcm.h>
>  #include <sound/pcm_drm_eld.h>
>  #include <sound/pcm_params.h>
> @@ -53,6 +54,31 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
> +#define VC5_HDMI_HORZA_HFP_SHIFT               16
> +#define VC5_HDMI_HORZA_HFP_MASK                        VC4_MASK(28, 16)
> +#define VC5_HDMI_HORZA_VPOS                    BIT(15)
> +#define VC5_HDMI_HORZA_HPOS                    BIT(14)
> +#define VC5_HDMI_HORZA_HAP_SHIFT               0
> +#define VC5_HDMI_HORZA_HAP_MASK                        VC4_MASK(13, 0)
> +
> +#define VC5_HDMI_HORZB_HBP_SHIFT               16
> +#define VC5_HDMI_HORZB_HBP_MASK                        VC4_MASK(26, 16)
> +#define VC5_HDMI_HORZB_HSP_SHIFT               0
> +#define VC5_HDMI_HORZB_HSP_MASK                        VC4_MASK(10, 0)
> +
> +#define VC5_HDMI_VERTA_VSP_SHIFT               24
> +#define VC5_HDMI_VERTA_VSP_MASK                        VC4_MASK(28, 24)
> +#define VC5_HDMI_VERTA_VFP_SHIFT               16
> +#define VC5_HDMI_VERTA_VFP_MASK                        VC4_MASK(22, 16)
> +#define VC5_HDMI_VERTA_VAL_SHIFT               0
> +#define VC5_HDMI_VERTA_VAL_MASK                        VC4_MASK(12, 0)
> +
> +#define VC5_HDMI_VERTB_VSPO_SHIFT              16
> +#define VC5_HDMI_VERTB_VSPO_MASK               VC4_MASK(29, 16)
> +
> +# define VC4_HD_M_SW_RST                       BIT(2)
> +# define VC4_HD_M_ENABLE                       BIT(0)
> +
>  #define CEC_CLOCK_FREQ 40000
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -82,6 +108,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
>         HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
>  }
>
> +static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
> +{
> +       reset_control_reset(vc4_hdmi->reset);
> +
> +       HDMI_WRITE(HDMI_DVP_CTL, 0);
> +
> +       HDMI_WRITE(HDMI_CLOCK_STOP,
> +                  HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
> +}
> +
>  static enum drm_connector_status
>  vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -391,6 +427,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
>         HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
>  }
>
> +static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> +{
> +       u32 csc_ctl;
> +
> +       csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
> +
> +       if (enable) {
> +               /* CEA VICs other than #1 requre limited range RGB
> +                * output unless overridden by an AVI infoframe.
> +                * Apply a colorspace conversion to squash 0-255 down
> +                * to 16-235.  The matrix here is:
> +                *
> +                * [ 0.8594 0      0      16]
> +                * [ 0      0.8594 0      16]
> +                * [ 0      0      0.8594 16]
> +                * [ 0      0      0       1]
> +                * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> +                */
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
> +       } else {
> +               /* Still use the matrix for full range, but make it unity.
> +                * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> +                */
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
> +       }
> +
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> +}
> +
>  static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>                                  struct drm_display_mode *mode)
>  {
> @@ -435,6 +510,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>         HDMI_WRITE(HDMI_VERTB0, vertb_even);
>         HDMI_WRITE(HDMI_VERTB1, vertb);
>  }
> +static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
> +                                struct drm_display_mode *mode)
> +{
> +       bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
> +       bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
> +       bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +       u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
> +       u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
> +                                  VC5_HDMI_VERTA_VSP) |
> +                    VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
> +                                  VC5_HDMI_VERTA_VFP) |
> +                    VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
> +       u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
> +                    VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
> +                                  VC4_HDMI_VERTB_VBP));
> +       u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
> +                         VC4_SET_FIELD(mode->crtc_vtotal -
> +                                       mode->crtc_vsync_end -
> +                                       interlaced,
> +                                       VC4_HDMI_VERTB_VBP));
> +
> +       HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
> +       HDMI_WRITE(HDMI_HORZA,
> +                  (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
> +                  (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
> +                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> +                                VC5_HDMI_HORZA_HAP) |
> +                  VC4_SET_FIELD((mode->hsync_start -
> +                                 mode->hdisplay) * pixel_rep,
> +                                VC5_HDMI_HORZA_HFP));
> +
> +       HDMI_WRITE(HDMI_HORZB,
> +                  VC4_SET_FIELD((mode->htotal -
> +                                 mode->hsync_end) * pixel_rep,
> +                                VC5_HDMI_HORZB_HBP) |
> +                  VC4_SET_FIELD((mode->hsync_end -
> +                                 mode->hsync_start) * pixel_rep,
> +                                VC5_HDMI_HORZB_HSP));
> +
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
> +
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
> +
> +       HDMI_WRITE(HDMI_CLOCK_STOP, 0);
> +}
>
>  static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>  {
> @@ -645,6 +767,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
>         return channel_map;
>  }
>
> +static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
> +{
> +       int i;
> +       u32 channel_map = 0;
> +
> +       for (i = 0; i < 8; i++) {
> +               if (channel_mask & BIT(i))
> +                       channel_map |= i << (4 * i);
> +       }
> +       return channel_map;
> +}
> +
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
>  {
> @@ -1377,6 +1511,98 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>         return 0;
>  }
>
> +static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
> +{
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       struct device *dev = &pdev->dev;
> +       struct resource *res;
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
> +                                              resource_size(res));
> +       if (IS_ERR(vc4_hdmi->hdmicore_regs))
> +               return PTR_ERR(vc4_hdmi->hdmicore_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->hd_regs))
> +               return PTR_ERR(vc4_hdmi->hd_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->cec_regs))
> +               return PTR_ERR(vc4_hdmi->cec_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->csc_regs))
> +               return PTR_ERR(vc4_hdmi->csc_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->dvp_regs))
> +               return PTR_ERR(vc4_hdmi->dvp_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->phy_regs))
> +               return PTR_ERR(vc4_hdmi->phy_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->ram_regs))
> +               return PTR_ERR(vc4_hdmi->ram_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->rm_regs))
> +               return PTR_ERR(vc4_hdmi->rm_regs);
> +
> +       vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
> +       if (IS_ERR(vc4_hdmi->hsm_clock)) {
> +               DRM_ERROR("Failed to get HDMI state machine clock\n");
> +               return PTR_ERR(vc4_hdmi->hsm_clock);
> +       }
> +
> +       vc4_hdmi->audio_clock = devm_clk_get(dev, "clk-108M");
> +       if (IS_ERR(vc4_hdmi->audio_clock)) {
> +               DRM_ERROR("Failed to get 108MHz clock\n");
> +               return PTR_ERR(vc4_hdmi->audio_clock);
> +       }
> +
> +       vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
> +       if (IS_ERR(vc4_hdmi->reset)) {
> +               DRM_ERROR("Failed to get HDMI reset line\n");
> +               return PTR_ERR(vc4_hdmi->reset);
> +       }
> +
> +       return 0;
> +}
> +
>  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  {
>         const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
> @@ -1547,8 +1773,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .channel_map            = vc4_hdmi_channel_map,
>  };
>
> +static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
> +       .debugfs_name           = "hdmi0_regs",
> +       .card_name              = "vc4-hdmi-0",
> +       .max_pixel_clock        = 297000000,
> +       .registers              = vc5_hdmi_hdmi0_fields,
> +       .num_registers          = ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
> +       .phy_lane_mapping       = {
> +               PHY_LANE_0,
> +               PHY_LANE_1,
> +               PHY_LANE_2,
> +               PHY_LANE_CK,
> +       },
> +
> +       .init_resources         = vc5_hdmi_init_resources,
> +       .csc_setup              = vc5_hdmi_csc_setup,
> +       .reset                  = vc5_hdmi_reset,
> +       .set_timings            = vc5_hdmi_set_timings,
> +       .phy_init               = vc5_hdmi_phy_init,
> +       .phy_disable            = vc5_hdmi_phy_disable,
> +       .phy_rng_enable         = vc5_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc5_hdmi_phy_rng_disable,
> +       .channel_map            = vc5_hdmi_channel_map,
> +};
> +
> +static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI1,
> +       .debugfs_name           = "hdmi1_regs",
> +       .card_name              = "vc4-hdmi-1",
> +       .max_pixel_clock        = 297000000,
> +       .registers              = vc5_hdmi_hdmi1_fields,
> +       .num_registers          = ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
> +       .phy_lane_mapping       = {
> +               PHY_LANE_1,
> +               PHY_LANE_0,
> +               PHY_LANE_CK,
> +               PHY_LANE_2,
> +       },
> +
> +       .init_resources         = vc5_hdmi_init_resources,
> +       .csc_setup              = vc5_hdmi_csc_setup,
> +       .reset                  = vc5_hdmi_reset,
> +       .set_timings            = vc5_hdmi_set_timings,
> +       .phy_init               = vc5_hdmi_phy_init,
> +       .phy_disable            = vc5_hdmi_phy_disable,
> +       .phy_rng_enable         = vc5_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc5_hdmi_phy_rng_disable,
> +       .channel_map            = vc5_hdmi_channel_map,
> +};
> +
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
>         { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
> +       { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
> +       { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
>         {}
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 34138e0dd4a6..0806c6d9f24e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -26,6 +26,13 @@ struct drm_display_mode;
>  struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
> +enum vc4_hdmi_phy_channel {
> +       PHY_LANE_0 = 0,
> +       PHY_LANE_1,
> +       PHY_LANE_2,
> +       PHY_LANE_CK,
> +};
> +
>  struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
> @@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
>         /* Number of registers on that variant */
>         unsigned int num_registers;
>
> +       /* BCM2711 Only.
> +        * The variants don't map the lane in the same order in the
> +        * PHY, so this is an array mapping the HDMI channel (index)
> +        * to the PHY lane (value).
> +        */
> +       enum vc4_hdmi_phy_channel phy_lane_mapping[4];
> +
>         /* Callback to get the resources (memory region, interrupts,
>          * clocks, etc) for that variant.
>          */
> @@ -108,6 +122,20 @@ struct vc4_hdmi {
>         struct i2c_adapter *ddc;
>         void __iomem *hdmicore_regs;
>         void __iomem *hd_regs;
> +
> +       /* VC5 Only */
> +       void __iomem *cec_regs;
> +       /* VC5 Only */
> +       void __iomem *csc_regs;
> +       /* VC5 Only */
> +       void __iomem *dvp_regs;
> +       /* VC5 Only */
> +       void __iomem *phy_regs;
> +       /* VC5 Only */
> +       void __iomem *ram_regs;
> +       /* VC5 Only */
> +       void __iomem *rm_regs;
> +
>         int hpd_gpio;
>         bool hpd_active_low;
>
> @@ -120,6 +148,8 @@ struct vc4_hdmi {
>         struct clk *hsm_clock;
>         struct clk *audio_clock;
>
> +       struct reset_control *reset;
> +
>         struct debugfs_regset32 hdmi_regset;
>         struct debugfs_regset32 hd_regset;
>  };
> @@ -144,4 +174,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>  void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>  void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +                      struct drm_display_mode *mode);
> +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
> +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
> +
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 93287e24d7d1..4d36f8c33401 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -10,6 +10,123 @@
>  #include "vc4_regs.h"
>  #include "vc4_hdmi_regs.h"
>
> +#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB   BIT(5)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB        BIT(4)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET  BIT(3)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET   BIT(2)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET   BIT(1)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET   BIT(0)
> +
> +#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN     BIT(4)
> +
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT    29
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK     VC4_MASK(31, 29)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT   24
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK    VC4_MASK(28, 24)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT    21
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK     VC4_MASK(23, 21)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT   16
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK    VC4_MASK(20, 16)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT    13
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK     VC4_MASK(15, 13)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT   8
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK    VC4_MASK(12, 8)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT   5
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK    VC4_MASK(7, 5)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT  0
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK   VC4_MASK(4, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT      15
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK       VC4_MASK(19, 15)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT      10
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK       VC4_MASK(14, 10)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT      5
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK       VC4_MASK(9, 5)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT         0
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK          VC4_MASK(4, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT           16
> +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK            VC4_MASK(19, 16)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT  12
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK   VC4_MASK(15, 12)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT  8
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK   VC4_MASK(11, 8)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT  4
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK   VC4_MASK(7, 4)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT     0
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK      VC4_MASK(3, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT                 17
> +#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK                  VC4_MASK(19, 17)
> +#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT                 12
> +#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK                  VC4_MASK(16, 12)
> +#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT                        10
> +#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK                 VC4_MASK(11, 10)
> +#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT                 8
> +#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK                  VC4_MASK(9, 8)
> +#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT                 6
> +#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK                  VC4_MASK(7, 6)
> +#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT                        0
> +#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK                 VC4_MASK(5, 0)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE          BIT(13)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN          BIT(12)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW       BIT(11)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH      BIT(10)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT                9
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK         VC4_MASK(9, 9)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2          BIT(8)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2                BIT(7)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN          BIT(6)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK          BIT(5)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT                    16
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK                     VC4_MASK(27, 16)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT     14
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK      VC4_MASK(15, 14)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE          BIT(13)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT           11
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK            VC4_MASK(12, 11)
> +
> +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT              8
> +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK               VC4_MASK(15, 8)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT             0
> +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK              VC4_MASK(3, 0)
> +
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK VC4_MASK(13, 12)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT        12
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK  VC4_MASK(9, 8)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT 8
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK  VC4_MASK(5, 4)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT 4
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK  VC4_MASK(1, 0)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT 0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK                VC4_MASK(27, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT       0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK                VC4_MASK(27, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT       0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK VC4_MASK(31, 16)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT        16
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK   VC4_MASK(15, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT  0
> +
> +#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS         BIT(19)
> +#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR         BIT(17)
> +#define VC4_HDMI_RM_CONTROL_FREE_RUN                   BIT(4)
> +
> +#define VC4_HDMI_RM_OFFSET_ONLY                                BIT(31)
> +#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT                        0
> +#define VC4_HDMI_RM_OFFSET_OFFSET_MASK                 VC4_MASK(30, 0)
> +
> +#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT                 24
> +#define VC4_HDMI_RM_FORMAT_SHIFT_MASK                  VC4_MASK(25, 24)
> +
> +#define OSCILLATOR_FREQUENCY   54000000
> +
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
>  {
>         /* PHY should be in reset, like
> @@ -38,3 +155,366 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
>                    HDMI_READ(HDMI_TX_PHY_CTL_0) |
>                    VC4_HDMI_TX_PHY_RNG_PWRDN);
>  }
> +
> +static unsigned long long
> +phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
> +{
> +       unsigned long long vco_freq = clock;
> +       unsigned int _vco_div = 0;
> +       unsigned int _vco_sel = 0;
> +
> +       while (vco_freq < 3000000000ULL) {
> +               _vco_div++;
> +               vco_freq = clock * _vco_div * 10;
> +       }
> +
> +       if (vco_freq > 4500000000ULL)
> +               _vco_sel = 1;
> +
> +       *vco_sel = _vco_sel;
> +       *vco_div = _vco_div;
> +
> +       return vco_freq;
> +}
> +
> +static u8 phy_get_cp_current(unsigned long vco_freq)
> +{
> +       if (vco_freq < 3700000000ULL)
> +               return 0x1c;
> +
> +       return 0x18;
> +}
> +
> +static u32 phy_get_rm_offset(unsigned long long vco_freq)
> +{
> +       unsigned long long fref = OSCILLATOR_FREQUENCY;
> +       u64 offset = 0;
> +
> +       /* RM offset is stored as 9.22 format */
> +       offset = vco_freq * 2;
> +       offset = offset << 22;
> +       do_div(offset, fref);
> +       offset >>= 2;
> +
> +       return offset;
> +}
> +
> +static u8 phy_get_vco_gain(unsigned long long vco_freq)
> +{
> +       if (vco_freq < 3350000000ULL)
> +               return 0xf;
> +
> +       if (vco_freq < 3700000000ULL)
> +               return 0xc;
> +
> +       if (vco_freq < 4050000000ULL)
> +               return 0x6;
> +
> +       if (vco_freq < 4800000000ULL)
> +               return 0x5;
> +
> +       if (vco_freq < 5200000000ULL)
> +               return 0x7;
> +
> +       return 0x2;
> +}
> +
> +struct phy_lane_settings {
> +       struct {
> +               u8 preemphasis;
> +               u8 main_driver;
> +       } amplitude;
> +
> +       u8 res_sel_data;
> +       u8 term_res_sel_data;
> +};
> +
> +struct phy_settings {
> +       unsigned long long min_rate;
> +       unsigned long long max_rate;
> +       struct phy_lane_settings channel[3];
> +       struct phy_lane_settings clock;
> +};
> +
> +static const struct phy_settings vc5_hdmi_phy_settings[] = {
> +       {
> +               0, 50000000,
> +               {
> +                       {{0x0, 0x0A}, 0x12, 0x0},
> +                       {{0x0, 0x0A}, 0x12, 0x0},
> +                       {{0x0, 0x0A}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0A}, 0x18, 0x0},
> +       },
> +       {
> +               50000001, 75000000,
> +               {
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               75000001,   165000000,
> +               {
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               165000001,  250000000,
> +               {
> +                       {{0x0, 0x0F}, 0x12, 0x1},
> +                       {{0x0, 0x0F}, 0x12, 0x1},
> +                       {{0x0, 0x0F}, 0x12, 0x1}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               250000001,  340000000,
> +               {
> +                       {{0x2, 0x0D}, 0x12, 0x1},
> +                       {{0x2, 0x0D}, 0x12, 0x1},
> +                       {{0x2, 0x0D}, 0x12, 0x1}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0xF},
> +       },
> +       {
> +               340000001,  450000000,
> +               {
> +                       {{0x0, 0x1B}, 0x12, 0xF},
> +                       {{0x0, 0x1B}, 0x12, 0xF},
> +                       {{0x0, 0x1B}, 0x12, 0xF}
> +               },
> +               {{0x0, 0x0A}, 0x12, 0xF},
> +       },
> +       {
> +               450000001,  600000000,
> +               {
> +                       {{0x0, 0x1C}, 0x12, 0xF},
> +                       {{0x0, 0x1C}, 0x12, 0xF},
> +                       {{0x0, 0x1C}, 0x12, 0xF}
> +               },
> +               {{0x0, 0x0B}, 0x13, 0xF},
> +       },
> +};
> +
> +static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
> +{
> +       unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
> +       unsigned int i;
> +
> +       for (i = 0; i < count; i++) {
> +               const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
> +
> +               if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
> +                       return s;
> +       }
> +
> +       /*
> +        * If the pixel clock exceeds our max setting, try the max
> +        * setting anyway.
> +        */
> +       return &vc5_hdmi_phy_settings[count - 1];
> +}
> +
> +static const struct phy_lane_settings *
> +phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
> +                        unsigned long long tmds_rate)
> +{
> +       const struct phy_settings *settings = phy_get_settings(tmds_rate);
> +
> +       if (chan == PHY_LANE_CK)
> +               return &settings->clock;
> +
> +       return &settings->channel[chan];
> +}
> +
> +static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
> +}
> +
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +{
> +       const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
> +       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> +       unsigned long long pixel_freq = mode->clock * 1000;
> +       unsigned long long vco_freq;
> +       unsigned char word_sel;
> +       u8 vco_sel, vco_div;
> +
> +       vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
> +
> +       vc5_hdmi_reset_phy(vc4_hdmi);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
> +
> +       HDMI_WRITE(HDMI_RM_CONTROL,
> +                  HDMI_READ(HDMI_RM_CONTROL) |
> +                  VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
> +                  VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
> +                  VC4_HDMI_RM_CONTROL_FREE_RUN);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
> +                  (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
> +                   ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
> +                  VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
> +                  (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
> +                   ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
> +                  VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
> +
> +       HDMI_WRITE(HDMI_RM_OFFSET,
> +                  VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
> +                                VC4_HDMI_RM_OFFSET_OFFSET) |
> +                  VC4_HDMI_RM_OFFSET_ONLY);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
> +                  VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
> +                  VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
> +                  VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
> +                  VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
> +                  HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
> +                  VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
> +                  VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
> +
> +       HDMI_WRITE(HDMI_RM_FORMAT,
> +                  HDMI_READ(HDMI_RM_FORMAT) |
> +                  VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
> +                  HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
> +
> +       if (pixel_freq >= 340000000)
> +               word_sel = 3;
> +       else
> +               word_sel = 0;
> +       HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_3,
> +                  VC4_SET_FIELD(phy_get_cp_current(vco_freq),
> +                                VC4_HDMI_TX_PHY_CTL_3_ICP) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
> +                  VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
> +                  VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
> +                  VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
> +
> +       chan0_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
> +                                        pixel_freq);
> +       chan1_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
> +                                        pixel_freq);
> +       chan2_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
> +                                        pixel_freq);
> +       clock_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
> +                                        pixel_freq);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
> +                  VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
> +                  VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
> +                  VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
> +                  VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
> +                  VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
> +                  VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
> +                  VC4_SET_FIELD(clock_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_1,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_1) |
> +                  VC4_SET_FIELD(chan0_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
> +                  VC4_SET_FIELD(chan1_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
> +                  VC4_SET_FIELD(chan2_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
> +                  VC4_SET_FIELD(clock_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_2,
> +                  VC4_SET_FIELD(chan0_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
> +                  VC4_SET_FIELD(chan1_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
> +                  VC4_SET_FIELD(chan2_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
> +                  VC4_SET_FIELD(clock_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
> +                  VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
> +                                VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
> +                  ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
> +                    VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
> +                  VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
> +                  VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
> +}
> +
> +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) {
> +       vc5_hdmi_reset_phy(vc4_hdmi);
> +}
> +
> +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
> +                  ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +}
> +
> +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
> +                  VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +}
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> index bc47cc9bc883..a5f1354e3e06 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
>         VC4_INVALID = 0,
>         VC4_HDMI,
>         VC4_HD,
> +       VC5_CEC,
> +       VC5_CSC,
> +       VC5_DVP,
> +       VC5_PHY,
> +       VC5_RAM,
> +       VC5_RM,
>  };
>
>  enum vc4_hdmi_field {
> @@ -36,6 +42,7 @@ enum vc4_hdmi_field {
>         HDMI_CEC_TX_DATA_2,
>         HDMI_CEC_TX_DATA_3,
>         HDMI_CEC_TX_DATA_4,
> +       HDMI_CLOCK_STOP,
>         HDMI_CORE_REV,
>         HDMI_CRP_CFG,
>         HDMI_CSC_12_11,
> @@ -52,6 +59,7 @@ enum vc4_hdmi_field {
>          */
>         HDMI_CTS_0,
>         HDMI_CTS_1,
> +       HDMI_DVP_CTL,
>         HDMI_FIFO_CTL,
>         HDMI_FRAME_COUNT,
>         HDMI_HORZA,
> @@ -84,10 +92,27 @@ enum vc4_hdmi_field {
>         HDMI_RAM_PACKET_CONFIG,
>         HDMI_RAM_PACKET_START,
>         HDMI_RAM_PACKET_STATUS,
> +       HDMI_RM_CONTROL,
> +       HDMI_RM_FORMAT,
> +       HDMI_RM_OFFSET,
>         HDMI_SCHEDULER_CONTROL,
>         HDMI_SW_RESET_CONTROL,
> +       HDMI_TX_PHY_CHANNEL_SWAP,
> +       HDMI_TX_PHY_CLK_DIV,
>         HDMI_TX_PHY_CTL_0,
> +       HDMI_TX_PHY_CTL_1,
> +       HDMI_TX_PHY_CTL_2,
> +       HDMI_TX_PHY_CTL_3,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
> +       HDMI_TX_PHY_PLL_CFG,
> +       HDMI_TX_PHY_PLL_CTL_0,
> +       HDMI_TX_PHY_PLL_CTL_1,
> +       HDMI_TX_PHY_POWERDOWN_CTL,
>         HDMI_TX_PHY_RESET_CTL,
> +       HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
> +       HDMI_VEC_INTERFACE_XBAR,
>         HDMI_VERTA0,
>         HDMI_VERTA1,
>         HDMI_VERTB0,
> @@ -110,6 +135,12 @@ struct vc4_hdmi_register {
>
>  #define VC4_HD_REG(reg, offset)                _VC4_REG(VC4_HD, reg, offset)
>  #define VC4_HDMI_REG(reg, offset)      _VC4_REG(VC4_HDMI, reg, offset)
> +#define VC5_CEC_REG(reg, offset)       _VC4_REG(VC5_CEC, reg, offset)
> +#define VC5_CSC_REG(reg, offset)       _VC4_REG(VC5_CSC, reg, offset)
> +#define VC5_DVP_REG(reg, offset)       _VC4_REG(VC5_DVP, reg, offset)
> +#define VC5_PHY_REG(reg, offset)       _VC4_REG(VC5_PHY, reg, offset)
> +#define VC5_RAM_REG(reg, offset)       _VC4_REG(VC5_RAM, reg, offset)
> +#define VC5_RM_REG(reg, offset)                _VC4_REG(VC5_RM, reg, offset)
>
>  static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
>         VC4_HD_REG(HDMI_M_CTL, 0x000c),
> @@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
>         VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
>  };
>
> +static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
> +       VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0014),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0044),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),
> +
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
> +
> +       VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
> +       VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
> +
> +       VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
> +       VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
> +       VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
> +       VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
> +       VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
> +
> +       VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
> +       VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
> +       VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
> +
> +       VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
> +
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
> +
> +       VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
> +       VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
> +       VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
> +       VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
> +       VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
> +       VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
> +       VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
> +};
> +
> +static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
> +       VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0034),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0048),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),
> +
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
> +
> +       VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
> +       VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
> +
> +       VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
> +       VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
> +       VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
> +       VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
> +       VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
> +
> +       VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
> +       VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
> +       VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
> +
> +       VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
> +
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
> +
> +       VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
> +       VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
> +       VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
> +       VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
> +       VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
> +       VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
> +       VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
> +};
> +
>  static inline
>  void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
>                                         enum vc4_hdmi_regs reg)
> @@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
>         case VC4_HDMI:
>                 return hdmi->hdmicore_regs;
>
> +       case VC5_CSC:
> +               return hdmi->csc_regs;
> +
> +       case VC5_CEC:
> +               return hdmi->cec_regs;
> +
> +       case VC5_DVP:
> +               return hdmi->dvp_regs;
> +
> +       case VC5_PHY:
> +               return hdmi->phy_regs;
> +
> +       case VC5_RAM:
> +               return hdmi->ram_regs;
> +
> +       case VC5_RM:
> +               return hdmi->rm_regs;
> +
>         default:
>                 return NULL;
>         }
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 30af52b406f1..be2c32a519b3 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -744,6 +744,8 @@
>  # define VC4_HD_CSC_CTL_RGB2YCC                        BIT(1)
>  # define VC4_HD_CSC_CTL_ENABLE                 BIT(0)
>
> +# define VC4_DVP_HT_CLOCK_STOP_PIXEL           BIT(1)
> +
>  /* HVS display list information. */
>  #define HVS_BOOTLOADER_DLIST_END                32
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers
@ 2020-07-28 15:21       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:21 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that the driver is ready for it, let's bring in the HDMI controllers
> variants for the BCM2711.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c      | 278 +++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h      |  36 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c  | 480 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h      |   2 +-
>  5 files changed, 997 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 37463b016b47..d5ba0b1b73a9 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -43,6 +43,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/rational.h>
> +#include <linux/reset.h>
>  #include <sound/dmaengine_pcm.h>
>  #include <sound/pcm_drm_eld.h>
>  #include <sound/pcm_params.h>
> @@ -53,6 +54,31 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
> +#define VC5_HDMI_HORZA_HFP_SHIFT               16
> +#define VC5_HDMI_HORZA_HFP_MASK                        VC4_MASK(28, 16)
> +#define VC5_HDMI_HORZA_VPOS                    BIT(15)
> +#define VC5_HDMI_HORZA_HPOS                    BIT(14)
> +#define VC5_HDMI_HORZA_HAP_SHIFT               0
> +#define VC5_HDMI_HORZA_HAP_MASK                        VC4_MASK(13, 0)
> +
> +#define VC5_HDMI_HORZB_HBP_SHIFT               16
> +#define VC5_HDMI_HORZB_HBP_MASK                        VC4_MASK(26, 16)
> +#define VC5_HDMI_HORZB_HSP_SHIFT               0
> +#define VC5_HDMI_HORZB_HSP_MASK                        VC4_MASK(10, 0)
> +
> +#define VC5_HDMI_VERTA_VSP_SHIFT               24
> +#define VC5_HDMI_VERTA_VSP_MASK                        VC4_MASK(28, 24)
> +#define VC5_HDMI_VERTA_VFP_SHIFT               16
> +#define VC5_HDMI_VERTA_VFP_MASK                        VC4_MASK(22, 16)
> +#define VC5_HDMI_VERTA_VAL_SHIFT               0
> +#define VC5_HDMI_VERTA_VAL_MASK                        VC4_MASK(12, 0)
> +
> +#define VC5_HDMI_VERTB_VSPO_SHIFT              16
> +#define VC5_HDMI_VERTB_VSPO_MASK               VC4_MASK(29, 16)
> +
> +# define VC4_HD_M_SW_RST                       BIT(2)
> +# define VC4_HD_M_ENABLE                       BIT(0)
> +
>  #define CEC_CLOCK_FREQ 40000
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -82,6 +108,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
>         HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
>  }
>
> +static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
> +{
> +       reset_control_reset(vc4_hdmi->reset);
> +
> +       HDMI_WRITE(HDMI_DVP_CTL, 0);
> +
> +       HDMI_WRITE(HDMI_CLOCK_STOP,
> +                  HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
> +}
> +
>  static enum drm_connector_status
>  vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -391,6 +427,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
>         HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
>  }
>
> +static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> +{
> +       u32 csc_ctl;
> +
> +       csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
> +
> +       if (enable) {
> +               /* CEA VICs other than #1 requre limited range RGB
> +                * output unless overridden by an AVI infoframe.
> +                * Apply a colorspace conversion to squash 0-255 down
> +                * to 16-235.  The matrix here is:
> +                *
> +                * [ 0.8594 0      0      16]
> +                * [ 0      0.8594 0      16]
> +                * [ 0      0      0.8594 16]
> +                * [ 0      0      0       1]
> +                * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> +                */
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
> +       } else {
> +               /* Still use the matrix for full range, but make it unity.
> +                * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> +                */
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
> +       }
> +
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> +}
> +
>  static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>                                  struct drm_display_mode *mode)
>  {
> @@ -435,6 +510,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>         HDMI_WRITE(HDMI_VERTB0, vertb_even);
>         HDMI_WRITE(HDMI_VERTB1, vertb);
>  }
> +static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
> +                                struct drm_display_mode *mode)
> +{
> +       bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
> +       bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
> +       bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +       u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
> +       u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
> +                                  VC5_HDMI_VERTA_VSP) |
> +                    VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
> +                                  VC5_HDMI_VERTA_VFP) |
> +                    VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
> +       u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
> +                    VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
> +                                  VC4_HDMI_VERTB_VBP));
> +       u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
> +                         VC4_SET_FIELD(mode->crtc_vtotal -
> +                                       mode->crtc_vsync_end -
> +                                       interlaced,
> +                                       VC4_HDMI_VERTB_VBP));
> +
> +       HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
> +       HDMI_WRITE(HDMI_HORZA,
> +                  (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
> +                  (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
> +                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> +                                VC5_HDMI_HORZA_HAP) |
> +                  VC4_SET_FIELD((mode->hsync_start -
> +                                 mode->hdisplay) * pixel_rep,
> +                                VC5_HDMI_HORZA_HFP));
> +
> +       HDMI_WRITE(HDMI_HORZB,
> +                  VC4_SET_FIELD((mode->htotal -
> +                                 mode->hsync_end) * pixel_rep,
> +                                VC5_HDMI_HORZB_HBP) |
> +                  VC4_SET_FIELD((mode->hsync_end -
> +                                 mode->hsync_start) * pixel_rep,
> +                                VC5_HDMI_HORZB_HSP));
> +
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
> +
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
> +
> +       HDMI_WRITE(HDMI_CLOCK_STOP, 0);
> +}
>
>  static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>  {
> @@ -645,6 +767,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
>         return channel_map;
>  }
>
> +static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
> +{
> +       int i;
> +       u32 channel_map = 0;
> +
> +       for (i = 0; i < 8; i++) {
> +               if (channel_mask & BIT(i))
> +                       channel_map |= i << (4 * i);
> +       }
> +       return channel_map;
> +}
> +
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
>  {
> @@ -1377,6 +1511,98 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>         return 0;
>  }
>
> +static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
> +{
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       struct device *dev = &pdev->dev;
> +       struct resource *res;
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
> +                                              resource_size(res));
> +       if (IS_ERR(vc4_hdmi->hdmicore_regs))
> +               return PTR_ERR(vc4_hdmi->hdmicore_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->hd_regs))
> +               return PTR_ERR(vc4_hdmi->hd_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->cec_regs))
> +               return PTR_ERR(vc4_hdmi->cec_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->csc_regs))
> +               return PTR_ERR(vc4_hdmi->csc_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->dvp_regs))
> +               return PTR_ERR(vc4_hdmi->dvp_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->phy_regs))
> +               return PTR_ERR(vc4_hdmi->phy_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->ram_regs))
> +               return PTR_ERR(vc4_hdmi->ram_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->rm_regs))
> +               return PTR_ERR(vc4_hdmi->rm_regs);
> +
> +       vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
> +       if (IS_ERR(vc4_hdmi->hsm_clock)) {
> +               DRM_ERROR("Failed to get HDMI state machine clock\n");
> +               return PTR_ERR(vc4_hdmi->hsm_clock);
> +       }
> +
> +       vc4_hdmi->audio_clock = devm_clk_get(dev, "clk-108M");
> +       if (IS_ERR(vc4_hdmi->audio_clock)) {
> +               DRM_ERROR("Failed to get 108MHz clock\n");
> +               return PTR_ERR(vc4_hdmi->audio_clock);
> +       }
> +
> +       vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
> +       if (IS_ERR(vc4_hdmi->reset)) {
> +               DRM_ERROR("Failed to get HDMI reset line\n");
> +               return PTR_ERR(vc4_hdmi->reset);
> +       }
> +
> +       return 0;
> +}
> +
>  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  {
>         const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
> @@ -1547,8 +1773,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .channel_map            = vc4_hdmi_channel_map,
>  };
>
> +static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
> +       .debugfs_name           = "hdmi0_regs",
> +       .card_name              = "vc4-hdmi-0",
> +       .max_pixel_clock        = 297000000,
> +       .registers              = vc5_hdmi_hdmi0_fields,
> +       .num_registers          = ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
> +       .phy_lane_mapping       = {
> +               PHY_LANE_0,
> +               PHY_LANE_1,
> +               PHY_LANE_2,
> +               PHY_LANE_CK,
> +       },
> +
> +       .init_resources         = vc5_hdmi_init_resources,
> +       .csc_setup              = vc5_hdmi_csc_setup,
> +       .reset                  = vc5_hdmi_reset,
> +       .set_timings            = vc5_hdmi_set_timings,
> +       .phy_init               = vc5_hdmi_phy_init,
> +       .phy_disable            = vc5_hdmi_phy_disable,
> +       .phy_rng_enable         = vc5_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc5_hdmi_phy_rng_disable,
> +       .channel_map            = vc5_hdmi_channel_map,
> +};
> +
> +static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI1,
> +       .debugfs_name           = "hdmi1_regs",
> +       .card_name              = "vc4-hdmi-1",
> +       .max_pixel_clock        = 297000000,
> +       .registers              = vc5_hdmi_hdmi1_fields,
> +       .num_registers          = ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
> +       .phy_lane_mapping       = {
> +               PHY_LANE_1,
> +               PHY_LANE_0,
> +               PHY_LANE_CK,
> +               PHY_LANE_2,
> +       },
> +
> +       .init_resources         = vc5_hdmi_init_resources,
> +       .csc_setup              = vc5_hdmi_csc_setup,
> +       .reset                  = vc5_hdmi_reset,
> +       .set_timings            = vc5_hdmi_set_timings,
> +       .phy_init               = vc5_hdmi_phy_init,
> +       .phy_disable            = vc5_hdmi_phy_disable,
> +       .phy_rng_enable         = vc5_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc5_hdmi_phy_rng_disable,
> +       .channel_map            = vc5_hdmi_channel_map,
> +};
> +
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
>         { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
> +       { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
> +       { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
>         {}
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 34138e0dd4a6..0806c6d9f24e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -26,6 +26,13 @@ struct drm_display_mode;
>  struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
> +enum vc4_hdmi_phy_channel {
> +       PHY_LANE_0 = 0,
> +       PHY_LANE_1,
> +       PHY_LANE_2,
> +       PHY_LANE_CK,
> +};
> +
>  struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
> @@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
>         /* Number of registers on that variant */
>         unsigned int num_registers;
>
> +       /* BCM2711 Only.
> +        * The variants don't map the lane in the same order in the
> +        * PHY, so this is an array mapping the HDMI channel (index)
> +        * to the PHY lane (value).
> +        */
> +       enum vc4_hdmi_phy_channel phy_lane_mapping[4];
> +
>         /* Callback to get the resources (memory region, interrupts,
>          * clocks, etc) for that variant.
>          */
> @@ -108,6 +122,20 @@ struct vc4_hdmi {
>         struct i2c_adapter *ddc;
>         void __iomem *hdmicore_regs;
>         void __iomem *hd_regs;
> +
> +       /* VC5 Only */
> +       void __iomem *cec_regs;
> +       /* VC5 Only */
> +       void __iomem *csc_regs;
> +       /* VC5 Only */
> +       void __iomem *dvp_regs;
> +       /* VC5 Only */
> +       void __iomem *phy_regs;
> +       /* VC5 Only */
> +       void __iomem *ram_regs;
> +       /* VC5 Only */
> +       void __iomem *rm_regs;
> +
>         int hpd_gpio;
>         bool hpd_active_low;
>
> @@ -120,6 +148,8 @@ struct vc4_hdmi {
>         struct clk *hsm_clock;
>         struct clk *audio_clock;
>
> +       struct reset_control *reset;
> +
>         struct debugfs_regset32 hdmi_regset;
>         struct debugfs_regset32 hd_regset;
>  };
> @@ -144,4 +174,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>  void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>  void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +                      struct drm_display_mode *mode);
> +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
> +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
> +
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 93287e24d7d1..4d36f8c33401 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -10,6 +10,123 @@
>  #include "vc4_regs.h"
>  #include "vc4_hdmi_regs.h"
>
> +#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB   BIT(5)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB        BIT(4)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET  BIT(3)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET   BIT(2)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET   BIT(1)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET   BIT(0)
> +
> +#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN     BIT(4)
> +
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT    29
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK     VC4_MASK(31, 29)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT   24
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK    VC4_MASK(28, 24)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT    21
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK     VC4_MASK(23, 21)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT   16
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK    VC4_MASK(20, 16)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT    13
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK     VC4_MASK(15, 13)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT   8
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK    VC4_MASK(12, 8)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT   5
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK    VC4_MASK(7, 5)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT  0
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK   VC4_MASK(4, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT      15
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK       VC4_MASK(19, 15)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT      10
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK       VC4_MASK(14, 10)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT      5
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK       VC4_MASK(9, 5)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT         0
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK          VC4_MASK(4, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT           16
> +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK            VC4_MASK(19, 16)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT  12
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK   VC4_MASK(15, 12)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT  8
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK   VC4_MASK(11, 8)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT  4
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK   VC4_MASK(7, 4)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT     0
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK      VC4_MASK(3, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT                 17
> +#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK                  VC4_MASK(19, 17)
> +#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT                 12
> +#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK                  VC4_MASK(16, 12)
> +#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT                        10
> +#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK                 VC4_MASK(11, 10)
> +#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT                 8
> +#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK                  VC4_MASK(9, 8)
> +#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT                 6
> +#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK                  VC4_MASK(7, 6)
> +#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT                        0
> +#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK                 VC4_MASK(5, 0)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE          BIT(13)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN          BIT(12)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW       BIT(11)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH      BIT(10)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT                9
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK         VC4_MASK(9, 9)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2          BIT(8)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2                BIT(7)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN          BIT(6)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK          BIT(5)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT                    16
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK                     VC4_MASK(27, 16)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT     14
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK      VC4_MASK(15, 14)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE          BIT(13)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT           11
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK            VC4_MASK(12, 11)
> +
> +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT              8
> +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK               VC4_MASK(15, 8)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT             0
> +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK              VC4_MASK(3, 0)
> +
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK VC4_MASK(13, 12)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT        12
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK  VC4_MASK(9, 8)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT 8
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK  VC4_MASK(5, 4)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT 4
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK  VC4_MASK(1, 0)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT 0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK                VC4_MASK(27, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT       0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK                VC4_MASK(27, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT       0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK VC4_MASK(31, 16)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT        16
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK   VC4_MASK(15, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT  0
> +
> +#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS         BIT(19)
> +#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR         BIT(17)
> +#define VC4_HDMI_RM_CONTROL_FREE_RUN                   BIT(4)
> +
> +#define VC4_HDMI_RM_OFFSET_ONLY                                BIT(31)
> +#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT                        0
> +#define VC4_HDMI_RM_OFFSET_OFFSET_MASK                 VC4_MASK(30, 0)
> +
> +#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT                 24
> +#define VC4_HDMI_RM_FORMAT_SHIFT_MASK                  VC4_MASK(25, 24)
> +
> +#define OSCILLATOR_FREQUENCY   54000000
> +
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
>  {
>         /* PHY should be in reset, like
> @@ -38,3 +155,366 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
>                    HDMI_READ(HDMI_TX_PHY_CTL_0) |
>                    VC4_HDMI_TX_PHY_RNG_PWRDN);
>  }
> +
> +static unsigned long long
> +phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
> +{
> +       unsigned long long vco_freq = clock;
> +       unsigned int _vco_div = 0;
> +       unsigned int _vco_sel = 0;
> +
> +       while (vco_freq < 3000000000ULL) {
> +               _vco_div++;
> +               vco_freq = clock * _vco_div * 10;
> +       }
> +
> +       if (vco_freq > 4500000000ULL)
> +               _vco_sel = 1;
> +
> +       *vco_sel = _vco_sel;
> +       *vco_div = _vco_div;
> +
> +       return vco_freq;
> +}
> +
> +static u8 phy_get_cp_current(unsigned long vco_freq)
> +{
> +       if (vco_freq < 3700000000ULL)
> +               return 0x1c;
> +
> +       return 0x18;
> +}
> +
> +static u32 phy_get_rm_offset(unsigned long long vco_freq)
> +{
> +       unsigned long long fref = OSCILLATOR_FREQUENCY;
> +       u64 offset = 0;
> +
> +       /* RM offset is stored as 9.22 format */
> +       offset = vco_freq * 2;
> +       offset = offset << 22;
> +       do_div(offset, fref);
> +       offset >>= 2;
> +
> +       return offset;
> +}
> +
> +static u8 phy_get_vco_gain(unsigned long long vco_freq)
> +{
> +       if (vco_freq < 3350000000ULL)
> +               return 0xf;
> +
> +       if (vco_freq < 3700000000ULL)
> +               return 0xc;
> +
> +       if (vco_freq < 4050000000ULL)
> +               return 0x6;
> +
> +       if (vco_freq < 4800000000ULL)
> +               return 0x5;
> +
> +       if (vco_freq < 5200000000ULL)
> +               return 0x7;
> +
> +       return 0x2;
> +}
> +
> +struct phy_lane_settings {
> +       struct {
> +               u8 preemphasis;
> +               u8 main_driver;
> +       } amplitude;
> +
> +       u8 res_sel_data;
> +       u8 term_res_sel_data;
> +};
> +
> +struct phy_settings {
> +       unsigned long long min_rate;
> +       unsigned long long max_rate;
> +       struct phy_lane_settings channel[3];
> +       struct phy_lane_settings clock;
> +};
> +
> +static const struct phy_settings vc5_hdmi_phy_settings[] = {
> +       {
> +               0, 50000000,
> +               {
> +                       {{0x0, 0x0A}, 0x12, 0x0},
> +                       {{0x0, 0x0A}, 0x12, 0x0},
> +                       {{0x0, 0x0A}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0A}, 0x18, 0x0},
> +       },
> +       {
> +               50000001, 75000000,
> +               {
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               75000001,   165000000,
> +               {
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               165000001,  250000000,
> +               {
> +                       {{0x0, 0x0F}, 0x12, 0x1},
> +                       {{0x0, 0x0F}, 0x12, 0x1},
> +                       {{0x0, 0x0F}, 0x12, 0x1}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               250000001,  340000000,
> +               {
> +                       {{0x2, 0x0D}, 0x12, 0x1},
> +                       {{0x2, 0x0D}, 0x12, 0x1},
> +                       {{0x2, 0x0D}, 0x12, 0x1}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0xF},
> +       },
> +       {
> +               340000001,  450000000,
> +               {
> +                       {{0x0, 0x1B}, 0x12, 0xF},
> +                       {{0x0, 0x1B}, 0x12, 0xF},
> +                       {{0x0, 0x1B}, 0x12, 0xF}
> +               },
> +               {{0x0, 0x0A}, 0x12, 0xF},
> +       },
> +       {
> +               450000001,  600000000,
> +               {
> +                       {{0x0, 0x1C}, 0x12, 0xF},
> +                       {{0x0, 0x1C}, 0x12, 0xF},
> +                       {{0x0, 0x1C}, 0x12, 0xF}
> +               },
> +               {{0x0, 0x0B}, 0x13, 0xF},
> +       },
> +};
> +
> +static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
> +{
> +       unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
> +       unsigned int i;
> +
> +       for (i = 0; i < count; i++) {
> +               const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
> +
> +               if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
> +                       return s;
> +       }
> +
> +       /*
> +        * If the pixel clock exceeds our max setting, try the max
> +        * setting anyway.
> +        */
> +       return &vc5_hdmi_phy_settings[count - 1];
> +}
> +
> +static const struct phy_lane_settings *
> +phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
> +                        unsigned long long tmds_rate)
> +{
> +       const struct phy_settings *settings = phy_get_settings(tmds_rate);
> +
> +       if (chan == PHY_LANE_CK)
> +               return &settings->clock;
> +
> +       return &settings->channel[chan];
> +}
> +
> +static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
> +}
> +
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +{
> +       const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
> +       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> +       unsigned long long pixel_freq = mode->clock * 1000;
> +       unsigned long long vco_freq;
> +       unsigned char word_sel;
> +       u8 vco_sel, vco_div;
> +
> +       vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
> +
> +       vc5_hdmi_reset_phy(vc4_hdmi);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
> +
> +       HDMI_WRITE(HDMI_RM_CONTROL,
> +                  HDMI_READ(HDMI_RM_CONTROL) |
> +                  VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
> +                  VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
> +                  VC4_HDMI_RM_CONTROL_FREE_RUN);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
> +                  (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
> +                   ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
> +                  VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
> +                  (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
> +                   ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
> +                  VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
> +
> +       HDMI_WRITE(HDMI_RM_OFFSET,
> +                  VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
> +                                VC4_HDMI_RM_OFFSET_OFFSET) |
> +                  VC4_HDMI_RM_OFFSET_ONLY);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
> +                  VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
> +                  VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
> +                  VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
> +                  VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
> +                  HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
> +                  VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
> +                  VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
> +
> +       HDMI_WRITE(HDMI_RM_FORMAT,
> +                  HDMI_READ(HDMI_RM_FORMAT) |
> +                  VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
> +                  HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
> +
> +       if (pixel_freq >= 340000000)
> +               word_sel = 3;
> +       else
> +               word_sel = 0;
> +       HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_3,
> +                  VC4_SET_FIELD(phy_get_cp_current(vco_freq),
> +                                VC4_HDMI_TX_PHY_CTL_3_ICP) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
> +                  VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
> +                  VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
> +                  VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
> +
> +       chan0_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
> +                                        pixel_freq);
> +       chan1_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
> +                                        pixel_freq);
> +       chan2_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
> +                                        pixel_freq);
> +       clock_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
> +                                        pixel_freq);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
> +                  VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
> +                  VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
> +                  VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
> +                  VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
> +                  VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
> +                  VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
> +                  VC4_SET_FIELD(clock_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_1,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_1) |
> +                  VC4_SET_FIELD(chan0_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
> +                  VC4_SET_FIELD(chan1_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
> +                  VC4_SET_FIELD(chan2_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
> +                  VC4_SET_FIELD(clock_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_2,
> +                  VC4_SET_FIELD(chan0_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
> +                  VC4_SET_FIELD(chan1_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
> +                  VC4_SET_FIELD(chan2_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
> +                  VC4_SET_FIELD(clock_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
> +                  VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
> +                                VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
> +                  ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
> +                    VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
> +                  VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
> +                  VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
> +}
> +
> +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) {
> +       vc5_hdmi_reset_phy(vc4_hdmi);
> +}
> +
> +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
> +                  ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +}
> +
> +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
> +                  VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +}
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> index bc47cc9bc883..a5f1354e3e06 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
>         VC4_INVALID = 0,
>         VC4_HDMI,
>         VC4_HD,
> +       VC5_CEC,
> +       VC5_CSC,
> +       VC5_DVP,
> +       VC5_PHY,
> +       VC5_RAM,
> +       VC5_RM,
>  };
>
>  enum vc4_hdmi_field {
> @@ -36,6 +42,7 @@ enum vc4_hdmi_field {
>         HDMI_CEC_TX_DATA_2,
>         HDMI_CEC_TX_DATA_3,
>         HDMI_CEC_TX_DATA_4,
> +       HDMI_CLOCK_STOP,
>         HDMI_CORE_REV,
>         HDMI_CRP_CFG,
>         HDMI_CSC_12_11,
> @@ -52,6 +59,7 @@ enum vc4_hdmi_field {
>          */
>         HDMI_CTS_0,
>         HDMI_CTS_1,
> +       HDMI_DVP_CTL,
>         HDMI_FIFO_CTL,
>         HDMI_FRAME_COUNT,
>         HDMI_HORZA,
> @@ -84,10 +92,27 @@ enum vc4_hdmi_field {
>         HDMI_RAM_PACKET_CONFIG,
>         HDMI_RAM_PACKET_START,
>         HDMI_RAM_PACKET_STATUS,
> +       HDMI_RM_CONTROL,
> +       HDMI_RM_FORMAT,
> +       HDMI_RM_OFFSET,
>         HDMI_SCHEDULER_CONTROL,
>         HDMI_SW_RESET_CONTROL,
> +       HDMI_TX_PHY_CHANNEL_SWAP,
> +       HDMI_TX_PHY_CLK_DIV,
>         HDMI_TX_PHY_CTL_0,
> +       HDMI_TX_PHY_CTL_1,
> +       HDMI_TX_PHY_CTL_2,
> +       HDMI_TX_PHY_CTL_3,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
> +       HDMI_TX_PHY_PLL_CFG,
> +       HDMI_TX_PHY_PLL_CTL_0,
> +       HDMI_TX_PHY_PLL_CTL_1,
> +       HDMI_TX_PHY_POWERDOWN_CTL,
>         HDMI_TX_PHY_RESET_CTL,
> +       HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
> +       HDMI_VEC_INTERFACE_XBAR,
>         HDMI_VERTA0,
>         HDMI_VERTA1,
>         HDMI_VERTB0,
> @@ -110,6 +135,12 @@ struct vc4_hdmi_register {
>
>  #define VC4_HD_REG(reg, offset)                _VC4_REG(VC4_HD, reg, offset)
>  #define VC4_HDMI_REG(reg, offset)      _VC4_REG(VC4_HDMI, reg, offset)
> +#define VC5_CEC_REG(reg, offset)       _VC4_REG(VC5_CEC, reg, offset)
> +#define VC5_CSC_REG(reg, offset)       _VC4_REG(VC5_CSC, reg, offset)
> +#define VC5_DVP_REG(reg, offset)       _VC4_REG(VC5_DVP, reg, offset)
> +#define VC5_PHY_REG(reg, offset)       _VC4_REG(VC5_PHY, reg, offset)
> +#define VC5_RAM_REG(reg, offset)       _VC4_REG(VC5_RAM, reg, offset)
> +#define VC5_RM_REG(reg, offset)                _VC4_REG(VC5_RM, reg, offset)
>
>  static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
>         VC4_HD_REG(HDMI_M_CTL, 0x000c),
> @@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
>         VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
>  };
>
> +static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
> +       VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0014),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0044),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),
> +
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
> +
> +       VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
> +       VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
> +
> +       VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
> +       VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
> +       VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
> +       VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
> +       VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
> +
> +       VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
> +       VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
> +       VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
> +
> +       VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
> +
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
> +
> +       VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
> +       VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
> +       VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
> +       VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
> +       VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
> +       VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
> +       VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
> +};
> +
> +static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
> +       VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0034),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0048),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),
> +
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
> +
> +       VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
> +       VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
> +
> +       VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
> +       VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
> +       VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
> +       VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
> +       VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
> +
> +       VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
> +       VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
> +       VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
> +
> +       VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
> +
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
> +
> +       VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
> +       VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
> +       VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
> +       VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
> +       VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
> +       VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
> +       VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
> +};
> +
>  static inline
>  void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
>                                         enum vc4_hdmi_regs reg)
> @@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
>         case VC4_HDMI:
>                 return hdmi->hdmicore_regs;
>
> +       case VC5_CSC:
> +               return hdmi->csc_regs;
> +
> +       case VC5_CEC:
> +               return hdmi->cec_regs;
> +
> +       case VC5_DVP:
> +               return hdmi->dvp_regs;
> +
> +       case VC5_PHY:
> +               return hdmi->phy_regs;
> +
> +       case VC5_RAM:
> +               return hdmi->ram_regs;
> +
> +       case VC5_RM:
> +               return hdmi->rm_regs;
> +
>         default:
>                 return NULL;
>         }
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 30af52b406f1..be2c32a519b3 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -744,6 +744,8 @@
>  # define VC4_HD_CSC_CTL_RGB2YCC                        BIT(1)
>  # define VC4_HD_CSC_CTL_ENABLE                 BIT(0)
>
> +# define VC4_DVP_HT_CLOCK_STOP_PIXEL           BIT(1)
> +
>  /* HVS display list information. */
>  #define HVS_BOOTLOADER_DLIST_END                32
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers
@ 2020-07-28 15:21       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:21 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that the driver is ready for it, let's bring in the HDMI controllers
> variants for the BCM2711.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c      | 278 +++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi.h      |  36 ++-
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c  | 480 +++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 201 ++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h      |   2 +-
>  5 files changed, 997 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 37463b016b47..d5ba0b1b73a9 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -43,6 +43,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/rational.h>
> +#include <linux/reset.h>
>  #include <sound/dmaengine_pcm.h>
>  #include <sound/pcm_drm_eld.h>
>  #include <sound/pcm_params.h>
> @@ -53,6 +54,31 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>
> +#define VC5_HDMI_HORZA_HFP_SHIFT               16
> +#define VC5_HDMI_HORZA_HFP_MASK                        VC4_MASK(28, 16)
> +#define VC5_HDMI_HORZA_VPOS                    BIT(15)
> +#define VC5_HDMI_HORZA_HPOS                    BIT(14)
> +#define VC5_HDMI_HORZA_HAP_SHIFT               0
> +#define VC5_HDMI_HORZA_HAP_MASK                        VC4_MASK(13, 0)
> +
> +#define VC5_HDMI_HORZB_HBP_SHIFT               16
> +#define VC5_HDMI_HORZB_HBP_MASK                        VC4_MASK(26, 16)
> +#define VC5_HDMI_HORZB_HSP_SHIFT               0
> +#define VC5_HDMI_HORZB_HSP_MASK                        VC4_MASK(10, 0)
> +
> +#define VC5_HDMI_VERTA_VSP_SHIFT               24
> +#define VC5_HDMI_VERTA_VSP_MASK                        VC4_MASK(28, 24)
> +#define VC5_HDMI_VERTA_VFP_SHIFT               16
> +#define VC5_HDMI_VERTA_VFP_MASK                        VC4_MASK(22, 16)
> +#define VC5_HDMI_VERTA_VAL_SHIFT               0
> +#define VC5_HDMI_VERTA_VAL_MASK                        VC4_MASK(12, 0)
> +
> +#define VC5_HDMI_VERTB_VSPO_SHIFT              16
> +#define VC5_HDMI_VERTB_VSPO_MASK               VC4_MASK(29, 16)
> +
> +# define VC4_HD_M_SW_RST                       BIT(2)
> +# define VC4_HD_M_ENABLE                       BIT(0)
> +
>  #define CEC_CLOCK_FREQ 40000
>
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -82,6 +108,16 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
>         HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
>  }
>
> +static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
> +{
> +       reset_control_reset(vc4_hdmi->reset);
> +
> +       HDMI_WRITE(HDMI_DVP_CTL, 0);
> +
> +       HDMI_WRITE(HDMI_CLOCK_STOP,
> +                  HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
> +}
> +
>  static enum drm_connector_status
>  vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -391,6 +427,45 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
>         HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
>  }
>
> +static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable)
> +{
> +       u32 csc_ctl;
> +
> +       csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */
> +
> +       if (enable) {
> +               /* CEA VICs other than #1 requre limited range RGB
> +                * output unless overridden by an AVI infoframe.
> +                * Apply a colorspace conversion to squash 0-255 down
> +                * to 16-235.  The matrix here is:
> +                *
> +                * [ 0.8594 0      0      16]
> +                * [ 0      0.8594 0      16]
> +                * [ 0      0      0.8594 16]
> +                * [ 0      0      0       1]
> +                * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> +                */
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80);
> +       } else {
> +               /* Still use the matrix for full range, but make it unity.
> +                * Matrix is signed 2p13 fixed point, with signed 9p6 offsets
> +                */
> +               HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000);
> +               HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000);
> +               HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000);
> +       }
> +
> +       HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
> +}
> +
>  static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>                                  struct drm_display_mode *mode)
>  {
> @@ -435,6 +510,53 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
>         HDMI_WRITE(HDMI_VERTB0, vertb_even);
>         HDMI_WRITE(HDMI_VERTB1, vertb);
>  }
> +static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
> +                                struct drm_display_mode *mode)
> +{
> +       bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
> +       bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
> +       bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +       u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1;
> +       u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start,
> +                                  VC5_HDMI_VERTA_VSP) |
> +                    VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay,
> +                                  VC5_HDMI_VERTA_VFP) |
> +                    VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL));
> +       u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
> +                    VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end,
> +                                  VC4_HDMI_VERTB_VBP));
> +       u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) |
> +                         VC4_SET_FIELD(mode->crtc_vtotal -
> +                                       mode->crtc_vsync_end -
> +                                       interlaced,
> +                                       VC4_HDMI_VERTB_VBP));
> +
> +       HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021);
> +       HDMI_WRITE(HDMI_HORZA,
> +                  (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) |
> +                  (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) |
> +                  VC4_SET_FIELD(mode->hdisplay * pixel_rep,
> +                                VC5_HDMI_HORZA_HAP) |
> +                  VC4_SET_FIELD((mode->hsync_start -
> +                                 mode->hdisplay) * pixel_rep,
> +                                VC5_HDMI_HORZA_HFP));
> +
> +       HDMI_WRITE(HDMI_HORZB,
> +                  VC4_SET_FIELD((mode->htotal -
> +                                 mode->hsync_end) * pixel_rep,
> +                                VC5_HDMI_HORZB_HBP) |
> +                  VC4_SET_FIELD((mode->hsync_end -
> +                                 mode->hsync_start) * pixel_rep,
> +                                VC5_HDMI_HORZB_HSP));
> +
> +       HDMI_WRITE(HDMI_VERTA0, verta);
> +       HDMI_WRITE(HDMI_VERTA1, verta);
> +
> +       HDMI_WRITE(HDMI_VERTB0, vertb_even);
> +       HDMI_WRITE(HDMI_VERTB1, vertb);
> +
> +       HDMI_WRITE(HDMI_CLOCK_STOP, 0);
> +}
>
>  static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
>  {
> @@ -645,6 +767,18 @@ static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
>         return channel_map;
>  }
>
> +static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
> +{
> +       int i;
> +       u32 channel_map = 0;
> +
> +       for (i = 0; i < 8; i++) {
> +               if (channel_mask & BIT(i))
> +                       channel_map |= i << (4 * i);
> +       }
> +       return channel_map;
> +}
> +
>  /* HDMI audio codec callbacks */
>  static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
>  {
> @@ -1377,6 +1511,98 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
>         return 0;
>  }
>
> +static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
> +{
> +       struct platform_device *pdev = vc4_hdmi->pdev;
> +       struct device *dev = &pdev->dev;
> +       struct resource *res;
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start,
> +                                              resource_size(res));
> +       if (IS_ERR(vc4_hdmi->hdmicore_regs))
> +               return PTR_ERR(vc4_hdmi->hdmicore_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->hd_regs))
> +               return PTR_ERR(vc4_hdmi->hd_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->cec_regs))
> +               return PTR_ERR(vc4_hdmi->cec_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->csc_regs))
> +               return PTR_ERR(vc4_hdmi->csc_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->dvp_regs))
> +               return PTR_ERR(vc4_hdmi->dvp_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->phy_regs))
> +               return PTR_ERR(vc4_hdmi->phy_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->ram_regs))
> +               return PTR_ERR(vc4_hdmi->ram_regs);
> +
> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm");
> +       if (!res)
> +               return -ENODEV;
> +
> +       vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res));
> +       if (IS_ERR(vc4_hdmi->rm_regs))
> +               return PTR_ERR(vc4_hdmi->rm_regs);
> +
> +       vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi");
> +       if (IS_ERR(vc4_hdmi->hsm_clock)) {
> +               DRM_ERROR("Failed to get HDMI state machine clock\n");
> +               return PTR_ERR(vc4_hdmi->hsm_clock);
> +       }
> +
> +       vc4_hdmi->audio_clock = devm_clk_get(dev, "clk-108M");
> +       if (IS_ERR(vc4_hdmi->audio_clock)) {
> +               DRM_ERROR("Failed to get 108MHz clock\n");
> +               return PTR_ERR(vc4_hdmi->audio_clock);
> +       }
> +
> +       vc4_hdmi->reset = devm_reset_control_get(dev, NULL);
> +       if (IS_ERR(vc4_hdmi->reset)) {
> +               DRM_ERROR("Failed to get HDMI reset line\n");
> +               return PTR_ERR(vc4_hdmi->reset);
> +       }
> +
> +       return 0;
> +}
> +
>  static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  {
>         const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
> @@ -1547,8 +1773,60 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
>         .channel_map            = vc4_hdmi_channel_map,
>  };
>
> +static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI0,
> +       .debugfs_name           = "hdmi0_regs",
> +       .card_name              = "vc4-hdmi-0",
> +       .max_pixel_clock        = 297000000,
> +       .registers              = vc5_hdmi_hdmi0_fields,
> +       .num_registers          = ARRAY_SIZE(vc5_hdmi_hdmi0_fields),
> +       .phy_lane_mapping       = {
> +               PHY_LANE_0,
> +               PHY_LANE_1,
> +               PHY_LANE_2,
> +               PHY_LANE_CK,
> +       },
> +
> +       .init_resources         = vc5_hdmi_init_resources,
> +       .csc_setup              = vc5_hdmi_csc_setup,
> +       .reset                  = vc5_hdmi_reset,
> +       .set_timings            = vc5_hdmi_set_timings,
> +       .phy_init               = vc5_hdmi_phy_init,
> +       .phy_disable            = vc5_hdmi_phy_disable,
> +       .phy_rng_enable         = vc5_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc5_hdmi_phy_rng_disable,
> +       .channel_map            = vc5_hdmi_channel_map,
> +};
> +
> +static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
> +       .encoder_type           = VC4_ENCODER_TYPE_HDMI1,
> +       .debugfs_name           = "hdmi1_regs",
> +       .card_name              = "vc4-hdmi-1",
> +       .max_pixel_clock        = 297000000,
> +       .registers              = vc5_hdmi_hdmi1_fields,
> +       .num_registers          = ARRAY_SIZE(vc5_hdmi_hdmi1_fields),
> +       .phy_lane_mapping       = {
> +               PHY_LANE_1,
> +               PHY_LANE_0,
> +               PHY_LANE_CK,
> +               PHY_LANE_2,
> +       },
> +
> +       .init_resources         = vc5_hdmi_init_resources,
> +       .csc_setup              = vc5_hdmi_csc_setup,
> +       .reset                  = vc5_hdmi_reset,
> +       .set_timings            = vc5_hdmi_set_timings,
> +       .phy_init               = vc5_hdmi_phy_init,
> +       .phy_disable            = vc5_hdmi_phy_disable,
> +       .phy_rng_enable         = vc5_hdmi_phy_rng_enable,
> +       .phy_rng_disable        = vc5_hdmi_phy_rng_disable,
> +       .channel_map            = vc5_hdmi_channel_map,
> +};
> +
>  static const struct of_device_id vc4_hdmi_dt_match[] = {
>         { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant },
> +       { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant },
> +       { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant },
>         {}
>  };
>
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 34138e0dd4a6..0806c6d9f24e 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -26,6 +26,13 @@ struct drm_display_mode;
>  struct vc4_hdmi;
>  struct vc4_hdmi_register;
>
> +enum vc4_hdmi_phy_channel {
> +       PHY_LANE_0 = 0,
> +       PHY_LANE_1,
> +       PHY_LANE_2,
> +       PHY_LANE_CK,
> +};
> +
>  struct vc4_hdmi_variant {
>         /* Encoder Type for that controller */
>         enum vc4_encoder_type encoder_type;
> @@ -48,6 +55,13 @@ struct vc4_hdmi_variant {
>         /* Number of registers on that variant */
>         unsigned int num_registers;
>
> +       /* BCM2711 Only.
> +        * The variants don't map the lane in the same order in the
> +        * PHY, so this is an array mapping the HDMI channel (index)
> +        * to the PHY lane (value).
> +        */
> +       enum vc4_hdmi_phy_channel phy_lane_mapping[4];
> +
>         /* Callback to get the resources (memory region, interrupts,
>          * clocks, etc) for that variant.
>          */
> @@ -108,6 +122,20 @@ struct vc4_hdmi {
>         struct i2c_adapter *ddc;
>         void __iomem *hdmicore_regs;
>         void __iomem *hd_regs;
> +
> +       /* VC5 Only */
> +       void __iomem *cec_regs;
> +       /* VC5 Only */
> +       void __iomem *csc_regs;
> +       /* VC5 Only */
> +       void __iomem *dvp_regs;
> +       /* VC5 Only */
> +       void __iomem *phy_regs;
> +       /* VC5 Only */
> +       void __iomem *ram_regs;
> +       /* VC5 Only */
> +       void __iomem *rm_regs;
> +
>         int hpd_gpio;
>         bool hpd_active_low;
>
> @@ -120,6 +148,8 @@ struct vc4_hdmi {
>         struct clk *hsm_clock;
>         struct clk *audio_clock;
>
> +       struct reset_control *reset;
> +
>         struct debugfs_regset32 hdmi_regset;
>         struct debugfs_regset32 hd_regset;
>  };
> @@ -144,4 +174,10 @@ void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
>  void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
>  void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
>
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi,
> +                      struct drm_display_mode *mode);
> +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi);
> +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi);
> +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi);
> +
>  #endif /* _VC4_HDMI_H_ */
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> index 93287e24d7d1..4d36f8c33401 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c
> @@ -10,6 +10,123 @@
>  #include "vc4_regs.h"
>  #include "vc4_hdmi_regs.h"
>
> +#define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB   BIT(5)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB        BIT(4)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET  BIT(3)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET   BIT(2)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET   BIT(1)
> +#define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET   BIT(0)
> +
> +#define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN     BIT(4)
> +
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT    29
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK     VC4_MASK(31, 29)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT   24
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK    VC4_MASK(28, 24)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT    21
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK     VC4_MASK(23, 21)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT   16
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK    VC4_MASK(20, 16)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT    13
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK     VC4_MASK(15, 13)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT   8
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK    VC4_MASK(12, 8)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT   5
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK    VC4_MASK(7, 5)
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT  0
> +#define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK   VC4_MASK(4, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT      15
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK       VC4_MASK(19, 15)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT      10
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK       VC4_MASK(14, 10)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT      5
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK       VC4_MASK(9, 5)
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT         0
> +#define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK          VC4_MASK(4, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT           16
> +#define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK            VC4_MASK(19, 16)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT  12
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK   VC4_MASK(15, 12)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT  8
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK   VC4_MASK(11, 8)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT  4
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK   VC4_MASK(7, 4)
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT     0
> +#define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK      VC4_MASK(3, 0)
> +
> +#define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT                 17
> +#define VC4_HDMI_TX_PHY_CTL_3_RP_MASK                  VC4_MASK(19, 17)
> +#define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT                 12
> +#define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK                  VC4_MASK(16, 12)
> +#define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT                        10
> +#define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK                 VC4_MASK(11, 10)
> +#define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT                 8
> +#define VC4_HDMI_TX_PHY_CTL_3_CP_MASK                  VC4_MASK(9, 8)
> +#define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT                 6
> +#define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK                  VC4_MASK(7, 6)
> +#define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT                        0
> +#define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK                 VC4_MASK(5, 0)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE          BIT(13)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN          BIT(12)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW       BIT(11)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH      BIT(10)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT                9
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK         VC4_MASK(9, 9)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2          BIT(8)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2                BIT(7)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN          BIT(6)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK          BIT(5)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT                    16
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK                     VC4_MASK(27, 16)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT     14
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK      VC4_MASK(15, 14)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE          BIT(13)
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT           11
> +#define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK            VC4_MASK(12, 11)
> +
> +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT              8
> +#define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK               VC4_MASK(15, 8)
> +
> +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT             0
> +#define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK              VC4_MASK(3, 0)
> +
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK VC4_MASK(13, 12)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT        12
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK  VC4_MASK(9, 8)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT 8
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK  VC4_MASK(5, 4)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT 4
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK  VC4_MASK(1, 0)
> +#define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT 0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK                VC4_MASK(27, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT       0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK                VC4_MASK(27, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT       0
> +
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK VC4_MASK(31, 16)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT        16
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK   VC4_MASK(15, 0)
> +#define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT  0
> +
> +#define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS         BIT(19)
> +#define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR         BIT(17)
> +#define VC4_HDMI_RM_CONTROL_FREE_RUN                   BIT(4)
> +
> +#define VC4_HDMI_RM_OFFSET_ONLY                                BIT(31)
> +#define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT                        0
> +#define VC4_HDMI_RM_OFFSET_OFFSET_MASK                 VC4_MASK(30, 0)
> +
> +#define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT                 24
> +#define VC4_HDMI_RM_FORMAT_SHIFT_MASK                  VC4_MASK(25, 24)
> +
> +#define OSCILLATOR_FREQUENCY   54000000
> +
>  void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
>  {
>         /* PHY should be in reset, like
> @@ -38,3 +155,366 @@ void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
>                    HDMI_READ(HDMI_TX_PHY_CTL_0) |
>                    VC4_HDMI_TX_PHY_RNG_PWRDN);
>  }
> +
> +static unsigned long long
> +phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div)
> +{
> +       unsigned long long vco_freq = clock;
> +       unsigned int _vco_div = 0;
> +       unsigned int _vco_sel = 0;
> +
> +       while (vco_freq < 3000000000ULL) {
> +               _vco_div++;
> +               vco_freq = clock * _vco_div * 10;
> +       }
> +
> +       if (vco_freq > 4500000000ULL)
> +               _vco_sel = 1;
> +
> +       *vco_sel = _vco_sel;
> +       *vco_div = _vco_div;
> +
> +       return vco_freq;
> +}
> +
> +static u8 phy_get_cp_current(unsigned long vco_freq)
> +{
> +       if (vco_freq < 3700000000ULL)
> +               return 0x1c;
> +
> +       return 0x18;
> +}
> +
> +static u32 phy_get_rm_offset(unsigned long long vco_freq)
> +{
> +       unsigned long long fref = OSCILLATOR_FREQUENCY;
> +       u64 offset = 0;
> +
> +       /* RM offset is stored as 9.22 format */
> +       offset = vco_freq * 2;
> +       offset = offset << 22;
> +       do_div(offset, fref);
> +       offset >>= 2;
> +
> +       return offset;
> +}
> +
> +static u8 phy_get_vco_gain(unsigned long long vco_freq)
> +{
> +       if (vco_freq < 3350000000ULL)
> +               return 0xf;
> +
> +       if (vco_freq < 3700000000ULL)
> +               return 0xc;
> +
> +       if (vco_freq < 4050000000ULL)
> +               return 0x6;
> +
> +       if (vco_freq < 4800000000ULL)
> +               return 0x5;
> +
> +       if (vco_freq < 5200000000ULL)
> +               return 0x7;
> +
> +       return 0x2;
> +}
> +
> +struct phy_lane_settings {
> +       struct {
> +               u8 preemphasis;
> +               u8 main_driver;
> +       } amplitude;
> +
> +       u8 res_sel_data;
> +       u8 term_res_sel_data;
> +};
> +
> +struct phy_settings {
> +       unsigned long long min_rate;
> +       unsigned long long max_rate;
> +       struct phy_lane_settings channel[3];
> +       struct phy_lane_settings clock;
> +};
> +
> +static const struct phy_settings vc5_hdmi_phy_settings[] = {
> +       {
> +               0, 50000000,
> +               {
> +                       {{0x0, 0x0A}, 0x12, 0x0},
> +                       {{0x0, 0x0A}, 0x12, 0x0},
> +                       {{0x0, 0x0A}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0A}, 0x18, 0x0},
> +       },
> +       {
> +               50000001, 75000000,
> +               {
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               75000001,   165000000,
> +               {
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0},
> +                       {{0x0, 0x09}, 0x12, 0x0}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               165000001,  250000000,
> +               {
> +                       {{0x0, 0x0F}, 0x12, 0x1},
> +                       {{0x0, 0x0F}, 0x12, 0x1},
> +                       {{0x0, 0x0F}, 0x12, 0x1}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0x3},
> +       },
> +       {
> +               250000001,  340000000,
> +               {
> +                       {{0x2, 0x0D}, 0x12, 0x1},
> +                       {{0x2, 0x0D}, 0x12, 0x1},
> +                       {{0x2, 0x0D}, 0x12, 0x1}
> +               },
> +               {{0x0, 0x0C}, 0x18, 0xF},
> +       },
> +       {
> +               340000001,  450000000,
> +               {
> +                       {{0x0, 0x1B}, 0x12, 0xF},
> +                       {{0x0, 0x1B}, 0x12, 0xF},
> +                       {{0x0, 0x1B}, 0x12, 0xF}
> +               },
> +               {{0x0, 0x0A}, 0x12, 0xF},
> +       },
> +       {
> +               450000001,  600000000,
> +               {
> +                       {{0x0, 0x1C}, 0x12, 0xF},
> +                       {{0x0, 0x1C}, 0x12, 0xF},
> +                       {{0x0, 0x1C}, 0x12, 0xF}
> +               },
> +               {{0x0, 0x0B}, 0x13, 0xF},
> +       },
> +};
> +
> +static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate)
> +{
> +       unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings);
> +       unsigned int i;
> +
> +       for (i = 0; i < count; i++) {
> +               const struct phy_settings *s = &vc5_hdmi_phy_settings[i];
> +
> +               if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate)
> +                       return s;
> +       }
> +
> +       /*
> +        * If the pixel clock exceeds our max setting, try the max
> +        * setting anyway.
> +        */
> +       return &vc5_hdmi_phy_settings[count - 1];
> +}
> +
> +static const struct phy_lane_settings *
> +phy_get_channel_settings(enum vc4_hdmi_phy_channel chan,
> +                        unsigned long long tmds_rate)
> +{
> +       const struct phy_settings *settings = phy_get_settings(tmds_rate);
> +
> +       if (chan == PHY_LANE_CK)
> +               return &settings->clock;
> +
> +       return &settings->channel[chan];
> +}
> +
> +static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f);
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10));
> +}
> +
> +void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode)
> +{
> +       const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings;
> +       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
> +       unsigned long long pixel_freq = mode->clock * 1000;
> +       unsigned long long vco_freq;
> +       unsigned char word_sel;
> +       u8 vco_sel, vco_div;
> +
> +       vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div);
> +
> +       vc5_hdmi_reset_phy(vc4_hdmi);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET &
> +                  ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET);
> +
> +       HDMI_WRITE(HDMI_RM_CONTROL,
> +                  HDMI_READ(HDMI_RM_CONTROL) |
> +                  VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS |
> +                  VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR |
> +                  VC4_HDMI_RM_CONTROL_FREE_RUN);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
> +                  (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) &
> +                   ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) |
> +                  VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
> +                  (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) &
> +                   ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) |
> +                  VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT));
> +
> +       HDMI_WRITE(HDMI_RM_OFFSET,
> +                  VC4_SET_FIELD(phy_get_rm_offset(vco_freq),
> +                                VC4_HDMI_RM_OFFSET_OFFSET) |
> +                  VC4_HDMI_RM_OFFSET_ONLY);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CLK_DIV,
> +                  VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
> +                  VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) |
> +                  VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0,
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE |
> +                  VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1,
> +                  HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) |
> +                  VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE |
> +                  VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) |
> +                  VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP));
> +
> +       HDMI_WRITE(HDMI_RM_FORMAT,
> +                  HDMI_READ(HDMI_RM_FORMAT) |
> +                  VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_PLL_CFG,
> +                  HDMI_READ(HDMI_TX_PHY_PLL_CFG) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV));
> +
> +       if (pixel_freq >= 340000000)
> +               word_sel = 3;
> +       else
> +               word_sel = 0;
> +       HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_3,
> +                  VC4_SET_FIELD(phy_get_cp_current(vco_freq),
> +                                VC4_HDMI_TX_PHY_CTL_3_ICP) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) |
> +                  VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) |
> +                  VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) |
> +                  VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) |
> +                  VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ));
> +
> +       chan0_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0],
> +                                        pixel_freq);
> +       chan1_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1],
> +                                        pixel_freq);
> +       chan2_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2],
> +                                        pixel_freq);
> +       clock_settings =
> +               phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK],
> +                                        pixel_freq);
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_0,
> +                  VC4_SET_FIELD(chan0_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) |
> +                  VC4_SET_FIELD(chan0_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) |
> +                  VC4_SET_FIELD(chan1_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) |
> +                  VC4_SET_FIELD(chan1_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) |
> +                  VC4_SET_FIELD(chan2_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) |
> +                  VC4_SET_FIELD(chan2_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) |
> +                  VC4_SET_FIELD(clock_settings->amplitude.preemphasis,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) |
> +                  VC4_SET_FIELD(clock_settings->amplitude.main_driver,
> +                                VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_1,
> +                  HDMI_READ(HDMI_TX_PHY_CTL_1) |
> +                  VC4_SET_FIELD(chan0_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) |
> +                  VC4_SET_FIELD(chan1_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) |
> +                  VC4_SET_FIELD(chan2_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) |
> +                  VC4_SET_FIELD(clock_settings->res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CTL_2,
> +                  VC4_SET_FIELD(chan0_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) |
> +                  VC4_SET_FIELD(chan1_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) |
> +                  VC4_SET_FIELD(chan2_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) |
> +                  VC4_SET_FIELD(clock_settings->term_res_sel_data,
> +                                VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) |
> +                  VC4_SET_FIELD(phy_get_vco_gain(vco_freq),
> +                                VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP,
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) |
> +                  VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK],
> +                                VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) &
> +                  ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
> +                    VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB));
> +
> +       HDMI_WRITE(HDMI_TX_PHY_RESET_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_RESET_CTL) |
> +                  VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB |
> +                  VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB);
> +}
> +
> +void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) {
> +       vc5_hdmi_reset_phy(vc4_hdmi);
> +}
> +
> +void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) &
> +                  ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +}
> +
> +void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi)
> +{
> +       HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL,
> +                  HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) |
> +                  VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN);
> +}
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> index bc47cc9bc883..a5f1354e3e06 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> @@ -9,6 +9,12 @@ enum vc4_hdmi_regs {
>         VC4_INVALID = 0,
>         VC4_HDMI,
>         VC4_HD,
> +       VC5_CEC,
> +       VC5_CSC,
> +       VC5_DVP,
> +       VC5_PHY,
> +       VC5_RAM,
> +       VC5_RM,
>  };
>
>  enum vc4_hdmi_field {
> @@ -36,6 +42,7 @@ enum vc4_hdmi_field {
>         HDMI_CEC_TX_DATA_2,
>         HDMI_CEC_TX_DATA_3,
>         HDMI_CEC_TX_DATA_4,
> +       HDMI_CLOCK_STOP,
>         HDMI_CORE_REV,
>         HDMI_CRP_CFG,
>         HDMI_CSC_12_11,
> @@ -52,6 +59,7 @@ enum vc4_hdmi_field {
>          */
>         HDMI_CTS_0,
>         HDMI_CTS_1,
> +       HDMI_DVP_CTL,
>         HDMI_FIFO_CTL,
>         HDMI_FRAME_COUNT,
>         HDMI_HORZA,
> @@ -84,10 +92,27 @@ enum vc4_hdmi_field {
>         HDMI_RAM_PACKET_CONFIG,
>         HDMI_RAM_PACKET_START,
>         HDMI_RAM_PACKET_STATUS,
> +       HDMI_RM_CONTROL,
> +       HDMI_RM_FORMAT,
> +       HDMI_RM_OFFSET,
>         HDMI_SCHEDULER_CONTROL,
>         HDMI_SW_RESET_CONTROL,
> +       HDMI_TX_PHY_CHANNEL_SWAP,
> +       HDMI_TX_PHY_CLK_DIV,
>         HDMI_TX_PHY_CTL_0,
> +       HDMI_TX_PHY_CTL_1,
> +       HDMI_TX_PHY_CTL_2,
> +       HDMI_TX_PHY_CTL_3,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2,
> +       HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4,
> +       HDMI_TX_PHY_PLL_CFG,
> +       HDMI_TX_PHY_PLL_CTL_0,
> +       HDMI_TX_PHY_PLL_CTL_1,
> +       HDMI_TX_PHY_POWERDOWN_CTL,
>         HDMI_TX_PHY_RESET_CTL,
> +       HDMI_TX_PHY_TMDS_CLK_WORD_SEL,
> +       HDMI_VEC_INTERFACE_XBAR,
>         HDMI_VERTA0,
>         HDMI_VERTA1,
>         HDMI_VERTB0,
> @@ -110,6 +135,12 @@ struct vc4_hdmi_register {
>
>  #define VC4_HD_REG(reg, offset)                _VC4_REG(VC4_HD, reg, offset)
>  #define VC4_HDMI_REG(reg, offset)      _VC4_REG(VC4_HDMI, reg, offset)
> +#define VC5_CEC_REG(reg, offset)       _VC4_REG(VC5_CEC, reg, offset)
> +#define VC5_CSC_REG(reg, offset)       _VC4_REG(VC5_CSC, reg, offset)
> +#define VC5_DVP_REG(reg, offset)       _VC4_REG(VC5_DVP, reg, offset)
> +#define VC5_PHY_REG(reg, offset)       _VC4_REG(VC5_PHY, reg, offset)
> +#define VC5_RAM_REG(reg, offset)       _VC4_REG(VC5_RAM, reg, offset)
> +#define VC5_RM_REG(reg, offset)                _VC4_REG(VC5_RM, reg, offset)
>
>  static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
>         VC4_HD_REG(HDMI_M_CTL, 0x000c),
> @@ -172,6 +203,158 @@ static const struct vc4_hdmi_register vc4_hdmi_fields[] = {
>         VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400),
>  };
>
> +static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
> +       VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0010),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0014),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x0018),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x001c),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x0020),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0044),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060),
> +
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
> +
> +       VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
> +       VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
> +
> +       VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
> +       VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
> +       VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
> +       VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
> +       VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
> +
> +       VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
> +       VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
> +       VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
> +
> +       VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
> +
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
> +
> +       VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
> +       VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
> +       VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
> +       VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
> +       VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
> +       VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
> +       VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
> +};
> +
> +static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
> +       VC4_HD_REG(HDMI_DVP_CTL, 0x0000),
> +       VC4_HD_REG(HDMI_MAI_CTL, 0x0030),
> +       VC4_HD_REG(HDMI_MAI_THR, 0x0034),
> +       VC4_HD_REG(HDMI_MAI_FMT, 0x0038),
> +       VC4_HD_REG(HDMI_MAI_DATA, 0x003c),
> +       VC4_HD_REG(HDMI_MAI_SMP, 0x0040),
> +       VC4_HD_REG(HDMI_VID_CTL, 0x0048),
> +       VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064),
> +
> +       VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074),
> +       VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc),
> +       VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4),
> +       VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8),
> +       VC4_HDMI_REG(HDMI_CTS_0, 0x0cc),
> +       VC4_HDMI_REG(HDMI_CTS_1, 0x0d0),
> +       VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0),
> +       VC4_HDMI_REG(HDMI_HORZA, 0x0e4),
> +       VC4_HDMI_REG(HDMI_HORZB, 0x0e8),
> +       VC4_HDMI_REG(HDMI_VERTA0, 0x0ec),
> +       VC4_HDMI_REG(HDMI_VERTB0, 0x0f0),
> +       VC4_HDMI_REG(HDMI_VERTA1, 0x0f4),
> +       VC4_HDMI_REG(HDMI_VERTB1, 0x0f8),
> +       VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c),
> +       VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0),
> +       VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8),
> +
> +       VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc),
> +       VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0),
> +
> +       VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000),
> +       VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010),
> +       VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020),
> +       VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034),
> +       VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c),
> +       VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054),
> +       VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c),
> +
> +       VC5_RM_REG(HDMI_RM_CONTROL, 0x000),
> +       VC5_RM_REG(HDMI_RM_OFFSET, 0x018),
> +       VC5_RM_REG(HDMI_RM_FORMAT, 0x01c),
> +
> +       VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000),
> +
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
> +       VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
> +       VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040),
> +       VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044),
> +
> +       VC5_CSC_REG(HDMI_CSC_CTL, 0x000),
> +       VC5_CSC_REG(HDMI_CSC_12_11, 0x004),
> +       VC5_CSC_REG(HDMI_CSC_14_13, 0x008),
> +       VC5_CSC_REG(HDMI_CSC_22_21, 0x00c),
> +       VC5_CSC_REG(HDMI_CSC_24_23, 0x010),
> +       VC5_CSC_REG(HDMI_CSC_32_31, 0x014),
> +       VC5_CSC_REG(HDMI_CSC_34_33, 0x018),
> +};
> +
>  static inline
>  void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
>                                         enum vc4_hdmi_regs reg)
> @@ -183,6 +366,24 @@ void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi,
>         case VC4_HDMI:
>                 return hdmi->hdmicore_regs;
>
> +       case VC5_CSC:
> +               return hdmi->csc_regs;
> +
> +       case VC5_CEC:
> +               return hdmi->cec_regs;
> +
> +       case VC5_DVP:
> +               return hdmi->dvp_regs;
> +
> +       case VC5_PHY:
> +               return hdmi->phy_regs;
> +
> +       case VC5_RAM:
> +               return hdmi->ram_regs;
> +
> +       case VC5_RM:
> +               return hdmi->rm_regs;
> +
>         default:
>                 return NULL;
>         }
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 30af52b406f1..be2c32a519b3 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -744,6 +744,8 @@
>  # define VC4_HD_CSC_CTL_RGB2YCC                        BIT(1)
>  # define VC4_HD_CSC_CTL_ENABLE                 BIT(0)
>
> +# define VC4_DVP_HT_CLOCK_STOP_PIXEL           BIT(1)
> +
>  /* HVS display list information. */
>  #define HVS_BOOTLOADER_DLIST_END                32
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:30       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The BCM2711 has a reworked display pipeline, and the load tracker needs
> some adjustement to operate properly. Let's add a compatible for BCM2711

s/adjustement/adjustment

> and disable the load tracker until properly supported.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_drv.c   |  1 +-
>  drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
>  drivers/gpu/drm/vc4/vc4_kms.c   | 42 +++++++++++++++++++++++-----------
>  drivers/gpu/drm/vc4/vc4_plane.c |  5 ++++-
>  4 files changed, 38 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 9567d1019212..f1a5fd5dab6f 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev)
>  }
>
>  static const struct of_device_id vc4_of_match[] = {
> +       { .compatible = "brcm,bcm2711-vc5", },
>         { .compatible = "brcm,bcm2835-vc4", },
>         { .compatible = "brcm,cygnus-vc4", },
>         {},
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 501a48a714d3..8c8d96b6289f 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -200,6 +200,9 @@ struct vc4_dev {
>
>         int power_refcount;
>
> +       /* Set to true when the load tracker is supported. */
> +       bool load_tracker_available;
> +
>         /* Set to true when the load tracker is active. */
>         bool load_tracker_enabled;
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 7c8a87339959..ae479f988666 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -532,6 +532,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state)
>         struct drm_plane *plane;
>         int i;
>
> +       if (!vc4->load_tracker_available)
> +               return 0;
> +
>         priv_state = drm_atomic_get_private_obj_state(state,
>                                                       &vc4->load_tracker);
>         if (IS_ERR(priv_state))
> @@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
>         struct vc4_load_tracker_state *load_state;
>         int ret;
>
> -       /* Start with the load tracker enabled. Can be disabled through the
> -        * debugfs load_tracker file.
> -        */
> -       vc4->load_tracker_enabled = true;
> +       if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {

Is it better to look up the compatible string, or pass something via
the .data element of the of_device_id table? Probably down to personal
preference?

> +               vc4->load_tracker_available = true;
> +
> +               /* Start with the load tracker enabled. Can be
> +                * disabled through the debugfs load_tracker file.
> +                */
> +               vc4->load_tracker_enabled = true;
> +       }
>
>         sema_init(&vc4->async_modeset, 1);
>
> @@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
>                 return ret;
>         }
>
> -       dev->mode_config.max_width = 2048;
> -       dev->mode_config.max_height = 2048;
> +       if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {

We're making the same of_device_is_compatible call twice within
vc4_kms_load. Set a flag based on it and check that instead?

  Dave

> +               dev->mode_config.max_width = 7680;
> +               dev->mode_config.max_height = 7680;
> +       } else {
> +               dev->mode_config.max_width = 2048;
> +               dev->mode_config.max_height = 2048;
> +       }
> +
>         dev->mode_config.funcs = &vc4_mode_funcs;
>         dev->mode_config.preferred_depth = 24;
>         dev->mode_config.async_page_flip = true;
> @@ -714,14 +727,17 @@ int vc4_kms_load(struct drm_device *dev)
>         drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
>                                     &vc4_ctm_state_funcs);
>
> -       load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
> -       if (!load_state) {
> -               drm_atomic_private_obj_fini(&vc4->ctm_manager);
> -               return -ENOMEM;
> -       }
> +       if (vc4->load_tracker_available) {
> +               load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
> +               if (!load_state) {
> +                       drm_atomic_private_obj_fini(&vc4->ctm_manager);
> +                       return -ENOMEM;
> +               }
>
> -       drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base,
> -                                   &vc4_load_tracker_state_funcs);
> +               drm_atomic_private_obj_init(dev, &vc4->load_tracker,
> +                                           &load_state->base,
> +                                           &vc4_load_tracker_state_funcs);
> +       }
>
>         drm_mode_config_reset(dev);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 1e38e603f83b..24d7e6db6fdd 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state)
>         struct vc4_plane_state *vc4_state;
>         struct drm_crtc_state *crtc_state;
>         unsigned int vscale_factor;
> +       struct vc4_dev *vc4;
> +
> +       vc4 = to_vc4_dev(state->plane->dev);
> +       if (!vc4->load_tracker_available)
> +               return;
>
>         vc4_state = to_vc4_plane_state(state);
>         crtc_state = drm_atomic_get_existing_crtc_state(state->state,
> --
> git-series 0.9.1

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

* Re: [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
@ 2020-07-28 15:30       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The BCM2711 has a reworked display pipeline, and the load tracker needs
> some adjustement to operate properly. Let's add a compatible for BCM2711

s/adjustement/adjustment

> and disable the load tracker until properly supported.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_drv.c   |  1 +-
>  drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
>  drivers/gpu/drm/vc4/vc4_kms.c   | 42 +++++++++++++++++++++++-----------
>  drivers/gpu/drm/vc4/vc4_plane.c |  5 ++++-
>  4 files changed, 38 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 9567d1019212..f1a5fd5dab6f 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev)
>  }
>
>  static const struct of_device_id vc4_of_match[] = {
> +       { .compatible = "brcm,bcm2711-vc5", },
>         { .compatible = "brcm,bcm2835-vc4", },
>         { .compatible = "brcm,cygnus-vc4", },
>         {},
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 501a48a714d3..8c8d96b6289f 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -200,6 +200,9 @@ struct vc4_dev {
>
>         int power_refcount;
>
> +       /* Set to true when the load tracker is supported. */
> +       bool load_tracker_available;
> +
>         /* Set to true when the load tracker is active. */
>         bool load_tracker_enabled;
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 7c8a87339959..ae479f988666 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -532,6 +532,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state)
>         struct drm_plane *plane;
>         int i;
>
> +       if (!vc4->load_tracker_available)
> +               return 0;
> +
>         priv_state = drm_atomic_get_private_obj_state(state,
>                                                       &vc4->load_tracker);
>         if (IS_ERR(priv_state))
> @@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
>         struct vc4_load_tracker_state *load_state;
>         int ret;
>
> -       /* Start with the load tracker enabled. Can be disabled through the
> -        * debugfs load_tracker file.
> -        */
> -       vc4->load_tracker_enabled = true;
> +       if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {

Is it better to look up the compatible string, or pass something via
the .data element of the of_device_id table? Probably down to personal
preference?

> +               vc4->load_tracker_available = true;
> +
> +               /* Start with the load tracker enabled. Can be
> +                * disabled through the debugfs load_tracker file.
> +                */
> +               vc4->load_tracker_enabled = true;
> +       }
>
>         sema_init(&vc4->async_modeset, 1);
>
> @@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
>                 return ret;
>         }
>
> -       dev->mode_config.max_width = 2048;
> -       dev->mode_config.max_height = 2048;
> +       if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {

We're making the same of_device_is_compatible call twice within
vc4_kms_load. Set a flag based on it and check that instead?

  Dave

> +               dev->mode_config.max_width = 7680;
> +               dev->mode_config.max_height = 7680;
> +       } else {
> +               dev->mode_config.max_width = 2048;
> +               dev->mode_config.max_height = 2048;
> +       }
> +
>         dev->mode_config.funcs = &vc4_mode_funcs;
>         dev->mode_config.preferred_depth = 24;
>         dev->mode_config.async_page_flip = true;
> @@ -714,14 +727,17 @@ int vc4_kms_load(struct drm_device *dev)
>         drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
>                                     &vc4_ctm_state_funcs);
>
> -       load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
> -       if (!load_state) {
> -               drm_atomic_private_obj_fini(&vc4->ctm_manager);
> -               return -ENOMEM;
> -       }
> +       if (vc4->load_tracker_available) {
> +               load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
> +               if (!load_state) {
> +                       drm_atomic_private_obj_fini(&vc4->ctm_manager);
> +                       return -ENOMEM;
> +               }
>
> -       drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base,
> -                                   &vc4_load_tracker_state_funcs);
> +               drm_atomic_private_obj_init(dev, &vc4->load_tracker,
> +                                           &load_state->base,
> +                                           &vc4_load_tracker_state_funcs);
> +       }
>
>         drm_mode_config_reset(dev);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 1e38e603f83b..24d7e6db6fdd 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state)
>         struct vc4_plane_state *vc4_state;
>         struct drm_crtc_state *crtc_state;
>         unsigned int vscale_factor;
> +       struct vc4_dev *vc4;
> +
> +       vc4 = to_vc4_dev(state->plane->dev);
> +       if (!vc4->load_tracker_available)
> +               return;
>
>         vc4_state = to_vc4_plane_state(state);
>         crtc_state = drm_atomic_get_existing_crtc_state(state->state,
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
@ 2020-07-28 15:30       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The BCM2711 has a reworked display pipeline, and the load tracker needs
> some adjustement to operate properly. Let's add a compatible for BCM2711

s/adjustement/adjustment

> and disable the load tracker until properly supported.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_drv.c   |  1 +-
>  drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
>  drivers/gpu/drm/vc4/vc4_kms.c   | 42 +++++++++++++++++++++++-----------
>  drivers/gpu/drm/vc4/vc4_plane.c |  5 ++++-
>  4 files changed, 38 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
> index 9567d1019212..f1a5fd5dab6f 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.c
> +++ b/drivers/gpu/drm/vc4/vc4_drv.c
> @@ -372,6 +372,7 @@ static int vc4_platform_drm_remove(struct platform_device *pdev)
>  }
>
>  static const struct of_device_id vc4_of_match[] = {
> +       { .compatible = "brcm,bcm2711-vc5", },
>         { .compatible = "brcm,bcm2835-vc4", },
>         { .compatible = "brcm,cygnus-vc4", },
>         {},
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 501a48a714d3..8c8d96b6289f 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -200,6 +200,9 @@ struct vc4_dev {
>
>         int power_refcount;
>
> +       /* Set to true when the load tracker is supported. */
> +       bool load_tracker_available;
> +
>         /* Set to true when the load tracker is active. */
>         bool load_tracker_enabled;
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 7c8a87339959..ae479f988666 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -532,6 +532,9 @@ static int vc4_load_tracker_atomic_check(struct drm_atomic_state *state)
>         struct drm_plane *plane;
>         int i;
>
> +       if (!vc4->load_tracker_available)
> +               return 0;
> +
>         priv_state = drm_atomic_get_private_obj_state(state,
>                                                       &vc4->load_tracker);
>         if (IS_ERR(priv_state))
> @@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
>         struct vc4_load_tracker_state *load_state;
>         int ret;
>
> -       /* Start with the load tracker enabled. Can be disabled through the
> -        * debugfs load_tracker file.
> -        */
> -       vc4->load_tracker_enabled = true;
> +       if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {

Is it better to look up the compatible string, or pass something via
the .data element of the of_device_id table? Probably down to personal
preference?

> +               vc4->load_tracker_available = true;
> +
> +               /* Start with the load tracker enabled. Can be
> +                * disabled through the debugfs load_tracker file.
> +                */
> +               vc4->load_tracker_enabled = true;
> +       }
>
>         sema_init(&vc4->async_modeset, 1);
>
> @@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
>                 return ret;
>         }
>
> -       dev->mode_config.max_width = 2048;
> -       dev->mode_config.max_height = 2048;
> +       if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {

We're making the same of_device_is_compatible call twice within
vc4_kms_load. Set a flag based on it and check that instead?

  Dave

> +               dev->mode_config.max_width = 7680;
> +               dev->mode_config.max_height = 7680;
> +       } else {
> +               dev->mode_config.max_width = 2048;
> +               dev->mode_config.max_height = 2048;
> +       }
> +
>         dev->mode_config.funcs = &vc4_mode_funcs;
>         dev->mode_config.preferred_depth = 24;
>         dev->mode_config.async_page_flip = true;
> @@ -714,14 +727,17 @@ int vc4_kms_load(struct drm_device *dev)
>         drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base,
>                                     &vc4_ctm_state_funcs);
>
> -       load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
> -       if (!load_state) {
> -               drm_atomic_private_obj_fini(&vc4->ctm_manager);
> -               return -ENOMEM;
> -       }
> +       if (vc4->load_tracker_available) {
> +               load_state = kzalloc(sizeof(*load_state), GFP_KERNEL);
> +               if (!load_state) {
> +                       drm_atomic_private_obj_fini(&vc4->ctm_manager);
> +                       return -ENOMEM;
> +               }
>
> -       drm_atomic_private_obj_init(dev, &vc4->load_tracker, &load_state->base,
> -                                   &vc4_load_tracker_state_funcs);
> +               drm_atomic_private_obj_init(dev, &vc4->load_tracker,
> +                                           &load_state->base,
> +                                           &vc4_load_tracker_state_funcs);
> +       }
>
>         drm_mode_config_reset(dev);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 1e38e603f83b..24d7e6db6fdd 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -516,6 +516,11 @@ static void vc4_plane_calc_load(struct drm_plane_state *state)
>         struct vc4_plane_state *vc4_state;
>         struct drm_crtc_state *crtc_state;
>         unsigned int vscale_factor;
> +       struct vc4_dev *vc4;
> +
> +       vc4 = to_vc4_dev(state->plane->dev);
> +       if (!vc4->load_tracker_available)
> +               return;
>
>         vc4_state = to_vc4_plane_state(state);
>         crtc_state = drm_atomic_get_existing_crtc_state(state->state,
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-07-28 15:35       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:35 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that all the drivers have been adjusted for it, let's bring in the
> necessary device tree changes.

Possibly a comment to say that the VEC and PV3 are deliberately NOT
enabled as the VEC requires further very specific clock setup changes?

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Otherwise
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  46 +++++++++++-
>  arch/arm/boot/dts/bcm2711.dtsi        | 115 ++++++++++++++++++++++++++-
>  2 files changed, 160 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> index 222d7825e1ab..b93eb30e1ddb 100644
> --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> @@ -68,6 +68,14 @@
>         };
>  };
>
> +&ddc0 {
> +       status = "okay";
> +};
> +
> +&ddc1 {
> +       status = "okay";
> +};
> +
>  &firmware {
>         firmware_clocks: clocks {
>                 compatible = "raspberrypi,firmware-clocks";
> @@ -163,6 +171,36 @@
>                           "RGMII_TXD3";
>  };
>
> +&hdmi0 {
> +       clocks = <&firmware_clocks 13>, <&dvp 0>;
> +       status = "okay";
> +};
> +
> +&hdmi1 {
> +       clocks = <&firmware_clocks 13>, <&dvp 1>;
> +       status = "okay";
> +};
> +
> +&hvs {
> +       clocks = <&firmware_clocks 4>;
> +};
> +
> +&pixelvalve0 {
> +       status = "okay";
> +};
> +
> +&pixelvalve1 {
> +       status = "okay";
> +};
> +
> +&pixelvalve2 {
> +       status = "okay";
> +};
> +
> +&pixelvalve4 {
> +       status = "okay";
> +};
> +
>  &pwm1 {
>         pinctrl-names = "default";
>         pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
> @@ -231,3 +269,11 @@
>  &vchiq {
>         interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
>  };
> +
> +&vc4 {
> +       status = "okay";
> +};
> +
> +&vec {
> +       status = "disabled";
> +};
> diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
> index 00bcaed1be32..e637378650f6 100644
> --- a/arch/arm/boot/dts/bcm2711.dtsi
> +++ b/arch/arm/boot/dts/bcm2711.dtsi
> @@ -12,6 +12,11 @@
>
>         interrupt-parent = <&gicv2>;
>
> +       vc4: gpu {
> +               compatible = "brcm,bcm2711-vc5";
> +               status = "disabled";
> +       };
> +
>         clk_108MHz: clk-108M {
>                 #clock-cells = <0>;
>                 compatible = "fixed-clock";
> @@ -238,6 +243,27 @@
>                         status = "disabled";
>                 };
>
> +               pixelvalve0: pixelvalve@7e206000 {
> +                       compatible = "brcm,bcm2711-pixelvalve0";
> +                       reg = <0x7e206000 0x100>;
> +                       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               pixelvalve1: pixelvalve@7e207000 {
> +                       compatible = "brcm,bcm2711-pixelvalve1";
> +                       reg = <0x7e207000 0x100>;
> +                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               pixelvalve2: pixelvalve@7e20a000 {
> +                       compatible = "brcm,bcm2711-pixelvalve2";
> +                       reg = <0x7e20a000 0x100>;
> +                       interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
>                 pwm1: pwm@7e20c800 {
>                         compatible = "brcm,bcm2835-pwm";
>                         reg = <0x7e20c800 0x28>;
> @@ -248,10 +274,25 @@
>                         status = "disabled";
>                 };
>
> -               hvs@7e400000 {
> +               pixelvalve4: pixelvalve@7e216000 {
> +                       compatible = "brcm,bcm2711-pixelvalve4";
> +                       reg = <0x7e216000 0x100>;
> +                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               hvs: hvs@7e400000 {
> +                       compatible = "brcm,bcm2711-hvs";
>                         interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>                 };
>
> +               pixelvalve3: pixelvalve@7ec12000 {
> +                       compatible = "brcm,bcm2711-pixelvalve3";
> +                       reg = <0x7ec12000 0x100>;
> +                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
>                 dvp: clock@7ef00000 {
>                         compatible = "brcm,brcm2711-dvp";
>                         reg = <0x7ef00000 0x10>;
> @@ -259,6 +300,78 @@
>                         #clock-cells = <1>;
>                         #reset-cells = <1>;
>                 };
> +
> +               hdmi0: hdmi@7ef00700 {
> +                       compatible = "brcm,bcm2711-hdmi0";
> +                       reg = <0x7ef00700 0x300>,
> +                             <0x7ef00300 0x200>,
> +                             <0x7ef00f00 0x80>,
> +                             <0x7ef00f80 0x80>,
> +                             <0x7ef01b00 0x200>,
> +                             <0x7ef01f00 0x400>,
> +                             <0x7ef00200 0x80>,
> +                             <0x7ef04300 0x100>,
> +                             <0x7ef20000 0x100>;
> +                       reg-names = "hdmi",
> +                                   "dvp",
> +                                   "phy",
> +                                   "rm",
> +                                   "packet",
> +                                   "metadata",
> +                                   "csc",
> +                                   "cec",
> +                                   "hd";
> +                       clock-names = "hdmi", "clk-108M";
> +                       resets = <&dvp 0>;
> +                       ddc = <&ddc0>;
> +                       dmas = <&dma 10>;
> +                       dma-names = "audio-rx";
> +                       status = "disabled";
> +               };
> +
> +               ddc0: i2c@7ef04500 {
> +                       compatible = "brcm,bcm2711-hdmi-i2c";
> +                       reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
> +                       reg-names = "bsc", "auto-i2c";
> +                       clock-frequency = <97500>;
> +                       status = "disabled";
> +               };
> +
> +               hdmi1: hdmi@7ef05700 {
> +                       compatible = "brcm,bcm2711-hdmi1";
> +                       reg = <0x7ef05700 0x300>,
> +                             <0x7ef05300 0x200>,
> +                             <0x7ef05f00 0x80>,
> +                             <0x7ef05f80 0x80>,
> +                             <0x7ef06b00 0x200>,
> +                             <0x7ef06f00 0x400>,
> +                             <0x7ef00280 0x80>,
> +                             <0x7ef09300 0x100>,
> +                             <0x7ef20000 0x100>;
> +                       reg-names = "hdmi",
> +                                   "dvp",
> +                                   "phy",
> +                                   "rm",
> +                                   "packet",
> +                                   "metadata",
> +                                   "csc",
> +                                   "cec",
> +                                   "hd";
> +                       ddc = <&ddc1>;
> +                       clock-names = "hdmi", "clk-108M";
> +                       resets = <&dvp 1>;
> +                       dmas = <&dma 17>;
> +                       dma-names = "audio-rx";
> +                       status = "disabled";
> +               };
> +
> +               ddc1: i2c@7ef09500 {
> +                       compatible = "brcm,bcm2711-hdmi-i2c";
> +                       reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
> +                       reg-names = "bsc", "auto-i2c";
> +                       clock-frequency = <97500>;
> +                       status = "disabled";
> +               };
>         };
>
>         /*
> --
> git-series 0.9.1

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

* Re: [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline
@ 2020-07-28 15:35       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:35 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that all the drivers have been adjusted for it, let's bring in the
> necessary device tree changes.

Possibly a comment to say that the VEC and PV3 are deliberately NOT
enabled as the VEC requires further very specific clock setup changes?

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Otherwise
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  46 +++++++++++-
>  arch/arm/boot/dts/bcm2711.dtsi        | 115 ++++++++++++++++++++++++++-
>  2 files changed, 160 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> index 222d7825e1ab..b93eb30e1ddb 100644
> --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> @@ -68,6 +68,14 @@
>         };
>  };
>
> +&ddc0 {
> +       status = "okay";
> +};
> +
> +&ddc1 {
> +       status = "okay";
> +};
> +
>  &firmware {
>         firmware_clocks: clocks {
>                 compatible = "raspberrypi,firmware-clocks";
> @@ -163,6 +171,36 @@
>                           "RGMII_TXD3";
>  };
>
> +&hdmi0 {
> +       clocks = <&firmware_clocks 13>, <&dvp 0>;
> +       status = "okay";
> +};
> +
> +&hdmi1 {
> +       clocks = <&firmware_clocks 13>, <&dvp 1>;
> +       status = "okay";
> +};
> +
> +&hvs {
> +       clocks = <&firmware_clocks 4>;
> +};
> +
> +&pixelvalve0 {
> +       status = "okay";
> +};
> +
> +&pixelvalve1 {
> +       status = "okay";
> +};
> +
> +&pixelvalve2 {
> +       status = "okay";
> +};
> +
> +&pixelvalve4 {
> +       status = "okay";
> +};
> +
>  &pwm1 {
>         pinctrl-names = "default";
>         pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
> @@ -231,3 +269,11 @@
>  &vchiq {
>         interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
>  };
> +
> +&vc4 {
> +       status = "okay";
> +};
> +
> +&vec {
> +       status = "disabled";
> +};
> diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
> index 00bcaed1be32..e637378650f6 100644
> --- a/arch/arm/boot/dts/bcm2711.dtsi
> +++ b/arch/arm/boot/dts/bcm2711.dtsi
> @@ -12,6 +12,11 @@
>
>         interrupt-parent = <&gicv2>;
>
> +       vc4: gpu {
> +               compatible = "brcm,bcm2711-vc5";
> +               status = "disabled";
> +       };
> +
>         clk_108MHz: clk-108M {
>                 #clock-cells = <0>;
>                 compatible = "fixed-clock";
> @@ -238,6 +243,27 @@
>                         status = "disabled";
>                 };
>
> +               pixelvalve0: pixelvalve@7e206000 {
> +                       compatible = "brcm,bcm2711-pixelvalve0";
> +                       reg = <0x7e206000 0x100>;
> +                       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               pixelvalve1: pixelvalve@7e207000 {
> +                       compatible = "brcm,bcm2711-pixelvalve1";
> +                       reg = <0x7e207000 0x100>;
> +                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               pixelvalve2: pixelvalve@7e20a000 {
> +                       compatible = "brcm,bcm2711-pixelvalve2";
> +                       reg = <0x7e20a000 0x100>;
> +                       interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
>                 pwm1: pwm@7e20c800 {
>                         compatible = "brcm,bcm2835-pwm";
>                         reg = <0x7e20c800 0x28>;
> @@ -248,10 +274,25 @@
>                         status = "disabled";
>                 };
>
> -               hvs@7e400000 {
> +               pixelvalve4: pixelvalve@7e216000 {
> +                       compatible = "brcm,bcm2711-pixelvalve4";
> +                       reg = <0x7e216000 0x100>;
> +                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               hvs: hvs@7e400000 {
> +                       compatible = "brcm,bcm2711-hvs";
>                         interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>                 };
>
> +               pixelvalve3: pixelvalve@7ec12000 {
> +                       compatible = "brcm,bcm2711-pixelvalve3";
> +                       reg = <0x7ec12000 0x100>;
> +                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
>                 dvp: clock@7ef00000 {
>                         compatible = "brcm,brcm2711-dvp";
>                         reg = <0x7ef00000 0x10>;
> @@ -259,6 +300,78 @@
>                         #clock-cells = <1>;
>                         #reset-cells = <1>;
>                 };
> +
> +               hdmi0: hdmi@7ef00700 {
> +                       compatible = "brcm,bcm2711-hdmi0";
> +                       reg = <0x7ef00700 0x300>,
> +                             <0x7ef00300 0x200>,
> +                             <0x7ef00f00 0x80>,
> +                             <0x7ef00f80 0x80>,
> +                             <0x7ef01b00 0x200>,
> +                             <0x7ef01f00 0x400>,
> +                             <0x7ef00200 0x80>,
> +                             <0x7ef04300 0x100>,
> +                             <0x7ef20000 0x100>;
> +                       reg-names = "hdmi",
> +                                   "dvp",
> +                                   "phy",
> +                                   "rm",
> +                                   "packet",
> +                                   "metadata",
> +                                   "csc",
> +                                   "cec",
> +                                   "hd";
> +                       clock-names = "hdmi", "clk-108M";
> +                       resets = <&dvp 0>;
> +                       ddc = <&ddc0>;
> +                       dmas = <&dma 10>;
> +                       dma-names = "audio-rx";
> +                       status = "disabled";
> +               };
> +
> +               ddc0: i2c@7ef04500 {
> +                       compatible = "brcm,bcm2711-hdmi-i2c";
> +                       reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
> +                       reg-names = "bsc", "auto-i2c";
> +                       clock-frequency = <97500>;
> +                       status = "disabled";
> +               };
> +
> +               hdmi1: hdmi@7ef05700 {
> +                       compatible = "brcm,bcm2711-hdmi1";
> +                       reg = <0x7ef05700 0x300>,
> +                             <0x7ef05300 0x200>,
> +                             <0x7ef05f00 0x80>,
> +                             <0x7ef05f80 0x80>,
> +                             <0x7ef06b00 0x200>,
> +                             <0x7ef06f00 0x400>,
> +                             <0x7ef00280 0x80>,
> +                             <0x7ef09300 0x100>,
> +                             <0x7ef20000 0x100>;
> +                       reg-names = "hdmi",
> +                                   "dvp",
> +                                   "phy",
> +                                   "rm",
> +                                   "packet",
> +                                   "metadata",
> +                                   "csc",
> +                                   "cec",
> +                                   "hd";
> +                       ddc = <&ddc1>;
> +                       clock-names = "hdmi", "clk-108M";
> +                       resets = <&dvp 1>;
> +                       dmas = <&dma 17>;
> +                       dma-names = "audio-rx";
> +                       status = "disabled";
> +               };
> +
> +               ddc1: i2c@7ef09500 {
> +                       compatible = "brcm,bcm2711-hdmi-i2c";
> +                       reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
> +                       reg-names = "bsc", "auto-i2c";
> +                       clock-frequency = <97500>;
> +                       status = "disabled";
> +               };
>         };
>
>         /*
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline
@ 2020-07-28 15:35       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-28 15:35 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:44, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Now that all the drivers have been adjusted for it, let's bring in the
> necessary device tree changes.

Possibly a comment to say that the VEC and PV3 are deliberately NOT
enabled as the VEC requires further very specific clock setup changes?

> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Otherwise
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts |  46 +++++++++++-
>  arch/arm/boot/dts/bcm2711.dtsi        | 115 ++++++++++++++++++++++++++-
>  2 files changed, 160 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> index 222d7825e1ab..b93eb30e1ddb 100644
> --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
> @@ -68,6 +68,14 @@
>         };
>  };
>
> +&ddc0 {
> +       status = "okay";
> +};
> +
> +&ddc1 {
> +       status = "okay";
> +};
> +
>  &firmware {
>         firmware_clocks: clocks {
>                 compatible = "raspberrypi,firmware-clocks";
> @@ -163,6 +171,36 @@
>                           "RGMII_TXD3";
>  };
>
> +&hdmi0 {
> +       clocks = <&firmware_clocks 13>, <&dvp 0>;
> +       status = "okay";
> +};
> +
> +&hdmi1 {
> +       clocks = <&firmware_clocks 13>, <&dvp 1>;
> +       status = "okay";
> +};
> +
> +&hvs {
> +       clocks = <&firmware_clocks 4>;
> +};
> +
> +&pixelvalve0 {
> +       status = "okay";
> +};
> +
> +&pixelvalve1 {
> +       status = "okay";
> +};
> +
> +&pixelvalve2 {
> +       status = "okay";
> +};
> +
> +&pixelvalve4 {
> +       status = "okay";
> +};
> +
>  &pwm1 {
>         pinctrl-names = "default";
>         pinctrl-0 = <&pwm1_0_gpio40 &pwm1_1_gpio41>;
> @@ -231,3 +269,11 @@
>  &vchiq {
>         interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
>  };
> +
> +&vc4 {
> +       status = "okay";
> +};
> +
> +&vec {
> +       status = "disabled";
> +};
> diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
> index 00bcaed1be32..e637378650f6 100644
> --- a/arch/arm/boot/dts/bcm2711.dtsi
> +++ b/arch/arm/boot/dts/bcm2711.dtsi
> @@ -12,6 +12,11 @@
>
>         interrupt-parent = <&gicv2>;
>
> +       vc4: gpu {
> +               compatible = "brcm,bcm2711-vc5";
> +               status = "disabled";
> +       };
> +
>         clk_108MHz: clk-108M {
>                 #clock-cells = <0>;
>                 compatible = "fixed-clock";
> @@ -238,6 +243,27 @@
>                         status = "disabled";
>                 };
>
> +               pixelvalve0: pixelvalve@7e206000 {
> +                       compatible = "brcm,bcm2711-pixelvalve0";
> +                       reg = <0x7e206000 0x100>;
> +                       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               pixelvalve1: pixelvalve@7e207000 {
> +                       compatible = "brcm,bcm2711-pixelvalve1";
> +                       reg = <0x7e207000 0x100>;
> +                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               pixelvalve2: pixelvalve@7e20a000 {
> +                       compatible = "brcm,bcm2711-pixelvalve2";
> +                       reg = <0x7e20a000 0x100>;
> +                       interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
>                 pwm1: pwm@7e20c800 {
>                         compatible = "brcm,bcm2835-pwm";
>                         reg = <0x7e20c800 0x28>;
> @@ -248,10 +274,25 @@
>                         status = "disabled";
>                 };
>
> -               hvs@7e400000 {
> +               pixelvalve4: pixelvalve@7e216000 {
> +                       compatible = "brcm,bcm2711-pixelvalve4";
> +                       reg = <0x7e216000 0x100>;
> +                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
> +               hvs: hvs@7e400000 {
> +                       compatible = "brcm,bcm2711-hvs";
>                         interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>                 };
>
> +               pixelvalve3: pixelvalve@7ec12000 {
> +                       compatible = "brcm,bcm2711-pixelvalve3";
> +                       reg = <0x7ec12000 0x100>;
> +                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
> +                       status = "disabled";
> +               };
> +
>                 dvp: clock@7ef00000 {
>                         compatible = "brcm,brcm2711-dvp";
>                         reg = <0x7ef00000 0x10>;
> @@ -259,6 +300,78 @@
>                         #clock-cells = <1>;
>                         #reset-cells = <1>;
>                 };
> +
> +               hdmi0: hdmi@7ef00700 {
> +                       compatible = "brcm,bcm2711-hdmi0";
> +                       reg = <0x7ef00700 0x300>,
> +                             <0x7ef00300 0x200>,
> +                             <0x7ef00f00 0x80>,
> +                             <0x7ef00f80 0x80>,
> +                             <0x7ef01b00 0x200>,
> +                             <0x7ef01f00 0x400>,
> +                             <0x7ef00200 0x80>,
> +                             <0x7ef04300 0x100>,
> +                             <0x7ef20000 0x100>;
> +                       reg-names = "hdmi",
> +                                   "dvp",
> +                                   "phy",
> +                                   "rm",
> +                                   "packet",
> +                                   "metadata",
> +                                   "csc",
> +                                   "cec",
> +                                   "hd";
> +                       clock-names = "hdmi", "clk-108M";
> +                       resets = <&dvp 0>;
> +                       ddc = <&ddc0>;
> +                       dmas = <&dma 10>;
> +                       dma-names = "audio-rx";
> +                       status = "disabled";
> +               };
> +
> +               ddc0: i2c@7ef04500 {
> +                       compatible = "brcm,bcm2711-hdmi-i2c";
> +                       reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>;
> +                       reg-names = "bsc", "auto-i2c";
> +                       clock-frequency = <97500>;
> +                       status = "disabled";
> +               };
> +
> +               hdmi1: hdmi@7ef05700 {
> +                       compatible = "brcm,bcm2711-hdmi1";
> +                       reg = <0x7ef05700 0x300>,
> +                             <0x7ef05300 0x200>,
> +                             <0x7ef05f00 0x80>,
> +                             <0x7ef05f80 0x80>,
> +                             <0x7ef06b00 0x200>,
> +                             <0x7ef06f00 0x400>,
> +                             <0x7ef00280 0x80>,
> +                             <0x7ef09300 0x100>,
> +                             <0x7ef20000 0x100>;
> +                       reg-names = "hdmi",
> +                                   "dvp",
> +                                   "phy",
> +                                   "rm",
> +                                   "packet",
> +                                   "metadata",
> +                                   "csc",
> +                                   "cec",
> +                                   "hd";
> +                       ddc = <&ddc1>;
> +                       clock-names = "hdmi", "clk-108M";
> +                       resets = <&dvp 1>;
> +                       dmas = <&dma 17>;
> +                       dma-names = "audio-rx";
> +                       status = "disabled";
> +               };
> +
> +               ddc1: i2c@7ef09500 {
> +                       compatible = "brcm,bcm2711-hdmi-i2c";
> +                       reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>;
> +                       reg-names = "bsc", "auto-i2c";
> +                       clock-frequency = <97500>;
> +                       status = "disabled";
> +               };
>         };
>
>         /*
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-29 14:09       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> the HVS and the PV, we need to add some delay after disabling the PV output
> and before disabling the HDMI controller. 20ms seems to be good enough so
> let's use that.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d0b326e1df0a..7b178d67187f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       mdelay(20);

mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
not msleep instead?

  Dave

> +
>         if (vc4_encoder->post_crtc_disable)
>                 vc4_encoder->post_crtc_disable(encoder);
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 14:09       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> the HVS and the PV, we need to add some delay after disabling the PV output
> and before disabling the HDMI controller. 20ms seems to be good enough so
> let's use that.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d0b326e1df0a..7b178d67187f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       mdelay(20);

mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
not msleep instead?

  Dave

> +
>         if (vc4_encoder->post_crtc_disable)
>                 vc4_encoder->post_crtc_disable(encoder);
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 14:09       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:09 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> the HVS and the PV, we need to add some delay after disabling the PV output
> and before disabling the HDMI controller. 20ms seems to be good enough so
> let's use that.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index d0b326e1df0a..7b178d67187f 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>
> +       mdelay(20);

mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
not msleep instead?

  Dave

> +
>         if (vc4_encoder->post_crtc_disable)
>                 vc4_encoder->post_crtc_disable(encoder);
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-29 14:31       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
> being connected to a pixelvalve, and some muxing between the FIFOs and
> outputs.
>
> Any output cannot feed from any FIFO though, and they all have a bunch of
> constraints.
>
> In order to support this, let's store the possible FIFOs each output can be
> assigned to in the vc4_crtc_data, and use that information at atomic_check
> time to iterate over all the CRTCs enabled and assign them FIFOs.
>
> The channel assigned is then set in the vc4_crtc_state so that the rest of
> the driver can use it.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
>  drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
>  drivers/gpu/drm/vc4/vc4_kms.c  | 167 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
>  drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
>  6 files changed, 199 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index fe2e5675aed4..b7e47ce1476c 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
>         unsigned int cob_size;
>         u32 val;
>         int fifo_lines;
> @@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>          * Read vertical scanline which is currently composed for our
>          * pixelvalve by the HVS, and also the scaler status.
>          */
> -       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
> +       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
>
>         /* Get optional system timestamp after query. */
>         if (etime)
> @@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>                         *hpos += mode->crtc_htotal / 2;
>         }
>
> -       cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
> +       cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
>         /* This is the offset we need for translating hvs -> pv scanout pos. */
>         fifo_lines = cob_size / mode->crtc_hdisplay;
>
> @@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> -       u32 chan = vc4_crtc->channel;
> +       u32 chan = vc4_state->assigned_channel;
>         unsigned long flags;
>
>         spin_lock_irqsave(&dev->event_lock, flags);
> @@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
>         old_vc4_state = to_vc4_crtc_state(crtc->state);
>         vc4_state->feed_txp = old_vc4_state->feed_txp;
>         vc4_state->margins = old_vc4_state->margins;
> +       vc4_state->assigned_channel = old_vc4_state->assigned_channel;
>
>         __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
>         return &vc4_state->base;
> @@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
>         .base = {
> +               .hvs_available_channels = BIT(0),
>                 .hvs_output = 0,
>         },
>         .debugfs_name = "crtc0_regs",
> @@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
>         .base = {
> +               .hvs_available_channels = BIT(2),
>                 .hvs_output = 2,
>         },
>         .debugfs_name = "crtc1_regs",
> @@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
>         .base = {
> +               .hvs_available_channels = BIT(1),
>                 .hvs_output = 1,
>         },
>         .debugfs_name = "crtc2_regs",
> @@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
>                                   crtc_funcs, NULL);
>         drm_crtc_helper_add(crtc, crtc_helper_funcs);
> -       vc4_crtc->channel = vc4_crtc->data->hvs_output;
>         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
>         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index d1cf4c038180..9e81ad8331f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_crtc_data {
> +       /* Bitmask of channels (FIFOs) of the HVS that the output can source from */
> +       unsigned int hvs_available_channels;
> +
>         /* Which output of the HVS this pixelvalve sources from. */
>         int hvs_output;
>  };
> @@ -471,9 +474,6 @@ struct vc4_crtc {
>         /* Timestamp at start of vblank irq - unaffected by lock delays. */
>         ktime_t t_vblank;
>
> -       /* Which HVS channel we're using for our CRTC. */
> -       int channel;
> -
>         u8 lut_r[256];
>         u8 lut_g[256];
>         u8 lut_b[256];
> @@ -509,6 +509,7 @@ struct vc4_crtc_state {
>         struct drm_mm_node mm;
>         bool feed_txp;
>         bool txp_armed;
> +       unsigned int assigned_channel;
>
>         struct {
>                 unsigned int left;
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 6fd9de1dc65a..50e88f634799 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         u32 i;
>
>         /* The LUT memory is laid out with each HVS channel in order,
> @@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
>          */
>         HVS_WRITE(SCALER_GAMADDR,
>                   SCALER_GAMADDR_AUTOINC |
> -                 (vc4_crtc->channel * 3 * crtc->gamma_size));
> +                 (vc4_state->assigned_channel * 3 * crtc->gamma_size));
>
>         for (i = 0; i < crtc->gamma_size; i++)
>                 HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
> @@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
>                         crtc->state->event = NULL;
>                 }
>
> -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
> +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
>                           vc4_state->mm.start);
>
>                 spin_unlock_irqrestore(&dev->event_lock, flags);
>         } else {
> -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
> +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
>                           vc4_state->mm.start);
>         }
>  }
> @@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool oneshot = vc4_state->feed_txp;
> @@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>                                           SCALER5_DISPCTRLX_HEIGHT) |
>                             (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
>
> -       HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
> +       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
>  }
>
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
> @@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> -       u32 chan = vc4_crtc->channel;
> +       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
> +       unsigned int chan = vc4_state->assigned_channel;
>
>         if (HVS_READ(SCALER_DISPCTRLX(chan)) &
>             SCALER_DISPCTRLX_ENABLE) {
> @@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_plane *plane;
>         struct vc4_plane_state *vc4_plane_state;
> @@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                 /* This sets a black background color fill, as is the case
>                  * with other DRM drivers.
>                  */
> -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
> -                         HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
> +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
> +                         HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
>                           SCALER_DISPBKGND_FILL);
>
>         /* Only update DISPLIST if the CRTC was already running and is not
> @@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                 vc4_hvs_update_dlist(crtc);
>
>         if (crtc->state->color_mgmt_changed) {
> -               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
> +               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
>
>                 if (crtc->state->gamma_lut) {
>                         vc4_hvs_update_gamma_lut(crtc);
> @@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                          */
>                         dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
>                 }
> -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
> +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
>         }
>
>         if (debug_dump_regs) {
> @@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
>
> -       if (vc4_crtc->data->hvs_output == 2) {
> +       if (vc4_state->assigned_channel == 2) {
>                 u32 dispctrl;
>                 u32 dsp3_mux;
>
> @@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>                 HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
>         }
>
> -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
> +       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
>                   SCALER_DISPBKGND_AUTOHS |
>                   SCALER_DISPBKGND_GAMMA |
>                   (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 717673b18132..7c8a87339959 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
>                   VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
>  }
>
> +static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
> +                                    struct drm_atomic_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned int i;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
> +               u32 dispctrl;
> +               u32 dsp3_mux;
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               if (vc4_state->assigned_channel != 2)
> +                       continue;
> +
> +               /*
> +                * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
> +                * FIFO X'.
> +                * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
> +                *
> +                * DSP3 is connected to FIFO2 unless the transposer is
> +                * enabled. In this case, FIFO 2 is directly accessed by the
> +                * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
> +                * route.
> +                */
> +               if (vc4_state->feed_txp)
> +                       dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
> +               else
> +                       dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
> +
> +               dispctrl = HVS_READ(SCALER_DISPCTRL) &
> +                          ~SCALER_DISPCTRL_DSP3_MUX_MASK;
> +               HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
> +       }
> +}
> +
> +static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
> +                                    struct drm_atomic_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned char dsp2_mux = 0;
> +       unsigned char dsp3_mux = 3;
> +       unsigned char dsp4_mux = 3;
> +       unsigned char dsp5_mux = 3;
> +       unsigned int i;
> +       u32 reg;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               switch (vc4_crtc->data->hvs_output) {
> +               case 2:
> +                       dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
> +                       break;
> +
> +               case 3:
> +                       dsp3_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               case 4:
> +                       dsp4_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               case 5:
> +                       dsp5_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       reg = HVS_READ(SCALER_DISPECTRL);
> +       HVS_WRITE(SCALER_DISPECTRL,
> +                 (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPCTRL);
> +       HVS_WRITE(SCALER_DISPCTRL,
> +                 (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPEOLN);
> +       HVS_WRITE(SCALER_DISPEOLN,
> +                 (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPDITHER);
> +       HVS_WRITE(SCALER_DISPDITHER,
> +                 (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
> +}
> +
>  static void
>  vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  {
> @@ -157,9 +258,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>         int i;
>
>         for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> -               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +               struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
>
> -               vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
> +               vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
>         }
>
>         if (vc4->hvs->hvs5)
> @@ -173,6 +274,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>
>         vc4_ctm_commit(vc4, state);
>
> +       if (vc4->hvs->hvs5)
> +               vc5_hvs_pv_muxing_commit(vc4, state);
> +       else
> +               vc4_hvs_pv_muxing_commit(vc4, state);
> +
>         drm_atomic_helper_commit_planes(dev, state, 0);
>
>         drm_atomic_helper_commit_modeset_enables(dev, state);
> @@ -382,8 +488,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
>
>                 /* CTM is being enabled or the matrix changed. */
>                 if (new_crtc_state->ctm) {
> +                       struct vc4_crtc_state *vc4_crtc_state =
> +                               to_vc4_crtc_state(new_crtc_state);
> +
>                         /* fifo is 1-based since 0 disables CTM. */
> -                       int fifo = to_vc4_crtc(crtc)->channel + 1;
> +                       int fifo = vc4_crtc_state->assigned_channel + 1;
>
>                         /* Check userland isn't trying to turn on CTM for more
>                          * than one CRTC at a time.
> @@ -493,10 +602,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
>         .atomic_destroy_state = vc4_load_tracker_destroy_state,
>  };
>
> +#define NUM_OUTPUTS  6
> +#define NUM_CHANNELS 3
> +
>  static int
>  vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
>  {
> -       int ret;
> +       unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       int i, ret;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_crtc_state =
> +                       to_vc4_crtc_state(crtc_state);
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +               unsigned int matching_channels;
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               /*
> +                * The problem we have to solve here is that we have
> +                * up to 7 encoders, connected to up to 6 CRTCs.
> +                *
> +                * Those CRTCs, depending on the instance, can be
> +                * routed to 1, 2 or 3 HVS FIFOs, and we need to set
> +                * the change the muxing between FIFOs and outputs in
> +                * the HVS accordingly.
> +                *
> +                * It would be pretty hard to come up with an
> +                * algorithm that would generically solve
> +                * this. However, the current routing trees we support
> +                * allow us to simplify a bit the problem.
> +                *
> +                * Indeed, with the current supported layouts, if we
> +                * try to assign in the ascending crtc index order the
> +                * FIFOs, we can't fall into the situation where an
> +                * earlier CRTC that had multiple routes is assigned
> +                * one that was the only option for a later CRTC.
> +                *
> +                * If the layout changes and doesn't give us that in
> +                * the future, we will need to have something smarter,
> +                * but it works so far.
> +                */
> +               matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
> +               if (matching_channels) {
> +                       unsigned int channel = ffs(matching_channels) - 1;
> +
> +                       vc4_crtc_state->assigned_channel = channel;
> +                       unassigned_channels &= ~BIT(channel);
> +               } else {
> +                       return -EINVAL;
> +               }
> +       }
>
>         ret = vc4_ctm_atomic_check(dev, state);
>         if (ret < 0)
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 91b785725555..7fbac68b6fe1 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -286,9 +286,19 @@
>
>  #define SCALER_DISPID                           0x00000008
>  #define SCALER_DISPECTRL                        0x0000000c
> +# define SCALER_DISPECTRL_DSP2_MUX_SHIFT       31
> +# define SCALER_DISPECTRL_DSP2_MUX_MASK                VC4_MASK(31, 31)
> +
>  #define SCALER_DISPPROF                         0x00000010
> +
>  #define SCALER_DISPDITHER                       0x00000014
> +# define SCALER_DISPDITHER_DSP5_MUX_SHIFT      30
> +# define SCALER_DISPDITHER_DSP5_MUX_MASK       VC4_MASK(31, 30)
> +
>  #define SCALER_DISPEOLN                         0x00000018
> +# define SCALER_DISPEOLN_DSP4_MUX_SHIFT                30
> +# define SCALER_DISPEOLN_DSP4_MUX_MASK         VC4_MASK(31, 30)
> +
>  #define SCALER_DISPLIST0                        0x00000020
>  #define SCALER_DISPLIST1                        0x00000024
>  #define SCALER_DISPLIST2                        0x00000028
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index f39d9900d027..a2380d856000 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>  }
>
>  static const struct vc4_crtc_data vc4_txp_crtc_data = {
> +       .hvs_available_channels = BIT(2),
>         .hvs_output = 2,
>  };
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically
@ 2020-07-29 14:31       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
> being connected to a pixelvalve, and some muxing between the FIFOs and
> outputs.
>
> Any output cannot feed from any FIFO though, and they all have a bunch of
> constraints.
>
> In order to support this, let's store the possible FIFOs each output can be
> assigned to in the vc4_crtc_data, and use that information at atomic_check
> time to iterate over all the CRTCs enabled and assign them FIFOs.
>
> The channel assigned is then set in the vc4_crtc_state so that the rest of
> the driver can use it.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
>  drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
>  drivers/gpu/drm/vc4/vc4_kms.c  | 167 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
>  drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
>  6 files changed, 199 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index fe2e5675aed4..b7e47ce1476c 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
>         unsigned int cob_size;
>         u32 val;
>         int fifo_lines;
> @@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>          * Read vertical scanline which is currently composed for our
>          * pixelvalve by the HVS, and also the scaler status.
>          */
> -       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
> +       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
>
>         /* Get optional system timestamp after query. */
>         if (etime)
> @@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>                         *hpos += mode->crtc_htotal / 2;
>         }
>
> -       cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
> +       cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
>         /* This is the offset we need for translating hvs -> pv scanout pos. */
>         fifo_lines = cob_size / mode->crtc_hdisplay;
>
> @@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> -       u32 chan = vc4_crtc->channel;
> +       u32 chan = vc4_state->assigned_channel;
>         unsigned long flags;
>
>         spin_lock_irqsave(&dev->event_lock, flags);
> @@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
>         old_vc4_state = to_vc4_crtc_state(crtc->state);
>         vc4_state->feed_txp = old_vc4_state->feed_txp;
>         vc4_state->margins = old_vc4_state->margins;
> +       vc4_state->assigned_channel = old_vc4_state->assigned_channel;
>
>         __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
>         return &vc4_state->base;
> @@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
>         .base = {
> +               .hvs_available_channels = BIT(0),
>                 .hvs_output = 0,
>         },
>         .debugfs_name = "crtc0_regs",
> @@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
>         .base = {
> +               .hvs_available_channels = BIT(2),
>                 .hvs_output = 2,
>         },
>         .debugfs_name = "crtc1_regs",
> @@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
>         .base = {
> +               .hvs_available_channels = BIT(1),
>                 .hvs_output = 1,
>         },
>         .debugfs_name = "crtc2_regs",
> @@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
>                                   crtc_funcs, NULL);
>         drm_crtc_helper_add(crtc, crtc_helper_funcs);
> -       vc4_crtc->channel = vc4_crtc->data->hvs_output;
>         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
>         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index d1cf4c038180..9e81ad8331f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_crtc_data {
> +       /* Bitmask of channels (FIFOs) of the HVS that the output can source from */
> +       unsigned int hvs_available_channels;
> +
>         /* Which output of the HVS this pixelvalve sources from. */
>         int hvs_output;
>  };
> @@ -471,9 +474,6 @@ struct vc4_crtc {
>         /* Timestamp at start of vblank irq - unaffected by lock delays. */
>         ktime_t t_vblank;
>
> -       /* Which HVS channel we're using for our CRTC. */
> -       int channel;
> -
>         u8 lut_r[256];
>         u8 lut_g[256];
>         u8 lut_b[256];
> @@ -509,6 +509,7 @@ struct vc4_crtc_state {
>         struct drm_mm_node mm;
>         bool feed_txp;
>         bool txp_armed;
> +       unsigned int assigned_channel;
>
>         struct {
>                 unsigned int left;
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 6fd9de1dc65a..50e88f634799 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         u32 i;
>
>         /* The LUT memory is laid out with each HVS channel in order,
> @@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
>          */
>         HVS_WRITE(SCALER_GAMADDR,
>                   SCALER_GAMADDR_AUTOINC |
> -                 (vc4_crtc->channel * 3 * crtc->gamma_size));
> +                 (vc4_state->assigned_channel * 3 * crtc->gamma_size));
>
>         for (i = 0; i < crtc->gamma_size; i++)
>                 HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
> @@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
>                         crtc->state->event = NULL;
>                 }
>
> -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
> +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
>                           vc4_state->mm.start);
>
>                 spin_unlock_irqrestore(&dev->event_lock, flags);
>         } else {
> -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
> +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
>                           vc4_state->mm.start);
>         }
>  }
> @@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool oneshot = vc4_state->feed_txp;
> @@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>                                           SCALER5_DISPCTRLX_HEIGHT) |
>                             (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
>
> -       HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
> +       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
>  }
>
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
> @@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> -       u32 chan = vc4_crtc->channel;
> +       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
> +       unsigned int chan = vc4_state->assigned_channel;
>
>         if (HVS_READ(SCALER_DISPCTRLX(chan)) &
>             SCALER_DISPCTRLX_ENABLE) {
> @@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_plane *plane;
>         struct vc4_plane_state *vc4_plane_state;
> @@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                 /* This sets a black background color fill, as is the case
>                  * with other DRM drivers.
>                  */
> -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
> -                         HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
> +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
> +                         HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
>                           SCALER_DISPBKGND_FILL);
>
>         /* Only update DISPLIST if the CRTC was already running and is not
> @@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                 vc4_hvs_update_dlist(crtc);
>
>         if (crtc->state->color_mgmt_changed) {
> -               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
> +               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
>
>                 if (crtc->state->gamma_lut) {
>                         vc4_hvs_update_gamma_lut(crtc);
> @@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                          */
>                         dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
>                 }
> -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
> +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
>         }
>
>         if (debug_dump_regs) {
> @@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
>
> -       if (vc4_crtc->data->hvs_output == 2) {
> +       if (vc4_state->assigned_channel == 2) {
>                 u32 dispctrl;
>                 u32 dsp3_mux;
>
> @@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>                 HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
>         }
>
> -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
> +       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
>                   SCALER_DISPBKGND_AUTOHS |
>                   SCALER_DISPBKGND_GAMMA |
>                   (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 717673b18132..7c8a87339959 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
>                   VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
>  }
>
> +static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
> +                                    struct drm_atomic_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned int i;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
> +               u32 dispctrl;
> +               u32 dsp3_mux;
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               if (vc4_state->assigned_channel != 2)
> +                       continue;
> +
> +               /*
> +                * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
> +                * FIFO X'.
> +                * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
> +                *
> +                * DSP3 is connected to FIFO2 unless the transposer is
> +                * enabled. In this case, FIFO 2 is directly accessed by the
> +                * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
> +                * route.
> +                */
> +               if (vc4_state->feed_txp)
> +                       dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
> +               else
> +                       dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
> +
> +               dispctrl = HVS_READ(SCALER_DISPCTRL) &
> +                          ~SCALER_DISPCTRL_DSP3_MUX_MASK;
> +               HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
> +       }
> +}
> +
> +static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
> +                                    struct drm_atomic_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned char dsp2_mux = 0;
> +       unsigned char dsp3_mux = 3;
> +       unsigned char dsp4_mux = 3;
> +       unsigned char dsp5_mux = 3;
> +       unsigned int i;
> +       u32 reg;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               switch (vc4_crtc->data->hvs_output) {
> +               case 2:
> +                       dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
> +                       break;
> +
> +               case 3:
> +                       dsp3_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               case 4:
> +                       dsp4_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               case 5:
> +                       dsp5_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       reg = HVS_READ(SCALER_DISPECTRL);
> +       HVS_WRITE(SCALER_DISPECTRL,
> +                 (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPCTRL);
> +       HVS_WRITE(SCALER_DISPCTRL,
> +                 (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPEOLN);
> +       HVS_WRITE(SCALER_DISPEOLN,
> +                 (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPDITHER);
> +       HVS_WRITE(SCALER_DISPDITHER,
> +                 (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
> +}
> +
>  static void
>  vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  {
> @@ -157,9 +258,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>         int i;
>
>         for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> -               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +               struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
>
> -               vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
> +               vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
>         }
>
>         if (vc4->hvs->hvs5)
> @@ -173,6 +274,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>
>         vc4_ctm_commit(vc4, state);
>
> +       if (vc4->hvs->hvs5)
> +               vc5_hvs_pv_muxing_commit(vc4, state);
> +       else
> +               vc4_hvs_pv_muxing_commit(vc4, state);
> +
>         drm_atomic_helper_commit_planes(dev, state, 0);
>
>         drm_atomic_helper_commit_modeset_enables(dev, state);
> @@ -382,8 +488,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
>
>                 /* CTM is being enabled or the matrix changed. */
>                 if (new_crtc_state->ctm) {
> +                       struct vc4_crtc_state *vc4_crtc_state =
> +                               to_vc4_crtc_state(new_crtc_state);
> +
>                         /* fifo is 1-based since 0 disables CTM. */
> -                       int fifo = to_vc4_crtc(crtc)->channel + 1;
> +                       int fifo = vc4_crtc_state->assigned_channel + 1;
>
>                         /* Check userland isn't trying to turn on CTM for more
>                          * than one CRTC at a time.
> @@ -493,10 +602,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
>         .atomic_destroy_state = vc4_load_tracker_destroy_state,
>  };
>
> +#define NUM_OUTPUTS  6
> +#define NUM_CHANNELS 3
> +
>  static int
>  vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
>  {
> -       int ret;
> +       unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       int i, ret;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_crtc_state =
> +                       to_vc4_crtc_state(crtc_state);
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +               unsigned int matching_channels;
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               /*
> +                * The problem we have to solve here is that we have
> +                * up to 7 encoders, connected to up to 6 CRTCs.
> +                *
> +                * Those CRTCs, depending on the instance, can be
> +                * routed to 1, 2 or 3 HVS FIFOs, and we need to set
> +                * the change the muxing between FIFOs and outputs in
> +                * the HVS accordingly.
> +                *
> +                * It would be pretty hard to come up with an
> +                * algorithm that would generically solve
> +                * this. However, the current routing trees we support
> +                * allow us to simplify a bit the problem.
> +                *
> +                * Indeed, with the current supported layouts, if we
> +                * try to assign in the ascending crtc index order the
> +                * FIFOs, we can't fall into the situation where an
> +                * earlier CRTC that had multiple routes is assigned
> +                * one that was the only option for a later CRTC.
> +                *
> +                * If the layout changes and doesn't give us that in
> +                * the future, we will need to have something smarter,
> +                * but it works so far.
> +                */
> +               matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
> +               if (matching_channels) {
> +                       unsigned int channel = ffs(matching_channels) - 1;
> +
> +                       vc4_crtc_state->assigned_channel = channel;
> +                       unassigned_channels &= ~BIT(channel);
> +               } else {
> +                       return -EINVAL;
> +               }
> +       }
>
>         ret = vc4_ctm_atomic_check(dev, state);
>         if (ret < 0)
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 91b785725555..7fbac68b6fe1 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -286,9 +286,19 @@
>
>  #define SCALER_DISPID                           0x00000008
>  #define SCALER_DISPECTRL                        0x0000000c
> +# define SCALER_DISPECTRL_DSP2_MUX_SHIFT       31
> +# define SCALER_DISPECTRL_DSP2_MUX_MASK                VC4_MASK(31, 31)
> +
>  #define SCALER_DISPPROF                         0x00000010
> +
>  #define SCALER_DISPDITHER                       0x00000014
> +# define SCALER_DISPDITHER_DSP5_MUX_SHIFT      30
> +# define SCALER_DISPDITHER_DSP5_MUX_MASK       VC4_MASK(31, 30)
> +
>  #define SCALER_DISPEOLN                         0x00000018
> +# define SCALER_DISPEOLN_DSP4_MUX_SHIFT                30
> +# define SCALER_DISPEOLN_DSP4_MUX_MASK         VC4_MASK(31, 30)
> +
>  #define SCALER_DISPLIST0                        0x00000020
>  #define SCALER_DISPLIST1                        0x00000024
>  #define SCALER_DISPLIST2                        0x00000028
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index f39d9900d027..a2380d856000 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>  }
>
>  static const struct vc4_crtc_data vc4_txp_crtc_data = {
> +       .hvs_available_channels = BIT(2),
>         .hvs_output = 2,
>  };
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically
@ 2020-07-29 14:31       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The HVS found in the BCM2711 has 6 outputs and 3 FIFOs, with each output
> being connected to a pixelvalve, and some muxing between the FIFOs and
> outputs.
>
> Any output cannot feed from any FIFO though, and they all have a bunch of
> constraints.
>
> In order to support this, let's store the possible FIFOs each output can be
> assigned to in the vc4_crtc_data, and use that information at atomic_check
> time to iterate over all the CRTCs enabled and assign them FIFOs.
>
> The channel assigned is then set in the vc4_crtc_state so that the rest of
> the driver can use it.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c |  12 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |   7 +-
>  drivers/gpu/drm/vc4/vc4_hvs.c  |  28 ++----
>  drivers/gpu/drm/vc4/vc4_kms.c  | 167 +++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_regs.h |  10 ++-
>  drivers/gpu/drm/vc4/vc4_txp.c  |   1 +-
>  6 files changed, 199 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index fe2e5675aed4..b7e47ce1476c 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -88,6 +88,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
>         unsigned int cob_size;
>         u32 val;
>         int fifo_lines;
> @@ -104,7 +105,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>          * Read vertical scanline which is currently composed for our
>          * pixelvalve by the HVS, and also the scaler status.
>          */
> -       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc->channel));
> +       val = HVS_READ(SCALER_DISPSTATX(vc4_crtc_state->assigned_channel));
>
>         /* Get optional system timestamp after query. */
>         if (etime)
> @@ -124,7 +125,7 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
>                         *hpos += mode->crtc_htotal / 2;
>         }
>
> -       cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc->channel);
> +       cob_size = vc4_crtc_get_cob_allocation(vc4, vc4_crtc_state->assigned_channel);
>         /* This is the offset we need for translating hvs -> pv scanout pos. */
>         fifo_lines = cob_size / mode->crtc_hdisplay;
>
> @@ -520,7 +521,7 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> -       u32 chan = vc4_crtc->channel;
> +       u32 chan = vc4_state->assigned_channel;
>         unsigned long flags;
>
>         spin_lock_irqsave(&dev->event_lock, flags);
> @@ -719,6 +720,7 @@ struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
>         old_vc4_state = to_vc4_crtc_state(crtc->state);
>         vc4_state->feed_txp = old_vc4_state->feed_txp;
>         vc4_state->margins = old_vc4_state->margins;
> +       vc4_state->assigned_channel = old_vc4_state->assigned_channel;
>
>         __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base);
>         return &vc4_state->base;
> @@ -779,6 +781,7 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
>         .base = {
> +               .hvs_available_channels = BIT(0),
>                 .hvs_output = 0,
>         },
>         .debugfs_name = "crtc0_regs",
> @@ -791,6 +794,7 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
>         .base = {
> +               .hvs_available_channels = BIT(2),
>                 .hvs_output = 2,
>         },
>         .debugfs_name = "crtc1_regs",
> @@ -803,6 +807,7 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
>         .base = {
> +               .hvs_available_channels = BIT(1),
>                 .hvs_output = 1,
>         },
>         .debugfs_name = "crtc2_regs",
> @@ -866,7 +871,6 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>         drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
>                                   crtc_funcs, NULL);
>         drm_crtc_helper_add(crtc, crtc_helper_funcs);
> -       vc4_crtc->channel = vc4_crtc->data->hvs_output;
>         drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
>         drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index d1cf4c038180..9e81ad8331f1 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -447,6 +447,9 @@ to_vc4_encoder(struct drm_encoder *encoder)
>  }
>
>  struct vc4_crtc_data {
> +       /* Bitmask of channels (FIFOs) of the HVS that the output can source from */
> +       unsigned int hvs_available_channels;
> +
>         /* Which output of the HVS this pixelvalve sources from. */
>         int hvs_output;
>  };
> @@ -471,9 +474,6 @@ struct vc4_crtc {
>         /* Timestamp at start of vblank irq - unaffected by lock delays. */
>         ktime_t t_vblank;
>
> -       /* Which HVS channel we're using for our CRTC. */
> -       int channel;
> -
>         u8 lut_r[256];
>         u8 lut_g[256];
>         u8 lut_b[256];
> @@ -509,6 +509,7 @@ struct vc4_crtc_state {
>         struct drm_mm_node mm;
>         bool feed_txp;
>         bool txp_armed;
> +       unsigned int assigned_channel;
>
>         struct {
>                 unsigned int left;
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 6fd9de1dc65a..50e88f634799 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -161,6 +161,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         u32 i;
>
>         /* The LUT memory is laid out with each HVS channel in order,
> @@ -169,7 +170,7 @@ static void vc4_hvs_lut_load(struct drm_crtc *crtc)
>          */
>         HVS_WRITE(SCALER_GAMADDR,
>                   SCALER_GAMADDR_AUTOINC |
> -                 (vc4_crtc->channel * 3 * crtc->gamma_size));
> +                 (vc4_state->assigned_channel * 3 * crtc->gamma_size));
>
>         for (i = 0; i < crtc->gamma_size; i++)
>                 HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
> @@ -249,12 +250,12 @@ static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
>                         crtc->state->event = NULL;
>                 }
>
> -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
> +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
>                           vc4_state->mm.start);
>
>                 spin_unlock_irqrestore(&dev->event_lock, flags);
>         } else {
> -               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
> +               HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
>                           vc4_state->mm.start);
>         }
>  }
> @@ -264,7 +265,6 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool oneshot = vc4_state->feed_txp;
> @@ -292,7 +292,7 @@ void vc4_hvs_atomic_enable(struct drm_crtc *crtc,
>                                           SCALER5_DISPCTRLX_HEIGHT) |
>                             (oneshot ? SCALER5_DISPCTRLX_ONESHOT : 0);
>
> -       HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);
> +       HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl);
>  }
>
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
> @@ -300,8 +300,8 @@ void vc4_hvs_atomic_disable(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> -       u32 chan = vc4_crtc->channel;
> +       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(old_state);
> +       unsigned int chan = vc4_state->assigned_channel;
>
>         if (HVS_READ(SCALER_DISPCTRLX(chan)) &
>             SCALER_DISPCTRLX_ENABLE) {
> @@ -332,7 +332,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_plane *plane;
>         struct vc4_plane_state *vc4_plane_state;
> @@ -374,8 +373,8 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                 /* This sets a black background color fill, as is the case
>                  * with other DRM drivers.
>                  */
> -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
> -                         HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel)) |
> +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
> +                         HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel)) |
>                           SCALER_DISPBKGND_FILL);
>
>         /* Only update DISPLIST if the CRTC was already running and is not
> @@ -389,7 +388,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                 vc4_hvs_update_dlist(crtc);
>
>         if (crtc->state->color_mgmt_changed) {
> -               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_crtc->channel));
> +               u32 dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(vc4_state->assigned_channel));
>
>                 if (crtc->state->gamma_lut) {
>                         vc4_hvs_update_gamma_lut(crtc);
> @@ -401,7 +400,7 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>                          */
>                         dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
>                 }
> -               HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel), dispbkgndx);
> +               HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel), dispbkgndx);
>         }
>
>         if (debug_dump_regs) {
> @@ -414,12 +413,11 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>  {
>         struct drm_device *dev = crtc->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
>         struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
>         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
>         bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
>
> -       if (vc4_crtc->data->hvs_output == 2) {
> +       if (vc4_state->assigned_channel == 2) {
>                 u32 dispctrl;
>                 u32 dsp3_mux;
>
> @@ -443,7 +441,7 @@ void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
>                 HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
>         }
>
> -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
> +       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
>                   SCALER_DISPBKGND_AUTOHS |
>                   SCALER_DISPBKGND_GAMMA |
>                   (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 717673b18132..7c8a87339959 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -146,6 +146,107 @@ vc4_ctm_commit(struct vc4_dev *vc4, struct drm_atomic_state *state)
>                   VC4_SET_FIELD(ctm_state->fifo, SCALER_OLEDOFFS_DISPFIFO));
>  }
>
> +static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4,
> +                                    struct drm_atomic_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned int i;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
> +               u32 dispctrl;
> +               u32 dsp3_mux;
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               if (vc4_state->assigned_channel != 2)
> +                       continue;
> +
> +               /*
> +                * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
> +                * FIFO X'.
> +                * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
> +                *
> +                * DSP3 is connected to FIFO2 unless the transposer is
> +                * enabled. In this case, FIFO 2 is directly accessed by the
> +                * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
> +                * route.
> +                */
> +               if (vc4_state->feed_txp)
> +                       dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
> +               else
> +                       dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
> +
> +               dispctrl = HVS_READ(SCALER_DISPCTRL) &
> +                          ~SCALER_DISPCTRL_DSP3_MUX_MASK;
> +               HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
> +       }
> +}
> +
> +static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4,
> +                                    struct drm_atomic_state *state)
> +{
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       unsigned char dsp2_mux = 0;
> +       unsigned char dsp3_mux = 3;
> +       unsigned char dsp4_mux = 3;
> +       unsigned char dsp5_mux = 3;
> +       unsigned int i;
> +       u32 reg;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state);
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               switch (vc4_crtc->data->hvs_output) {
> +               case 2:
> +                       dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1;
> +                       break;
> +
> +               case 3:
> +                       dsp3_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               case 4:
> +                       dsp4_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               case 5:
> +                       dsp5_mux = vc4_state->assigned_channel;
> +                       break;
> +
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       reg = HVS_READ(SCALER_DISPECTRL);
> +       HVS_WRITE(SCALER_DISPECTRL,
> +                 (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPCTRL);
> +       HVS_WRITE(SCALER_DISPCTRL,
> +                 (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPEOLN);
> +       HVS_WRITE(SCALER_DISPEOLN,
> +                 (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX));
> +
> +       reg = HVS_READ(SCALER_DISPDITHER);
> +       HVS_WRITE(SCALER_DISPDITHER,
> +                 (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) |
> +                 VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX));
> +}
> +
>  static void
>  vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  {
> @@ -157,9 +258,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>         int i;
>
>         for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> -               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +               struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(new_crtc_state);
>
> -               vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
> +               vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel);
>         }
>
>         if (vc4->hvs->hvs5)
> @@ -173,6 +274,11 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>
>         vc4_ctm_commit(vc4, state);
>
> +       if (vc4->hvs->hvs5)
> +               vc5_hvs_pv_muxing_commit(vc4, state);
> +       else
> +               vc4_hvs_pv_muxing_commit(vc4, state);
> +
>         drm_atomic_helper_commit_planes(dev, state, 0);
>
>         drm_atomic_helper_commit_modeset_enables(dev, state);
> @@ -382,8 +488,11 @@ vc4_ctm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
>
>                 /* CTM is being enabled or the matrix changed. */
>                 if (new_crtc_state->ctm) {
> +                       struct vc4_crtc_state *vc4_crtc_state =
> +                               to_vc4_crtc_state(new_crtc_state);
> +
>                         /* fifo is 1-based since 0 disables CTM. */
> -                       int fifo = to_vc4_crtc(crtc)->channel + 1;
> +                       int fifo = vc4_crtc_state->assigned_channel + 1;
>
>                         /* Check userland isn't trying to turn on CTM for more
>                          * than one CRTC at a time.
> @@ -493,10 +602,60 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = {
>         .atomic_destroy_state = vc4_load_tracker_destroy_state,
>  };
>
> +#define NUM_OUTPUTS  6
> +#define NUM_CHANNELS 3
> +
>  static int
>  vc4_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
>  {
> -       int ret;
> +       unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0);
> +       struct drm_crtc_state *crtc_state;
> +       struct drm_crtc *crtc;
> +       int i, ret;
> +
> +       for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +               struct vc4_crtc_state *vc4_crtc_state =
> +                       to_vc4_crtc_state(crtc_state);
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> +               unsigned int matching_channels;
> +
> +               if (!crtc_state->active)
> +                       continue;
> +
> +               /*
> +                * The problem we have to solve here is that we have
> +                * up to 7 encoders, connected to up to 6 CRTCs.
> +                *
> +                * Those CRTCs, depending on the instance, can be
> +                * routed to 1, 2 or 3 HVS FIFOs, and we need to set
> +                * the change the muxing between FIFOs and outputs in
> +                * the HVS accordingly.
> +                *
> +                * It would be pretty hard to come up with an
> +                * algorithm that would generically solve
> +                * this. However, the current routing trees we support
> +                * allow us to simplify a bit the problem.
> +                *
> +                * Indeed, with the current supported layouts, if we
> +                * try to assign in the ascending crtc index order the
> +                * FIFOs, we can't fall into the situation where an
> +                * earlier CRTC that had multiple routes is assigned
> +                * one that was the only option for a later CRTC.
> +                *
> +                * If the layout changes and doesn't give us that in
> +                * the future, we will need to have something smarter,
> +                * but it works so far.
> +                */
> +               matching_channels = unassigned_channels & vc4_crtc->data->hvs_available_channels;
> +               if (matching_channels) {
> +                       unsigned int channel = ffs(matching_channels) - 1;
> +
> +                       vc4_crtc_state->assigned_channel = channel;
> +                       unassigned_channels &= ~BIT(channel);
> +               } else {
> +                       return -EINVAL;
> +               }
> +       }
>
>         ret = vc4_ctm_atomic_check(dev, state);
>         if (ret < 0)
> diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h
> index 91b785725555..7fbac68b6fe1 100644
> --- a/drivers/gpu/drm/vc4/vc4_regs.h
> +++ b/drivers/gpu/drm/vc4/vc4_regs.h
> @@ -286,9 +286,19 @@
>
>  #define SCALER_DISPID                           0x00000008
>  #define SCALER_DISPECTRL                        0x0000000c
> +# define SCALER_DISPECTRL_DSP2_MUX_SHIFT       31
> +# define SCALER_DISPECTRL_DSP2_MUX_MASK                VC4_MASK(31, 31)
> +
>  #define SCALER_DISPPROF                         0x00000010
> +
>  #define SCALER_DISPDITHER                       0x00000014
> +# define SCALER_DISPDITHER_DSP5_MUX_SHIFT      30
> +# define SCALER_DISPDITHER_DSP5_MUX_MASK       VC4_MASK(31, 30)
> +
>  #define SCALER_DISPEOLN                         0x00000018
> +# define SCALER_DISPEOLN_DSP4_MUX_SHIFT                30
> +# define SCALER_DISPEOLN_DSP4_MUX_MASK         VC4_MASK(31, 30)
> +
>  #define SCALER_DISPLIST0                        0x00000020
>  #define SCALER_DISPLIST1                        0x00000024
>  #define SCALER_DISPLIST2                        0x00000028
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index f39d9900d027..a2380d856000 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -452,6 +452,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
>  }
>
>  static const struct vc4_crtc_data vc4_txp_crtc_data = {
> +       .hvs_available_channels = BIT(2),
>         .hvs_output = 2,
>  };
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-07-29 14:09       ` Dave Stevenson
  (?)
@ 2020-07-29 14:42         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-29 14:42 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

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

Hi,

On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > In order to avoid pixels getting stuck in the (unflushable) FIFO between
> > the HVS and the PV, we need to add some delay after disabling the PV output
> > and before disabling the HDMI controller. 20ms seems to be good enough so
> > let's use that.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > index d0b326e1df0a..7b178d67187f 100644
> > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >
> > +       mdelay(20);
> 
> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> not msleep instead?

Since the timing was fairly critical, sleeping didn't seem like a good
solution since there's definitely some chance you overshoot and end up
with a higher time than the one you targeted.

Maxime

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

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 14:42         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-29 14:42 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi,

On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > In order to avoid pixels getting stuck in the (unflushable) FIFO between
> > the HVS and the PV, we need to add some delay after disabling the PV output
> > and before disabling the HDMI controller. 20ms seems to be good enough so
> > let's use that.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > index d0b326e1df0a..7b178d67187f 100644
> > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >
> > +       mdelay(20);
> 
> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> not msleep instead?

Since the timing was fairly critical, sleeping didn't seem like a good
solution since there's definitely some chance you overshoot and end up
with a higher time than the one you targeted.

Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 14:42         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-07-29 14:42 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel


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

Hi,

On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > In order to avoid pixels getting stuck in the (unflushable) FIFO between
> > the HVS and the PV, we need to add some delay after disabling the PV output
> > and before disabling the HDMI controller. 20ms seems to be good enough so
> > let's use that.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > index d0b326e1df0a..7b178d67187f 100644
> > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >
> > +       mdelay(20);
> 
> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> not msleep instead?

Since the timing was fairly critical, sleeping didn't seem like a good
solution since there's definitely some chance you overshoot and end up
with a higher time than the one you targeted.

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-29 14:42       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:42 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Since most of the HVS channel is setup in the init function, let's move the
> gamma setup there too. As this makes the HVS mode_set function empty, let's
> remove it in the process.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c |  2 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |  1 +-
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 59 +++++++++--------------------------
>  drivers/gpu/drm/vc4/vc4_txp.c  |  1 +-
>  4 files changed, 16 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 181d3fd57bc7..284a85b9d7d4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>  static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  {
>         vc4_crtc_config_pv(crtc);
> -
> -       vc4_hvs_mode_set_nofb(crtc);
>  }
>
>  static void require_hvs_enabled(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 4126506b3a69..dfcc684f5d28 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
>  void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
>  void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
> -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc);
>  void vc4_hvs_dump_state(struct drm_device *dev);
>  void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
>  void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 78bb1c0b0b76..c7de77afbf0a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>  {
>         struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
>         unsigned int chan = vc4_crtc_state->assigned_channel;
> +       bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +       u32 dispbkgndx;
>         u32 dispctrl;
>
>         /* Turn on the scaler, which will wait for vstart to start
> @@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>
>         HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
>
> +       dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
> +       dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
> +       dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
> +
> +       HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
> +                 SCALER_DISPBKGND_AUTOHS |
> +                 ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
> +                 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> +
> +       /* Reload the LUT, since the SRAMs would have been disabled if
> +        * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
> +        */
> +       vc4_hvs_lut_load(crtc);
> +
>         return 0;
>  }
>
> @@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>         }
>  }
>
> -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> -       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> -       bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
> -
> -       if (vc4_state->assigned_channel == 2) {
> -               u32 dispctrl;
> -               u32 dsp3_mux;
> -
> -               /*
> -                * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
> -                * FIFO X'.
> -                * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
> -                *
> -                * DSP3 is connected to FIFO2 unless the transposer is
> -                * enabled. In this case, FIFO 2 is directly accessed by the
> -                * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
> -                * route.
> -                */
> -               if (vc4_state->feed_txp)
> -                       dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
> -               else
> -                       dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
> -
> -               dispctrl = HVS_READ(SCALER_DISPCTRL) &
> -                          ~SCALER_DISPCTRL_DSP3_MUX_MASK;
> -               HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
> -       }
> -
> -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
> -                 SCALER_DISPBKGND_AUTOHS |
> -                 ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
> -                 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> -
> -       /* Reload the LUT, since the SRAMs would have been disabled if
> -        * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
> -        */
> -       vc4_hvs_lut_load(crtc);
> -}
> -
>  void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
>  {
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index a2380d856000..849dcafbfff1 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
>         .atomic_flush   = vc4_hvs_atomic_flush,
>         .atomic_enable  = vc4_txp_atomic_enable,
>         .atomic_disable = vc4_txp_atomic_disable,
> -       .mode_set_nofb  = vc4_hvs_mode_set_nofb,
>  };
>
>  static irqreturn_t vc4_txp_interrupt(int irq, void *data)
> --
> git-series 0.9.1

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

* Re: [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
@ 2020-07-29 14:42       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:42 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Since most of the HVS channel is setup in the init function, let's move the
> gamma setup there too. As this makes the HVS mode_set function empty, let's
> remove it in the process.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c |  2 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |  1 +-
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 59 +++++++++--------------------------
>  drivers/gpu/drm/vc4/vc4_txp.c  |  1 +-
>  4 files changed, 16 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 181d3fd57bc7..284a85b9d7d4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>  static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  {
>         vc4_crtc_config_pv(crtc);
> -
> -       vc4_hvs_mode_set_nofb(crtc);
>  }
>
>  static void require_hvs_enabled(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 4126506b3a69..dfcc684f5d28 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
>  void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
>  void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
> -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc);
>  void vc4_hvs_dump_state(struct drm_device *dev);
>  void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
>  void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 78bb1c0b0b76..c7de77afbf0a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>  {
>         struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
>         unsigned int chan = vc4_crtc_state->assigned_channel;
> +       bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +       u32 dispbkgndx;
>         u32 dispctrl;
>
>         /* Turn on the scaler, which will wait for vstart to start
> @@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>
>         HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
>
> +       dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
> +       dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
> +       dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
> +
> +       HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
> +                 SCALER_DISPBKGND_AUTOHS |
> +                 ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
> +                 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> +
> +       /* Reload the LUT, since the SRAMs would have been disabled if
> +        * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
> +        */
> +       vc4_hvs_lut_load(crtc);
> +
>         return 0;
>  }
>
> @@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>         }
>  }
>
> -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> -       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> -       bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
> -
> -       if (vc4_state->assigned_channel == 2) {
> -               u32 dispctrl;
> -               u32 dsp3_mux;
> -
> -               /*
> -                * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
> -                * FIFO X'.
> -                * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
> -                *
> -                * DSP3 is connected to FIFO2 unless the transposer is
> -                * enabled. In this case, FIFO 2 is directly accessed by the
> -                * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
> -                * route.
> -                */
> -               if (vc4_state->feed_txp)
> -                       dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
> -               else
> -                       dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
> -
> -               dispctrl = HVS_READ(SCALER_DISPCTRL) &
> -                          ~SCALER_DISPCTRL_DSP3_MUX_MASK;
> -               HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
> -       }
> -
> -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
> -                 SCALER_DISPBKGND_AUTOHS |
> -                 ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
> -                 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> -
> -       /* Reload the LUT, since the SRAMs would have been disabled if
> -        * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
> -        */
> -       vc4_hvs_lut_load(crtc);
> -}
> -
>  void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
>  {
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index a2380d856000..849dcafbfff1 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
>         .atomic_flush   = vc4_hvs_atomic_flush,
>         .atomic_enable  = vc4_txp_atomic_enable,
>         .atomic_disable = vc4_txp_atomic_disable,
> -       .mode_set_nofb  = vc4_hvs_mode_set_nofb,
>  };
>
>  static irqreturn_t vc4_txp_interrupt(int irq, void *data)
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
@ 2020-07-29 14:42       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:42 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Since most of the HVS channel is setup in the init function, let's move the
> gamma setup there too. As this makes the HVS mode_set function empty, let's
> remove it in the process.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c |  2 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |  1 +-
>  drivers/gpu/drm/vc4/vc4_hvs.c  | 59 +++++++++--------------------------
>  drivers/gpu/drm/vc4/vc4_txp.c  |  1 +-
>  4 files changed, 16 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 181d3fd57bc7..284a85b9d7d4 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -379,8 +379,6 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
>  static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc)
>  {
>         vc4_crtc_config_pv(crtc);
> -
> -       vc4_hvs_mode_set_nofb(crtc);
>  }
>
>  static void require_hvs_enabled(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 4126506b3a69..dfcc684f5d28 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -904,7 +904,6 @@ int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
>  void vc4_hvs_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
>  void vc4_hvs_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state);
>  void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *state);
> -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc);
>  void vc4_hvs_dump_state(struct drm_device *dev);
>  void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel);
>  void vc4_hvs_mask_underrun(struct drm_device *dev, int channel);
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 78bb1c0b0b76..c7de77afbf0a 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -201,6 +201,8 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>  {
>         struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
>         unsigned int chan = vc4_crtc_state->assigned_channel;
> +       bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
> +       u32 dispbkgndx;
>         u32 dispctrl;
>
>         /* Turn on the scaler, which will wait for vstart to start
> @@ -225,6 +227,20 @@ static int vc4_hvs_init_channel(struct vc4_dev *vc4, struct drm_crtc *crtc,
>
>         HVS_WRITE(SCALER_DISPCTRLX(chan), dispctrl);
>
> +       dispbkgndx = HVS_READ(SCALER_DISPBKGNDX(chan));
> +       dispbkgndx &= ~SCALER_DISPBKGND_GAMMA;
> +       dispbkgndx &= ~SCALER_DISPBKGND_INTERLACE;
> +
> +       HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
> +                 SCALER_DISPBKGND_AUTOHS |
> +                 ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
> +                 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> +
> +       /* Reload the LUT, since the SRAMs would have been disabled if
> +        * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
> +        */
> +       vc4_hvs_lut_load(crtc);
> +
>         return 0;
>  }
>
> @@ -421,49 +437,6 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
>         }
>  }
>
> -void vc4_hvs_mode_set_nofb(struct drm_crtc *crtc)
> -{
> -       struct drm_device *dev = crtc->dev;
> -       struct vc4_dev *vc4 = to_vc4_dev(dev);
> -       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> -       struct drm_display_mode *mode = &crtc->state->adjusted_mode;
> -       bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
> -
> -       if (vc4_state->assigned_channel == 2) {
> -               u32 dispctrl;
> -               u32 dsp3_mux;
> -
> -               /*
> -                * SCALER_DISPCTRL_DSP3 = X, where X < 2 means 'connect DSP3 to
> -                * FIFO X'.
> -                * SCALER_DISPCTRL_DSP3 = 3 means 'disable DSP 3'.
> -                *
> -                * DSP3 is connected to FIFO2 unless the transposer is
> -                * enabled. In this case, FIFO 2 is directly accessed by the
> -                * TXP IP, and we need to disable the FIFO2 -> pixelvalve1
> -                * route.
> -                */
> -               if (vc4_state->feed_txp)
> -                       dsp3_mux = VC4_SET_FIELD(3, SCALER_DISPCTRL_DSP3_MUX);
> -               else
> -                       dsp3_mux = VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
> -
> -               dispctrl = HVS_READ(SCALER_DISPCTRL) &
> -                          ~SCALER_DISPCTRL_DSP3_MUX_MASK;
> -               HVS_WRITE(SCALER_DISPCTRL, dispctrl | dsp3_mux);
> -       }
> -
> -       HVS_WRITE(SCALER_DISPBKGNDX(vc4_state->assigned_channel),
> -                 SCALER_DISPBKGND_AUTOHS |
> -                 ((!vc4->hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) |
> -                 (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
> -
> -       /* Reload the LUT, since the SRAMs would have been disabled if
> -        * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
> -        */
> -       vc4_hvs_lut_load(crtc);
> -}
> -
>  void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
>  {
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index a2380d856000..849dcafbfff1 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -436,7 +436,6 @@ static const struct drm_crtc_helper_funcs vc4_txp_crtc_helper_funcs = {
>         .atomic_flush   = vc4_hvs_atomic_flush,
>         .atomic_enable  = vc4_txp_atomic_enable,
>         .atomic_disable = vc4_txp_atomic_disable,
> -       .mode_set_nofb  = vc4_hvs_mode_set_nofb,
>  };
>
>  static irqreturn_t vc4_txp_interrupt(int irq, void *data)
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-07-29 14:42         ` Maxime Ripard
  (?)
@ 2020-07-29 14:45           ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

On Wed, 29 Jul 2020 at 15:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Hi,
>
> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> > On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> > >
> > > In order to avoid pixels getting stuck in the (unflushable) FIFO between
> > > the HVS and the PV, we need to add some delay after disabling the PV output
> > > and before disabling the HDMI controller. 20ms seems to be good enough so
> > > let's use that.
> > >
> > > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > > ---
> > >  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > > index d0b326e1df0a..7b178d67187f 100644
> > > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > > @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> > >         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> > >         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> > >
> > > +       mdelay(20);
> >
> > mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> > not msleep instead?
>
> Since the timing was fairly critical, sleeping didn't seem like a good
> solution since there's definitely some chance you overshoot and end up
> with a higher time than the one you targeted.

Fair enough. I know timing is "entertaining" around some of the 2711
pipeline setup.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 14:45           ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

On Wed, 29 Jul 2020 at 15:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Hi,
>
> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> > On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> > >
> > > In order to avoid pixels getting stuck in the (unflushable) FIFO between
> > > the HVS and the PV, we need to add some delay after disabling the PV output
> > > and before disabling the HDMI controller. 20ms seems to be good enough so
> > > let's use that.
> > >
> > > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > > ---
> > >  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > > index d0b326e1df0a..7b178d67187f 100644
> > > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > > @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> > >         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> > >         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> > >
> > > +       mdelay(20);
> >
> > mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> > not msleep instead?
>
> Since the timing was fairly critical, sleeping didn't seem like a good
> solution since there's definitely some chance you overshoot and end up
> with a higher time than the one you targeted.

Fair enough. I know timing is "entertaining" around some of the 2711
pipeline setup.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 14:45           ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 14:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

On Wed, 29 Jul 2020 at 15:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> Hi,
>
> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> > On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> > >
> > > In order to avoid pixels getting stuck in the (unflushable) FIFO between
> > > the HVS and the PV, we need to add some delay after disabling the PV output
> > > and before disabling the HDMI controller. 20ms seems to be good enough so
> > > let's use that.
> > >
> > > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > > ---
> > >  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> > >  1 file changed, 2 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> > > index d0b326e1df0a..7b178d67187f 100644
> > > --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> > > +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> > > @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> > >         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> > >         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> > >
> > > +       mdelay(20);
> >
> > mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> > not msleep instead?
>
> Since the timing was fairly critical, sleeping didn't seem like a good
> solution since there's definitely some chance you overshoot and end up
> with a higher time than the one you targeted.

Fair enough. I know timing is "entertaining" around some of the 2711
pipeline setup.

Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-07-29 15:02       ` Dave Stevenson
  -1 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 15:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4 atomic commit loop has an handrolled loop that is basically
> identical to for_each_new_crtc_state, let's convert it to that helper.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 210cc2408087..717673b18132 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>         struct drm_device *dev = state->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_hvs *hvs = vc4->hvs;
> -       struct vc4_crtc *vc4_crtc;
> +       struct drm_crtc_state *new_crtc_state;
> +       struct drm_crtc *crtc;
>         int i;
>
> -       for (i = 0; i < dev->mode_config.num_crtc; i++) {
> -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
> -                       continue;
> +       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);

for_each_new_crtc_in_state doesn't check !state->crtcs[i].commit as
the hand rolled loop did. Sorry, this is my lack of knowledge, but
does that actually make any real difference?

I see nothing wrong in calling vc4_hvs_mask_underrun multiple times
anyway, so it's most likely going to be harmless anyway, but wanted to
query it.

  Dave

>
> -               vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
>                 vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>         }
>
> --
> git-series 0.9.1

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

* Re: [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
@ 2020-07-29 15:02       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 15:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4 atomic commit loop has an handrolled loop that is basically
> identical to for_each_new_crtc_state, let's convert it to that helper.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 210cc2408087..717673b18132 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>         struct drm_device *dev = state->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_hvs *hvs = vc4->hvs;
> -       struct vc4_crtc *vc4_crtc;
> +       struct drm_crtc_state *new_crtc_state;
> +       struct drm_crtc *crtc;
>         int i;
>
> -       for (i = 0; i < dev->mode_config.num_crtc; i++) {
> -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
> -                       continue;
> +       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);

for_each_new_crtc_in_state doesn't check !state->crtcs[i].commit as
the hand rolled loop did. Sorry, this is my lack of knowledge, but
does that actually make any real difference?

I see nothing wrong in calling vc4_hvs_mask_underrun multiple times
anyway, so it's most likely going to be harmless anyway, but wanted to
query it.

  Dave

>
> -               vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
>                 vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>         }
>
> --
> git-series 0.9.1

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
@ 2020-07-29 15:02       ` Dave Stevenson
  0 siblings, 0 replies; 432+ messages in thread
From: Dave Stevenson @ 2020-07-29 15:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi Maxime

On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
>
> The vc4 atomic commit loop has an handrolled loop that is basically
> identical to for_each_new_crtc_state, let's convert it to that helper.
>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 210cc2408087..717673b18132 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>         struct drm_device *dev = state->dev;
>         struct vc4_dev *vc4 = to_vc4_dev(dev);
>         struct vc4_hvs *hvs = vc4->hvs;
> -       struct vc4_crtc *vc4_crtc;
> +       struct drm_crtc_state *new_crtc_state;
> +       struct drm_crtc *crtc;
>         int i;
>
> -       for (i = 0; i < dev->mode_config.num_crtc; i++) {
> -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
> -                       continue;
> +       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);

for_each_new_crtc_in_state doesn't check !state->crtcs[i].commit as
the hand rolled loop did. Sorry, this is my lack of knowledge, but
does that actually make any real difference?

I see nothing wrong in calling vc4_hvs_mask_underrun multiple times
anyway, so it's most likely going to be harmless anyway, but wanted to
query it.

  Dave

>
> -               vc4_crtc = to_vc4_crtc(state->crtcs[i].ptr);
>                 vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>         }
>
> --
> git-series 0.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-07-29 14:42         ` Maxime Ripard
  (?)
@ 2020-07-29 15:50           ` Stefan Wahren
  -1 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-07-29 15:50 UTC (permalink / raw)
  To: Maxime Ripard, Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> Hi,
>
> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>> let's use that.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>  1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>> index d0b326e1df0a..7b178d67187f 100644
>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>
>>> +       mdelay(20);
>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>> not msleep instead?
> Since the timing was fairly critical, sleeping didn't seem like a good
> solution since there's definitely some chance you overshoot and end up
> with a higher time than the one you targeted.

usleep_range(min, max) isn't a solution?

Stefan

>
> Maxime
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 15:50           ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-07-29 15:50 UTC (permalink / raw)
  To: Maxime Ripard, Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel

Hi Maxime,

Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> Hi,
>
> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>> let's use that.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>  1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>> index d0b326e1df0a..7b178d67187f 100644
>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>
>>> +       mdelay(20);
>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>> not msleep instead?
> Since the timing was fairly critical, sleeping didn't seem like a good
> solution since there's definitely some chance you overshoot and end up
> with a higher time than the one you targeted.

usleep_range(min, max) isn't a solution?

Stefan

>
> Maxime
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-07-29 15:50           ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-07-29 15:50 UTC (permalink / raw)
  To: Maxime Ripard, Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	linux-arm-kernel, Phil Elwell, Nicolas Saenz Julienne,
	linux-rpi-kernel

Hi Maxime,

Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> Hi,
>
> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>> let's use that.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>  1 file changed, 2 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>> index d0b326e1df0a..7b178d67187f 100644
>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>
>>> +       mdelay(20);
>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>> not msleep instead?
> Since the timing was fairly critical, sleeping didn't seem like a good
> solution since there's definitely some chance you overshoot and end up
> with a higher time than the one you targeted.

usleep_range(min, max) isn't a solution?

Stefan

>
> Maxime
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-08-21  7:18     ` Hoegeun Kwon
  -1 siblings, 0 replies; 432+ messages in thread
From: Hoegeun Kwon @ 2020-08-21  7:18 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
	Michael Turquette, Kamal Dasu, linux-kernel, dri-devel,
	linux-clk, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Phil Elwell, linux-arm-kernel, Hoegeun Kwon

Hi Maxime,

Thank you for your version 4 patch.
I tested all 78 patches based on the next-20200708.


Dual HDMI opearation does not work normally.
flip_done timed out occurs and doesn't work.
Could you check please it.

[  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[CRTC:64:crtc-3] flip_done timed out
[  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[CONNECTOR:32:HDMI-A-1] flip_done timed out
[  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[PLANE:60:plane-3] flip_done timed out


And there is a problem with 4k UDH not outputting...
So this problem worked as I fixed it like patches[1].

[1] [PATCH 0/3] drm/vc4: Support HDMI QHD or higher output


"[PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline" all patches.

Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>

Best regards,
Hoegeun

> Hi everyone,
>
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
>
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
>
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
>
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
>
> Let me know if you have any comments
> Maxime
>
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
>
> Changes from v3:
>    - Rebased on top of next-20200708
>    - Added a name to the HDMI audio codec component
>    - Only disable the BCM2711 HDMI pixelvalves at boot
>    - Fixed an error in the HVS binding
>    - Fix a framebuffer size condition that was inverted
>    - Changed the channel allocation algorithm using Eric's suggestion
>    - Always write the muxing values instead of updating if needed
>    - Improved a bit the hvs_available_channels comment in the structure
>    - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>    - Change the muxing code to take into account disparities between the
>      BCM2711 and previous SoCs.
>    - Only change the clock rate on BCM2711 during a modeset
>    - Fix a crash at atomic_disable
>    - Use clk_set_min_rate for the core clock too
>    - Add a few defines, and simplify the FIFO level stuff
>    - Reordered the patches according to Eric's reviews
>    - Fixed a regression with VID_CTL setting on RPI3
>
> Changes from v2:
>    - Rebased on top of next-20200526
>    - Split the firmware clock series away
>    - Removed the stuck pixel (with all the subsequent pixels being shifted
>      by one
>    - Fixed the writeback issue too.
>    - Fix the dual output
>    - Fixed the return value of phy_get_cp_current
>    - Enhanced the comment on the reset delay
>    - Increase the max width and height
>    - Made a proper Kconfig option for the DVP clock driver
>    - Fixed the alsa card name collision
>
> Changes from v1:
>    - Rebased on top of 5.7-rc1
>    - Run checkpatch
>    - Added audio support
>    - Fixed some HDMI timeouts
>    - Swiched to clk_hw_register_gate_parent_data
>    - Reorder Kconfig symbols in drivers/i2c/busses
>    - Make the firmware clocks a child of the firmware node
>    - Switch DVP clock driver to clk_hw interface
>    - constify raspberrypi_clk_data in raspberrypi_clock_property
>    - Don't mark firmware clocks as IGNORE_UNUSED
>    - Change from reset_ms to reset_us in reset-simple, and add a bit more
>      comments
>    - Remove generic clk patch to test if a NULL pointer is returned
>    - Removed misleading message in the is_prepared renaming patch commit
>      message
>    - Constify HDMI controller variants
>    - Fix a bug in the allocation size of the clk data array
>    - Added a mention in the DT binding conversion patches about the breakage
>    - Merged a few fixes from kbuild
>    - Fixed a few bisection and CEC build issues
>    - Collected Acked-by and Reviewed-by
>    - Change Dave email address to raspberrypi.com
>
> Dave Stevenson (7):
>    drm/vc4: Add support for the BCM2711 HVS5
>    drm/vc4: plane: Change LBM alignment constraint on LBM
>    drm/vc4: plane: Optimize the LBM allocation size
>    drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
>    drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
>    drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
>    drm/vc4: hdmi: Add audio-related callbacks
>
> Maxime Ripard (71):
>    dt-bindings: display: Add support for the BCM2711 HVS
>    drm/vc4: hvs: Boost the core clock during modeset
>    drm/vc4: plane: Create more planes
>    drm/vc4: crtc: Deal with different number of pixel per clock
>    drm/vc4: crtc: Use a shared interrupt
>    drm/vc4: crtc: Move the cob allocation outside of bind
>    drm/vc4: crtc: Rename HVS channel to output
>    drm/vc4: crtc: Use local chan variable
>    drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
>    drm/vc4: kms: Convert to for_each_new_crtc_state
>    drm/vc4: crtc: Assign output to channel automatically
>    drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
>    drm/vc4: crtc: Add function to compute FIFO level bits
>    drm/vc4: crtc: Rename HDMI encoder type to HDMI0
>    drm/vc4: crtc: Add HDMI1 encoder type
>    drm/vc4: crtc: Disable color management for HVS5
>    drm/vc4: crtc: Turn pixelvalve reset into a function
>    drm/vc4: crtc: Move PV dump to config_pv
>    drm/vc4: crtc: Move HVS init and close to a function
>    drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
>    drm/vc4: hvs: Make sure our channel is reset
>    drm/vc4: crtc: Remove mode_set_nofb
>    drm/vc4: crtc: Remove redundant pixelvalve reset
>    drm/vc4: crtc: Move HVS channel init before the PV initialisation
>    drm/vc4: encoder: Add finer-grained encoder callbacks
>    drm/vc4: crtc: Add a delay after disabling the PixelValve output
>    drm/vc4: crtc: Clear the PixelValve FIFO on disable
>    drm/vc4: crtc: Clear the PixelValve FIFO during configuration
>    drm/vc4: hvs: Make the stop_channel function public
>    drm/vc4: hvs: Introduce a function to get the assigned FIFO
>    drm/vc4: crtc: Move the CRTC disable out
>    drm/vc4: drv: Disable the CRTC at boot time
>    dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
>    drm/vc4: crtc: Add BCM2711 pixelvalves
>    drm/vc4: hdmi: Use debugfs private field
>    drm/vc4: hdmi: Move structure to header
>    drm/vc4: hdmi: rework connectors and encoders
>    drm/vc4: hdmi: Remove DDC argument to connector_init
>    drm/vc4: hdmi: Rename hdmi to vc4_hdmi
>    drm/vc4: hdmi: Move accessors to vc4_hdmi
>    drm/vc4: hdmi: Use local vc4_hdmi directly
>    drm/vc4: hdmi: Add container_of macros for encoders and connectors
>    drm/vc4: hdmi: Pass vc4_hdmi to CEC code
>    drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
>    drm/vc4: hdmi: Remove vc4_dev hdmi pointer
>    drm/vc4: hdmi: Remove vc4_hdmi_connector
>    drm/vc4: hdmi: Introduce resource init and variant
>    drm/vc4: hdmi: Implement a register layout abstraction
>    drm/vc4: hdmi: Add reset callback
>    drm/vc4: hdmi: Add PHY init and disable function
>    drm/vc4: hdmi: Add PHY RNG enable / disable function
>    drm/vc4: hdmi: Add a CSC setup callback
>    drm/vc4: hdmi: Store the encoder type in the variant structure
>    drm/vc4: hdmi: Deal with multiple debugfs files
>    drm/vc4: hdmi: Move CEC init to its own function
>    drm/vc4: hdmi: Add CEC support flag
>    drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
>    drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
>    drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
>    drm/vc4: hdmi: Use clk_set_min_rate instead
>    drm/vc4: hdmi: Deal with multiple ALSA cards
>    drm/vc4: hdmi: Remove register dumps in enable
>    drm/vc4: hdmi: Always recenter the HDMI FIFO
>    drm/vc4: hdmi: Implement finer-grained hooks
>    drm/vc4: hdmi: Do the VID_CTL configuration at once
>    drm/vc4: hdmi: Switch to blank pixels when disabled
>    drm/vc4: hdmi: Support the BCM2711 HDMI controllers
>    dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
>    dt-bindings: display: vc4: Document BCM2711 VC5
>    drm/vc4: drv: Support BCM2711
>    ARM: dts: bcm2711: Enable the display pipeline
>
>   Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
>   arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
>   arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
>   drivers/gpu/drm/vc4/Makefile                                            |    1 +-
>   drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
>   drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
>   drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
>   drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
>   drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
>   drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
>   drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
>   drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
>   drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
>   19 files changed, 3331 insertions(+), 1008 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
>
> base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-08-21  7:18     ` Hoegeun Kwon
  0 siblings, 0 replies; 432+ messages in thread
From: Hoegeun Kwon @ 2020-08-21  7:18 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Kamal Dasu, Stephen Boyd,
	Michael Turquette, Dave Stevenson, linux-kernel, dri-devel,
	Phil Elwell, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, linux-clk, linux-arm-kernel, Hoegeun Kwon

Hi Maxime,

Thank you for your version 4 patch.
I tested all 78 patches based on the next-20200708.


Dual HDMI opearation does not work normally.
flip_done timed out occurs and doesn't work.
Could you check please it.

[  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[CRTC:64:crtc-3] flip_done timed out
[  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[CONNECTOR:32:HDMI-A-1] flip_done timed out
[  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[PLANE:60:plane-3] flip_done timed out


And there is a problem with 4k UDH not outputting...
So this problem worked as I fixed it like patches[1].

[1] [PATCH 0/3] drm/vc4: Support HDMI QHD or higher output


"[PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline" all patches.

Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>

Best regards,
Hoegeun

> Hi everyone,
>
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
>
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
>
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
>
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
>
> Let me know if you have any comments
> Maxime
>
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
>
> Changes from v3:
>    - Rebased on top of next-20200708
>    - Added a name to the HDMI audio codec component
>    - Only disable the BCM2711 HDMI pixelvalves at boot
>    - Fixed an error in the HVS binding
>    - Fix a framebuffer size condition that was inverted
>    - Changed the channel allocation algorithm using Eric's suggestion
>    - Always write the muxing values instead of updating if needed
>    - Improved a bit the hvs_available_channels comment in the structure
>    - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>    - Change the muxing code to take into account disparities between the
>      BCM2711 and previous SoCs.
>    - Only change the clock rate on BCM2711 during a modeset
>    - Fix a crash at atomic_disable
>    - Use clk_set_min_rate for the core clock too
>    - Add a few defines, and simplify the FIFO level stuff
>    - Reordered the patches according to Eric's reviews
>    - Fixed a regression with VID_CTL setting on RPI3
>
> Changes from v2:
>    - Rebased on top of next-20200526
>    - Split the firmware clock series away
>    - Removed the stuck pixel (with all the subsequent pixels being shifted
>      by one
>    - Fixed the writeback issue too.
>    - Fix the dual output
>    - Fixed the return value of phy_get_cp_current
>    - Enhanced the comment on the reset delay
>    - Increase the max width and height
>    - Made a proper Kconfig option for the DVP clock driver
>    - Fixed the alsa card name collision
>
> Changes from v1:
>    - Rebased on top of 5.7-rc1
>    - Run checkpatch
>    - Added audio support
>    - Fixed some HDMI timeouts
>    - Swiched to clk_hw_register_gate_parent_data
>    - Reorder Kconfig symbols in drivers/i2c/busses
>    - Make the firmware clocks a child of the firmware node
>    - Switch DVP clock driver to clk_hw interface
>    - constify raspberrypi_clk_data in raspberrypi_clock_property
>    - Don't mark firmware clocks as IGNORE_UNUSED
>    - Change from reset_ms to reset_us in reset-simple, and add a bit more
>      comments
>    - Remove generic clk patch to test if a NULL pointer is returned
>    - Removed misleading message in the is_prepared renaming patch commit
>      message
>    - Constify HDMI controller variants
>    - Fix a bug in the allocation size of the clk data array
>    - Added a mention in the DT binding conversion patches about the breakage
>    - Merged a few fixes from kbuild
>    - Fixed a few bisection and CEC build issues
>    - Collected Acked-by and Reviewed-by
>    - Change Dave email address to raspberrypi.com
>
> Dave Stevenson (7):
>    drm/vc4: Add support for the BCM2711 HVS5
>    drm/vc4: plane: Change LBM alignment constraint on LBM
>    drm/vc4: plane: Optimize the LBM allocation size
>    drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
>    drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
>    drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
>    drm/vc4: hdmi: Add audio-related callbacks
>
> Maxime Ripard (71):
>    dt-bindings: display: Add support for the BCM2711 HVS
>    drm/vc4: hvs: Boost the core clock during modeset
>    drm/vc4: plane: Create more planes
>    drm/vc4: crtc: Deal with different number of pixel per clock
>    drm/vc4: crtc: Use a shared interrupt
>    drm/vc4: crtc: Move the cob allocation outside of bind
>    drm/vc4: crtc: Rename HVS channel to output
>    drm/vc4: crtc: Use local chan variable
>    drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
>    drm/vc4: kms: Convert to for_each_new_crtc_state
>    drm/vc4: crtc: Assign output to channel automatically
>    drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
>    drm/vc4: crtc: Add function to compute FIFO level bits
>    drm/vc4: crtc: Rename HDMI encoder type to HDMI0
>    drm/vc4: crtc: Add HDMI1 encoder type
>    drm/vc4: crtc: Disable color management for HVS5
>    drm/vc4: crtc: Turn pixelvalve reset into a function
>    drm/vc4: crtc: Move PV dump to config_pv
>    drm/vc4: crtc: Move HVS init and close to a function
>    drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
>    drm/vc4: hvs: Make sure our channel is reset
>    drm/vc4: crtc: Remove mode_set_nofb
>    drm/vc4: crtc: Remove redundant pixelvalve reset
>    drm/vc4: crtc: Move HVS channel init before the PV initialisation
>    drm/vc4: encoder: Add finer-grained encoder callbacks
>    drm/vc4: crtc: Add a delay after disabling the PixelValve output
>    drm/vc4: crtc: Clear the PixelValve FIFO on disable
>    drm/vc4: crtc: Clear the PixelValve FIFO during configuration
>    drm/vc4: hvs: Make the stop_channel function public
>    drm/vc4: hvs: Introduce a function to get the assigned FIFO
>    drm/vc4: crtc: Move the CRTC disable out
>    drm/vc4: drv: Disable the CRTC at boot time
>    dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
>    drm/vc4: crtc: Add BCM2711 pixelvalves
>    drm/vc4: hdmi: Use debugfs private field
>    drm/vc4: hdmi: Move structure to header
>    drm/vc4: hdmi: rework connectors and encoders
>    drm/vc4: hdmi: Remove DDC argument to connector_init
>    drm/vc4: hdmi: Rename hdmi to vc4_hdmi
>    drm/vc4: hdmi: Move accessors to vc4_hdmi
>    drm/vc4: hdmi: Use local vc4_hdmi directly
>    drm/vc4: hdmi: Add container_of macros for encoders and connectors
>    drm/vc4: hdmi: Pass vc4_hdmi to CEC code
>    drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
>    drm/vc4: hdmi: Remove vc4_dev hdmi pointer
>    drm/vc4: hdmi: Remove vc4_hdmi_connector
>    drm/vc4: hdmi: Introduce resource init and variant
>    drm/vc4: hdmi: Implement a register layout abstraction
>    drm/vc4: hdmi: Add reset callback
>    drm/vc4: hdmi: Add PHY init and disable function
>    drm/vc4: hdmi: Add PHY RNG enable / disable function
>    drm/vc4: hdmi: Add a CSC setup callback
>    drm/vc4: hdmi: Store the encoder type in the variant structure
>    drm/vc4: hdmi: Deal with multiple debugfs files
>    drm/vc4: hdmi: Move CEC init to its own function
>    drm/vc4: hdmi: Add CEC support flag
>    drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
>    drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
>    drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
>    drm/vc4: hdmi: Use clk_set_min_rate instead
>    drm/vc4: hdmi: Deal with multiple ALSA cards
>    drm/vc4: hdmi: Remove register dumps in enable
>    drm/vc4: hdmi: Always recenter the HDMI FIFO
>    drm/vc4: hdmi: Implement finer-grained hooks
>    drm/vc4: hdmi: Do the VID_CTL configuration at once
>    drm/vc4: hdmi: Switch to blank pixels when disabled
>    drm/vc4: hdmi: Support the BCM2711 HDMI controllers
>    dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
>    dt-bindings: display: vc4: Document BCM2711 VC5
>    drm/vc4: drv: Support BCM2711
>    ARM: dts: bcm2711: Enable the display pipeline
>
>   Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
>   arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
>   arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
>   drivers/gpu/drm/vc4/Makefile                                            |    1 +-
>   drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
>   drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
>   drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
>   drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
>   drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
>   drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
>   drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
>   drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
>   drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
>   19 files changed, 3331 insertions(+), 1008 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
>
> base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-08-21  7:18     ` Hoegeun Kwon
  0 siblings, 0 replies; 432+ messages in thread
From: Hoegeun Kwon @ 2020-08-21  7:18 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Kamal Dasu, Stephen Boyd,
	Michael Turquette, Dave Stevenson, linux-kernel, dri-devel,
	Phil Elwell, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, linux-clk, linux-arm-kernel, Hoegeun Kwon

Hi Maxime,

Thank you for your version 4 patch.
I tested all 78 patches based on the next-20200708.


Dual HDMI opearation does not work normally.
flip_done timed out occurs and doesn't work.
Could you check please it.

[  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[CRTC:64:crtc-3] flip_done timed out
[  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[CONNECTOR:32:HDMI-A-1] flip_done timed out
[  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
[PLANE:60:plane-3] flip_done timed out


And there is a problem with 4k UDH not outputting...
So this problem worked as I fixed it like patches[1].

[1] [PATCH 0/3] drm/vc4: Support HDMI QHD or higher output


"[PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline" all patches.

Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>

Best regards,
Hoegeun

> Hi everyone,
>
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
>
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
>
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
>
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
>
> Let me know if you have any comments
> Maxime
>
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
>
> Changes from v3:
>    - Rebased on top of next-20200708
>    - Added a name to the HDMI audio codec component
>    - Only disable the BCM2711 HDMI pixelvalves at boot
>    - Fixed an error in the HVS binding
>    - Fix a framebuffer size condition that was inverted
>    - Changed the channel allocation algorithm using Eric's suggestion
>    - Always write the muxing values instead of updating if needed
>    - Improved a bit the hvs_available_channels comment in the structure
>    - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>    - Change the muxing code to take into account disparities between the
>      BCM2711 and previous SoCs.
>    - Only change the clock rate on BCM2711 during a modeset
>    - Fix a crash at atomic_disable
>    - Use clk_set_min_rate for the core clock too
>    - Add a few defines, and simplify the FIFO level stuff
>    - Reordered the patches according to Eric's reviews
>    - Fixed a regression with VID_CTL setting on RPI3
>
> Changes from v2:
>    - Rebased on top of next-20200526
>    - Split the firmware clock series away
>    - Removed the stuck pixel (with all the subsequent pixels being shifted
>      by one
>    - Fixed the writeback issue too.
>    - Fix the dual output
>    - Fixed the return value of phy_get_cp_current
>    - Enhanced the comment on the reset delay
>    - Increase the max width and height
>    - Made a proper Kconfig option for the DVP clock driver
>    - Fixed the alsa card name collision
>
> Changes from v1:
>    - Rebased on top of 5.7-rc1
>    - Run checkpatch
>    - Added audio support
>    - Fixed some HDMI timeouts
>    - Swiched to clk_hw_register_gate_parent_data
>    - Reorder Kconfig symbols in drivers/i2c/busses
>    - Make the firmware clocks a child of the firmware node
>    - Switch DVP clock driver to clk_hw interface
>    - constify raspberrypi_clk_data in raspberrypi_clock_property
>    - Don't mark firmware clocks as IGNORE_UNUSED
>    - Change from reset_ms to reset_us in reset-simple, and add a bit more
>      comments
>    - Remove generic clk patch to test if a NULL pointer is returned
>    - Removed misleading message in the is_prepared renaming patch commit
>      message
>    - Constify HDMI controller variants
>    - Fix a bug in the allocation size of the clk data array
>    - Added a mention in the DT binding conversion patches about the breakage
>    - Merged a few fixes from kbuild
>    - Fixed a few bisection and CEC build issues
>    - Collected Acked-by and Reviewed-by
>    - Change Dave email address to raspberrypi.com
>
> Dave Stevenson (7):
>    drm/vc4: Add support for the BCM2711 HVS5
>    drm/vc4: plane: Change LBM alignment constraint on LBM
>    drm/vc4: plane: Optimize the LBM allocation size
>    drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
>    drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
>    drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
>    drm/vc4: hdmi: Add audio-related callbacks
>
> Maxime Ripard (71):
>    dt-bindings: display: Add support for the BCM2711 HVS
>    drm/vc4: hvs: Boost the core clock during modeset
>    drm/vc4: plane: Create more planes
>    drm/vc4: crtc: Deal with different number of pixel per clock
>    drm/vc4: crtc: Use a shared interrupt
>    drm/vc4: crtc: Move the cob allocation outside of bind
>    drm/vc4: crtc: Rename HVS channel to output
>    drm/vc4: crtc: Use local chan variable
>    drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
>    drm/vc4: kms: Convert to for_each_new_crtc_state
>    drm/vc4: crtc: Assign output to channel automatically
>    drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
>    drm/vc4: crtc: Add function to compute FIFO level bits
>    drm/vc4: crtc: Rename HDMI encoder type to HDMI0
>    drm/vc4: crtc: Add HDMI1 encoder type
>    drm/vc4: crtc: Disable color management for HVS5
>    drm/vc4: crtc: Turn pixelvalve reset into a function
>    drm/vc4: crtc: Move PV dump to config_pv
>    drm/vc4: crtc: Move HVS init and close to a function
>    drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
>    drm/vc4: hvs: Make sure our channel is reset
>    drm/vc4: crtc: Remove mode_set_nofb
>    drm/vc4: crtc: Remove redundant pixelvalve reset
>    drm/vc4: crtc: Move HVS channel init before the PV initialisation
>    drm/vc4: encoder: Add finer-grained encoder callbacks
>    drm/vc4: crtc: Add a delay after disabling the PixelValve output
>    drm/vc4: crtc: Clear the PixelValve FIFO on disable
>    drm/vc4: crtc: Clear the PixelValve FIFO during configuration
>    drm/vc4: hvs: Make the stop_channel function public
>    drm/vc4: hvs: Introduce a function to get the assigned FIFO
>    drm/vc4: crtc: Move the CRTC disable out
>    drm/vc4: drv: Disable the CRTC at boot time
>    dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
>    drm/vc4: crtc: Add BCM2711 pixelvalves
>    drm/vc4: hdmi: Use debugfs private field
>    drm/vc4: hdmi: Move structure to header
>    drm/vc4: hdmi: rework connectors and encoders
>    drm/vc4: hdmi: Remove DDC argument to connector_init
>    drm/vc4: hdmi: Rename hdmi to vc4_hdmi
>    drm/vc4: hdmi: Move accessors to vc4_hdmi
>    drm/vc4: hdmi: Use local vc4_hdmi directly
>    drm/vc4: hdmi: Add container_of macros for encoders and connectors
>    drm/vc4: hdmi: Pass vc4_hdmi to CEC code
>    drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
>    drm/vc4: hdmi: Remove vc4_dev hdmi pointer
>    drm/vc4: hdmi: Remove vc4_hdmi_connector
>    drm/vc4: hdmi: Introduce resource init and variant
>    drm/vc4: hdmi: Implement a register layout abstraction
>    drm/vc4: hdmi: Add reset callback
>    drm/vc4: hdmi: Add PHY init and disable function
>    drm/vc4: hdmi: Add PHY RNG enable / disable function
>    drm/vc4: hdmi: Add a CSC setup callback
>    drm/vc4: hdmi: Store the encoder type in the variant structure
>    drm/vc4: hdmi: Deal with multiple debugfs files
>    drm/vc4: hdmi: Move CEC init to its own function
>    drm/vc4: hdmi: Add CEC support flag
>    drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
>    drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
>    drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
>    drm/vc4: hdmi: Use clk_set_min_rate instead
>    drm/vc4: hdmi: Deal with multiple ALSA cards
>    drm/vc4: hdmi: Remove register dumps in enable
>    drm/vc4: hdmi: Always recenter the HDMI FIFO
>    drm/vc4: hdmi: Implement finer-grained hooks
>    drm/vc4: hdmi: Do the VID_CTL configuration at once
>    drm/vc4: hdmi: Switch to blank pixels when disabled
>    drm/vc4: hdmi: Support the BCM2711 HDMI controllers
>    dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
>    dt-bindings: display: vc4: Document BCM2711 VC5
>    drm/vc4: drv: Support BCM2711
>    ARM: dts: bcm2711: Enable the display pipeline
>
>   Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
>   Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
>   arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
>   arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
>   drivers/gpu/drm/vc4/Makefile                                            |    1 +-
>   drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
>   drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
>   drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
>   drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
>   drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
>   drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
>   drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
>   drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
>   drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
>   drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
>   19 files changed, 3331 insertions(+), 1008 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>   create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
>
> base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-07-29 15:50           ` Stefan Wahren
  (?)
@ 2020-08-25 15:06             ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-08-25 15:06 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Dave Stevenson, Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

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

Hi Stefan,

On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> > Hi,
> >
> > On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>> let's use that.
> >>>
> >>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>> ---
> >>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>  1 file changed, 2 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> index d0b326e1df0a..7b178d67187f 100644
> >>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>
> >>> +       mdelay(20);
> >> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >> not msleep instead?
> > Since the timing was fairly critical, sleeping didn't seem like a good
> > solution since there's definitely some chance you overshoot and end up
> > with a higher time than the one you targeted.
> 
> usleep_range(min, max) isn't a solution?

My understanding of usleep_range was that you can still overshoot, even
though it's backed by an HR timer so the resolution is not a jiffy. Are
we certain that we're going to be in that range?

Maxime

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

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-08-25 15:06             ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-08-25 15:06 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel


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

Hi Stefan,

On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> > Hi,
> >
> > On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>> let's use that.
> >>>
> >>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>> ---
> >>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>  1 file changed, 2 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> index d0b326e1df0a..7b178d67187f 100644
> >>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>
> >>> +       mdelay(20);
> >> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >> not msleep instead?
> > Since the timing was fairly critical, sleeping didn't seem like a good
> > solution since there's definitely some chance you overshoot and end up
> > with a higher time than the one you targeted.
> 
> usleep_range(min, max) isn't a solution?

My understanding of usleep_range was that you can still overshoot, even
though it's backed by an HR timer so the resolution is not a jiffy. Are
we certain that we're going to be in that range?

Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-08-25 15:06             ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-08-25 15:06 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel


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

Hi Stefan,

On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> > Hi,
> >
> > On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>> let's use that.
> >>>
> >>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>> ---
> >>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>  1 file changed, 2 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> index d0b326e1df0a..7b178d67187f 100644
> >>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>
> >>> +       mdelay(20);
> >> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >> not msleep instead?
> > Since the timing was fairly critical, sleeping didn't seem like a good
> > solution since there's definitely some chance you overshoot and end up
> > with a higher time than the one you targeted.
> 
> usleep_range(min, max) isn't a solution?

My understanding of usleep_range was that you can still overshoot, even
though it's backed by an HR timer so the resolution is not a jiffy. Are
we certain that we're going to be in that range?

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-08-25 15:06             ` Maxime Ripard
  (?)
@ 2020-08-25 21:30               ` Stefan Wahren
  -1 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-08-25 21:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel

Hi Maxime,

Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> Hi Stefan,
>
> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>> Hi,
>>>
>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>>>> let's use that.
>>>>>
>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>> ---
>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>>>  1 file changed, 2 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> index d0b326e1df0a..7b178d67187f 100644
>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>>>
>>>>> +       mdelay(20);
>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>>>> not msleep instead?
>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>> solution since there's definitely some chance you overshoot and end up
>>> with a higher time than the one you targeted.
>> usleep_range(min, max) isn't a solution?
> My understanding of usleep_range was that you can still overshoot, even
> though it's backed by an HR timer so the resolution is not a jiffy. Are
> we certain that we're going to be in that range?

you are right there is no guarantee about the upper wake up time.

And it's not worth the effort to poll the FIFO state until its empty
(using 20 ms as timeout)?

>
> Maxime
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-08-25 21:30               ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-08-25 21:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> Hi Stefan,
>
> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>> Hi,
>>>
>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>>>> let's use that.
>>>>>
>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>> ---
>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>>>  1 file changed, 2 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> index d0b326e1df0a..7b178d67187f 100644
>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>>>
>>>>> +       mdelay(20);
>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>>>> not msleep instead?
>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>> solution since there's definitely some chance you overshoot and end up
>>> with a higher time than the one you targeted.
>> usleep_range(min, max) isn't a solution?
> My understanding of usleep_range was that you can still overshoot, even
> though it's backed by an HR timer so the resolution is not a jiffy. Are
> we certain that we're going to be in that range?

you are right there is no guarantee about the upper wake up time.

And it's not worth the effort to poll the FIFO state until its empty
(using 20 ms as timeout)?

>
> Maxime
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-08-25 21:30               ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-08-25 21:30 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> Hi Stefan,
>
> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>> Hi,
>>>
>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>>>> let's use that.
>>>>>
>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>> ---
>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>>>  1 file changed, 2 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> index d0b326e1df0a..7b178d67187f 100644
>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>>>
>>>>> +       mdelay(20);
>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>>>> not msleep instead?
>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>> solution since there's definitely some chance you overshoot and end up
>>> with a higher time than the one you targeted.
>> usleep_range(min, max) isn't a solution?
> My understanding of usleep_range was that you can still overshoot, even
> though it's backed by an HR timer so the resolution is not a jiffy. Are
> we certain that we're going to be in that range?

you are right there is no guarantee about the upper wake up time.

And it's not worth the effort to poll the FIFO state until its empty
(using 20 ms as timeout)?

>
> Maxime
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
  2020-07-08 17:41   ` Maxime Ripard
  (?)
@ 2020-08-31  2:36     ` Chanwoo Choi
  -1 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-08-31  2:36 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, devicetree, Kamal Dasu, linux-clk,
	Michael Turquette, Philipp Zabel, Rob Herring, Stephen Boyd

Hi Maxime,

On 7/9/20 2:41 AM, Maxime Ripard wrote:
> Hi everyone,
> 
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
> 
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
> 
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
> 
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
> 
> Let me know if you have any comments
> Maxime
> 
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> 
> Changes from v3:
>   - Rebased on top of next-20200708
>   - Added a name to the HDMI audio codec component
>   - Only disable the BCM2711 HDMI pixelvalves at boot
>   - Fixed an error in the HVS binding
>   - Fix a framebuffer size condition that was inverted
>   - Changed the channel allocation algorithm using Eric's suggestion
>   - Always write the muxing values instead of updating if needed
>   - Improved a bit the hvs_available_channels comment in the structure
>   - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>   - Change the muxing code to take into account disparities between the
>     BCM2711 and previous SoCs.
>   - Only change the clock rate on BCM2711 during a modeset
>   - Fix a crash at atomic_disable
>   - Use clk_set_min_rate for the core clock too
>   - Add a few defines, and simplify the FIFO level stuff
>   - Reordered the patches according to Eric's reviews
>   - Fixed a regression with VID_CTL setting on RPI3
> 
> Changes from v2:
>   - Rebased on top of next-20200526
>   - Split the firmware clock series away
>   - Removed the stuck pixel (with all the subsequent pixels being shifted
>     by one
>   - Fixed the writeback issue too.
>   - Fix the dual output
>   - Fixed the return value of phy_get_cp_current
>   - Enhanced the comment on the reset delay
>   - Increase the max width and height
>   - Made a proper Kconfig option for the DVP clock driver
>   - Fixed the alsa card name collision
> 
> Changes from v1:
>   - Rebased on top of 5.7-rc1
>   - Run checkpatch
>   - Added audio support
>   - Fixed some HDMI timeouts
>   - Swiched to clk_hw_register_gate_parent_data
>   - Reorder Kconfig symbols in drivers/i2c/busses
>   - Make the firmware clocks a child of the firmware node
>   - Switch DVP clock driver to clk_hw interface
>   - constify raspberrypi_clk_data in raspberrypi_clock_property
>   - Don't mark firmware clocks as IGNORE_UNUSED
>   - Change from reset_ms to reset_us in reset-simple, and add a bit more
>     comments
>   - Remove generic clk patch to test if a NULL pointer is returned
>   - Removed misleading message in the is_prepared renaming patch commit
>     message
>   - Constify HDMI controller variants
>   - Fix a bug in the allocation size of the clk data array
>   - Added a mention in the DT binding conversion patches about the breakage
>   - Merged a few fixes from kbuild
>   - Fixed a few bisection and CEC build issues
>   - Collected Acked-by and Reviewed-by
>   - Change Dave email address to raspberrypi.com
> 
> Dave Stevenson (7):
>   drm/vc4: Add support for the BCM2711 HVS5
>   drm/vc4: plane: Change LBM alignment constraint on LBM
>   drm/vc4: plane: Optimize the LBM allocation size
>   drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
>   drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
>   drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
>   drm/vc4: hdmi: Add audio-related callbacks
> 
> Maxime Ripard (71):
>   dt-bindings: display: Add support for the BCM2711 HVS
>   drm/vc4: hvs: Boost the core clock during modeset
>   drm/vc4: plane: Create more planes
>   drm/vc4: crtc: Deal with different number of pixel per clock
>   drm/vc4: crtc: Use a shared interrupt
>   drm/vc4: crtc: Move the cob allocation outside of bind
>   drm/vc4: crtc: Rename HVS channel to output
>   drm/vc4: crtc: Use local chan variable
>   drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
>   drm/vc4: kms: Convert to for_each_new_crtc_state
>   drm/vc4: crtc: Assign output to channel automatically
>   drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
>   drm/vc4: crtc: Add function to compute FIFO level bits
>   drm/vc4: crtc: Rename HDMI encoder type to HDMI0
>   drm/vc4: crtc: Add HDMI1 encoder type
>   drm/vc4: crtc: Disable color management for HVS5
>   drm/vc4: crtc: Turn pixelvalve reset into a function
>   drm/vc4: crtc: Move PV dump to config_pv
>   drm/vc4: crtc: Move HVS init and close to a function
>   drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
>   drm/vc4: hvs: Make sure our channel is reset
>   drm/vc4: crtc: Remove mode_set_nofb
>   drm/vc4: crtc: Remove redundant pixelvalve reset
>   drm/vc4: crtc: Move HVS channel init before the PV initialisation
>   drm/vc4: encoder: Add finer-grained encoder callbacks
>   drm/vc4: crtc: Add a delay after disabling the PixelValve output
>   drm/vc4: crtc: Clear the PixelValve FIFO on disable
>   drm/vc4: crtc: Clear the PixelValve FIFO during configuration
>   drm/vc4: hvs: Make the stop_channel function public
>   drm/vc4: hvs: Introduce a function to get the assigned FIFO
>   drm/vc4: crtc: Move the CRTC disable out
>   drm/vc4: drv: Disable the CRTC at boot time
>   dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
>   drm/vc4: crtc: Add BCM2711 pixelvalves
>   drm/vc4: hdmi: Use debugfs private field
>   drm/vc4: hdmi: Move structure to header
>   drm/vc4: hdmi: rework connectors and encoders
>   drm/vc4: hdmi: Remove DDC argument to connector_init
>   drm/vc4: hdmi: Rename hdmi to vc4_hdmi
>   drm/vc4: hdmi: Move accessors to vc4_hdmi
>   drm/vc4: hdmi: Use local vc4_hdmi directly
>   drm/vc4: hdmi: Add container_of macros for encoders and connectors
>   drm/vc4: hdmi: Pass vc4_hdmi to CEC code
>   drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
>   drm/vc4: hdmi: Remove vc4_dev hdmi pointer
>   drm/vc4: hdmi: Remove vc4_hdmi_connector
>   drm/vc4: hdmi: Introduce resource init and variant
>   drm/vc4: hdmi: Implement a register layout abstraction
>   drm/vc4: hdmi: Add reset callback
>   drm/vc4: hdmi: Add PHY init and disable function
>   drm/vc4: hdmi: Add PHY RNG enable / disable function
>   drm/vc4: hdmi: Add a CSC setup callback
>   drm/vc4: hdmi: Store the encoder type in the variant structure
>   drm/vc4: hdmi: Deal with multiple debugfs files
>   drm/vc4: hdmi: Move CEC init to its own function
>   drm/vc4: hdmi: Add CEC support flag
>   drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
>   drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
>   drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
>   drm/vc4: hdmi: Use clk_set_min_rate instead
>   drm/vc4: hdmi: Deal with multiple ALSA cards
>   drm/vc4: hdmi: Remove register dumps in enable
>   drm/vc4: hdmi: Always recenter the HDMI FIFO
>   drm/vc4: hdmi: Implement finer-grained hooks
>   drm/vc4: hdmi: Do the VID_CTL configuration at once
>   drm/vc4: hdmi: Switch to blank pixels when disabled
>   drm/vc4: hdmi: Support the BCM2711 HDMI controllers
>   dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
>   dt-bindings: display: vc4: Document BCM2711 VC5
>   drm/vc4: drv: Support BCM2711
>   ARM: dts: bcm2711: Enable the display pipeline
> 
>  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
>  arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
>  drivers/gpu/drm/vc4/Makefile                                            |    1 +-
>  drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
>  drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
>  drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
>  drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
>  drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
>  drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
>  drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
>  19 files changed, 3331 insertions(+), 1008 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> 
> base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
> 

I tested it for stress test with reboot command repetitively
for verifying this patchset. It is well working.

Tested-by: Chanwoo Choi <cw00.choi@samsung.com>

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-08-31  2:36     ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-08-31  2:36 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
	Michael Turquette, Kamal Dasu, linux-kernel, dri-devel,
	linux-clk, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Philipp Zabel, Phil Elwell, linux-arm-kernel

Hi Maxime,

On 7/9/20 2:41 AM, Maxime Ripard wrote:
> Hi everyone,
> 
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
> 
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
> 
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
> 
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
> 
> Let me know if you have any comments
> Maxime
> 
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> 
> Changes from v3:
>   - Rebased on top of next-20200708
>   - Added a name to the HDMI audio codec component
>   - Only disable the BCM2711 HDMI pixelvalves at boot
>   - Fixed an error in the HVS binding
>   - Fix a framebuffer size condition that was inverted
>   - Changed the channel allocation algorithm using Eric's suggestion
>   - Always write the muxing values instead of updating if needed
>   - Improved a bit the hvs_available_channels comment in the structure
>   - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>   - Change the muxing code to take into account disparities between the
>     BCM2711 and previous SoCs.
>   - Only change the clock rate on BCM2711 during a modeset
>   - Fix a crash at atomic_disable
>   - Use clk_set_min_rate for the core clock too
>   - Add a few defines, and simplify the FIFO level stuff
>   - Reordered the patches according to Eric's reviews
>   - Fixed a regression with VID_CTL setting on RPI3
> 
> Changes from v2:
>   - Rebased on top of next-20200526
>   - Split the firmware clock series away
>   - Removed the stuck pixel (with all the subsequent pixels being shifted
>     by one
>   - Fixed the writeback issue too.
>   - Fix the dual output
>   - Fixed the return value of phy_get_cp_current
>   - Enhanced the comment on the reset delay
>   - Increase the max width and height
>   - Made a proper Kconfig option for the DVP clock driver
>   - Fixed the alsa card name collision
> 
> Changes from v1:
>   - Rebased on top of 5.7-rc1
>   - Run checkpatch
>   - Added audio support
>   - Fixed some HDMI timeouts
>   - Swiched to clk_hw_register_gate_parent_data
>   - Reorder Kconfig symbols in drivers/i2c/busses
>   - Make the firmware clocks a child of the firmware node
>   - Switch DVP clock driver to clk_hw interface
>   - constify raspberrypi_clk_data in raspberrypi_clock_property
>   - Don't mark firmware clocks as IGNORE_UNUSED
>   - Change from reset_ms to reset_us in reset-simple, and add a bit more
>     comments
>   - Remove generic clk patch to test if a NULL pointer is returned
>   - Removed misleading message in the is_prepared renaming patch commit
>     message
>   - Constify HDMI controller variants
>   - Fix a bug in the allocation size of the clk data array
>   - Added a mention in the DT binding conversion patches about the breakage
>   - Merged a few fixes from kbuild
>   - Fixed a few bisection and CEC build issues
>   - Collected Acked-by and Reviewed-by
>   - Change Dave email address to raspberrypi.com
> 
> Dave Stevenson (7):
>   drm/vc4: Add support for the BCM2711 HVS5
>   drm/vc4: plane: Change LBM alignment constraint on LBM
>   drm/vc4: plane: Optimize the LBM allocation size
>   drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
>   drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
>   drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
>   drm/vc4: hdmi: Add audio-related callbacks
> 
> Maxime Ripard (71):
>   dt-bindings: display: Add support for the BCM2711 HVS
>   drm/vc4: hvs: Boost the core clock during modeset
>   drm/vc4: plane: Create more planes
>   drm/vc4: crtc: Deal with different number of pixel per clock
>   drm/vc4: crtc: Use a shared interrupt
>   drm/vc4: crtc: Move the cob allocation outside of bind
>   drm/vc4: crtc: Rename HVS channel to output
>   drm/vc4: crtc: Use local chan variable
>   drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
>   drm/vc4: kms: Convert to for_each_new_crtc_state
>   drm/vc4: crtc: Assign output to channel automatically
>   drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
>   drm/vc4: crtc: Add function to compute FIFO level bits
>   drm/vc4: crtc: Rename HDMI encoder type to HDMI0
>   drm/vc4: crtc: Add HDMI1 encoder type
>   drm/vc4: crtc: Disable color management for HVS5
>   drm/vc4: crtc: Turn pixelvalve reset into a function
>   drm/vc4: crtc: Move PV dump to config_pv
>   drm/vc4: crtc: Move HVS init and close to a function
>   drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
>   drm/vc4: hvs: Make sure our channel is reset
>   drm/vc4: crtc: Remove mode_set_nofb
>   drm/vc4: crtc: Remove redundant pixelvalve reset
>   drm/vc4: crtc: Move HVS channel init before the PV initialisation
>   drm/vc4: encoder: Add finer-grained encoder callbacks
>   drm/vc4: crtc: Add a delay after disabling the PixelValve output
>   drm/vc4: crtc: Clear the PixelValve FIFO on disable
>   drm/vc4: crtc: Clear the PixelValve FIFO during configuration
>   drm/vc4: hvs: Make the stop_channel function public
>   drm/vc4: hvs: Introduce a function to get the assigned FIFO
>   drm/vc4: crtc: Move the CRTC disable out
>   drm/vc4: drv: Disable the CRTC at boot time
>   dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
>   drm/vc4: crtc: Add BCM2711 pixelvalves
>   drm/vc4: hdmi: Use debugfs private field
>   drm/vc4: hdmi: Move structure to header
>   drm/vc4: hdmi: rework connectors and encoders
>   drm/vc4: hdmi: Remove DDC argument to connector_init
>   drm/vc4: hdmi: Rename hdmi to vc4_hdmi
>   drm/vc4: hdmi: Move accessors to vc4_hdmi
>   drm/vc4: hdmi: Use local vc4_hdmi directly
>   drm/vc4: hdmi: Add container_of macros for encoders and connectors
>   drm/vc4: hdmi: Pass vc4_hdmi to CEC code
>   drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
>   drm/vc4: hdmi: Remove vc4_dev hdmi pointer
>   drm/vc4: hdmi: Remove vc4_hdmi_connector
>   drm/vc4: hdmi: Introduce resource init and variant
>   drm/vc4: hdmi: Implement a register layout abstraction
>   drm/vc4: hdmi: Add reset callback
>   drm/vc4: hdmi: Add PHY init and disable function
>   drm/vc4: hdmi: Add PHY RNG enable / disable function
>   drm/vc4: hdmi: Add a CSC setup callback
>   drm/vc4: hdmi: Store the encoder type in the variant structure
>   drm/vc4: hdmi: Deal with multiple debugfs files
>   drm/vc4: hdmi: Move CEC init to its own function
>   drm/vc4: hdmi: Add CEC support flag
>   drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
>   drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
>   drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
>   drm/vc4: hdmi: Use clk_set_min_rate instead
>   drm/vc4: hdmi: Deal with multiple ALSA cards
>   drm/vc4: hdmi: Remove register dumps in enable
>   drm/vc4: hdmi: Always recenter the HDMI FIFO
>   drm/vc4: hdmi: Implement finer-grained hooks
>   drm/vc4: hdmi: Do the VID_CTL configuration at once
>   drm/vc4: hdmi: Switch to blank pixels when disabled
>   drm/vc4: hdmi: Support the BCM2711 HDMI controllers
>   dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
>   dt-bindings: display: vc4: Document BCM2711 VC5
>   drm/vc4: drv: Support BCM2711
>   ARM: dts: bcm2711: Enable the display pipeline
> 
>  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
>  arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
>  drivers/gpu/drm/vc4/Makefile                                            |    1 +-
>  drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
>  drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
>  drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
>  drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
>  drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
>  drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
>  drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
>  19 files changed, 3331 insertions(+), 1008 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> 
> base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
> 

I tested it for stress test with reboot command repetitively
for verifying this patchset. It is well working.

Tested-by: Chanwoo Choi <cw00.choi@samsung.com>

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-08-31  2:36     ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-08-31  2:36 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
	Michael Turquette, Kamal Dasu, linux-kernel, dri-devel,
	linux-clk, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, Phil Elwell, linux-arm-kernel

Hi Maxime,

On 7/9/20 2:41 AM, Maxime Ripard wrote:
> Hi everyone,
> 
> Here's a (pretty long) series to introduce support in the VC4 DRM driver
> for the display pipeline found in the BCM2711 (and thus the RaspberryPi 4).
> 
> The main differences are that there's two HDMI controllers and that there's
> more pixelvalve now. Those pixelvalve come with a mux in the HVS that still
> have only 3 FIFOs. Both of those differences are breaking a bunch of
> expectations in the driver, so we first need a good bunch of cleanup and
> reworks to introduce support for the new controllers.
> 
> Similarly, the HDMI controller has all its registers shuffled and split in
> multiple controllers now, so we need a bunch of changes to support this as
> well.
> 
> Only the HDMI support is enabled for now (even though the DPI and DSI
> outputs have been tested too).
> 
> Let me know if you have any comments
> Maxime
> 
> Cc: bcm-kernel-feedback-list@broadcom.com
> Cc: devicetree@vger.kernel.org
> Cc: Kamal Dasu <kdasu.kdev@gmail.com>
> Cc: linux-clk@vger.kernel.org
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> 
> Changes from v3:
>   - Rebased on top of next-20200708
>   - Added a name to the HDMI audio codec component
>   - Only disable the BCM2711 HDMI pixelvalves at boot
>   - Fixed an error in the HVS binding
>   - Fix a framebuffer size condition that was inverted
>   - Changed the channel allocation algorithm using Eric's suggestion
>   - Always write the muxing values instead of updating if needed
>   - Improved a bit the hvs_available_channels comment in the structure
>   - Change atomic_complete_commit code to use for_each_new_crtc_in_state
>   - Change the muxing code to take into account disparities between the
>     BCM2711 and previous SoCs.
>   - Only change the clock rate on BCM2711 during a modeset
>   - Fix a crash at atomic_disable
>   - Use clk_set_min_rate for the core clock too
>   - Add a few defines, and simplify the FIFO level stuff
>   - Reordered the patches according to Eric's reviews
>   - Fixed a regression with VID_CTL setting on RPI3
> 
> Changes from v2:
>   - Rebased on top of next-20200526
>   - Split the firmware clock series away
>   - Removed the stuck pixel (with all the subsequent pixels being shifted
>     by one
>   - Fixed the writeback issue too.
>   - Fix the dual output
>   - Fixed the return value of phy_get_cp_current
>   - Enhanced the comment on the reset delay
>   - Increase the max width and height
>   - Made a proper Kconfig option for the DVP clock driver
>   - Fixed the alsa card name collision
> 
> Changes from v1:
>   - Rebased on top of 5.7-rc1
>   - Run checkpatch
>   - Added audio support
>   - Fixed some HDMI timeouts
>   - Swiched to clk_hw_register_gate_parent_data
>   - Reorder Kconfig symbols in drivers/i2c/busses
>   - Make the firmware clocks a child of the firmware node
>   - Switch DVP clock driver to clk_hw interface
>   - constify raspberrypi_clk_data in raspberrypi_clock_property
>   - Don't mark firmware clocks as IGNORE_UNUSED
>   - Change from reset_ms to reset_us in reset-simple, and add a bit more
>     comments
>   - Remove generic clk patch to test if a NULL pointer is returned
>   - Removed misleading message in the is_prepared renaming patch commit
>     message
>   - Constify HDMI controller variants
>   - Fix a bug in the allocation size of the clk data array
>   - Added a mention in the DT binding conversion patches about the breakage
>   - Merged a few fixes from kbuild
>   - Fixed a few bisection and CEC build issues
>   - Collected Acked-by and Reviewed-by
>   - Change Dave email address to raspberrypi.com
> 
> Dave Stevenson (7):
>   drm/vc4: Add support for the BCM2711 HVS5
>   drm/vc4: plane: Change LBM alignment constraint on LBM
>   drm/vc4: plane: Optimize the LBM allocation size
>   drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers
>   drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming
>   drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default.
>   drm/vc4: hdmi: Add audio-related callbacks
> 
> Maxime Ripard (71):
>   dt-bindings: display: Add support for the BCM2711 HVS
>   drm/vc4: hvs: Boost the core clock during modeset
>   drm/vc4: plane: Create more planes
>   drm/vc4: crtc: Deal with different number of pixel per clock
>   drm/vc4: crtc: Use a shared interrupt
>   drm/vc4: crtc: Move the cob allocation outside of bind
>   drm/vc4: crtc: Rename HVS channel to output
>   drm/vc4: crtc: Use local chan variable
>   drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable
>   drm/vc4: kms: Convert to for_each_new_crtc_state
>   drm/vc4: crtc: Assign output to channel automatically
>   drm/vc4: crtc: Add FIFO depth to vc4_crtc_data
>   drm/vc4: crtc: Add function to compute FIFO level bits
>   drm/vc4: crtc: Rename HDMI encoder type to HDMI0
>   drm/vc4: crtc: Add HDMI1 encoder type
>   drm/vc4: crtc: Disable color management for HVS5
>   drm/vc4: crtc: Turn pixelvalve reset into a function
>   drm/vc4: crtc: Move PV dump to config_pv
>   drm/vc4: crtc: Move HVS init and close to a function
>   drm/vc4: crtc: Move the HVS gamma LUT setup to our init function
>   drm/vc4: hvs: Make sure our channel is reset
>   drm/vc4: crtc: Remove mode_set_nofb
>   drm/vc4: crtc: Remove redundant pixelvalve reset
>   drm/vc4: crtc: Move HVS channel init before the PV initialisation
>   drm/vc4: encoder: Add finer-grained encoder callbacks
>   drm/vc4: crtc: Add a delay after disabling the PixelValve output
>   drm/vc4: crtc: Clear the PixelValve FIFO on disable
>   drm/vc4: crtc: Clear the PixelValve FIFO during configuration
>   drm/vc4: hvs: Make the stop_channel function public
>   drm/vc4: hvs: Introduce a function to get the assigned FIFO
>   drm/vc4: crtc: Move the CRTC disable out
>   drm/vc4: drv: Disable the CRTC at boot time
>   dt-bindings: display: vc4: pv: Add BCM2711 pixel valves
>   drm/vc4: crtc: Add BCM2711 pixelvalves
>   drm/vc4: hdmi: Use debugfs private field
>   drm/vc4: hdmi: Move structure to header
>   drm/vc4: hdmi: rework connectors and encoders
>   drm/vc4: hdmi: Remove DDC argument to connector_init
>   drm/vc4: hdmi: Rename hdmi to vc4_hdmi
>   drm/vc4: hdmi: Move accessors to vc4_hdmi
>   drm/vc4: hdmi: Use local vc4_hdmi directly
>   drm/vc4: hdmi: Add container_of macros for encoders and connectors
>   drm/vc4: hdmi: Pass vc4_hdmi to CEC code
>   drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device
>   drm/vc4: hdmi: Remove vc4_dev hdmi pointer
>   drm/vc4: hdmi: Remove vc4_hdmi_connector
>   drm/vc4: hdmi: Introduce resource init and variant
>   drm/vc4: hdmi: Implement a register layout abstraction
>   drm/vc4: hdmi: Add reset callback
>   drm/vc4: hdmi: Add PHY init and disable function
>   drm/vc4: hdmi: Add PHY RNG enable / disable function
>   drm/vc4: hdmi: Add a CSC setup callback
>   drm/vc4: hdmi: Store the encoder type in the variant structure
>   drm/vc4: hdmi: Deal with multiple debugfs files
>   drm/vc4: hdmi: Move CEC init to its own function
>   drm/vc4: hdmi: Add CEC support flag
>   drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define
>   drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid
>   drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
>   drm/vc4: hdmi: Use clk_set_min_rate instead
>   drm/vc4: hdmi: Deal with multiple ALSA cards
>   drm/vc4: hdmi: Remove register dumps in enable
>   drm/vc4: hdmi: Always recenter the HDMI FIFO
>   drm/vc4: hdmi: Implement finer-grained hooks
>   drm/vc4: hdmi: Do the VID_CTL configuration at once
>   drm/vc4: hdmi: Switch to blank pixels when disabled
>   drm/vc4: hdmi: Support the BCM2711 HDMI controllers
>   dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
>   dt-bindings: display: vc4: Document BCM2711 VC5
>   drm/vc4: drv: Support BCM2711
>   ARM: dts: bcm2711: Enable the display pipeline
> 
>  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml        |  109 +++++-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml         |   18 +-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml |    5 +-
>  Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml         |    1 +-
>  arch/arm/boot/dts/bcm2711-rpi-4-b.dts                                   |   46 ++-
>  arch/arm/boot/dts/bcm2711.dtsi                                          |  115 ++++-
>  drivers/gpu/drm/vc4/Makefile                                            |    1 +-
>  drivers/gpu/drm/vc4/vc4_crtc.c                                          |  338 +++++++++++----
>  drivers/gpu/drm/vc4/vc4_drv.c                                           |    5 +-
>  drivers/gpu/drm/vc4/vc4_drv.h                                           |   43 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c                                          | 1625 +++++++++++++++++++++++++++++++++++++++++++-----------------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h                                          |  183 ++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_phy.c                                      |  520 +++++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hdmi_regs.h                                     |  442 ++++++++++++++++++++-
>  drivers/gpu/drm/vc4/vc4_hvs.c                                           |  260 +++++++-----
>  drivers/gpu/drm/vc4/vc4_kms.c                                           |  225 +++++++++-
>  drivers/gpu/drm/vc4/vc4_plane.c                                         |  222 +++++++---
>  drivers/gpu/drm/vc4/vc4_regs.h                                          |  177 +++-----
>  drivers/gpu/drm/vc4/vc4_txp.c                                           |    4 +-
>  19 files changed, 3331 insertions(+), 1008 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi.h
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_phy.c
>  create mode 100644 drivers/gpu/drm/vc4/vc4_hdmi_regs.h
> 
> base-commit: 5bdd2824d705fb8d339d6f96e464b907c9a1553d
> 

I tested it for stress test with reboot command repetitively
for verifying this patchset. It is well working.

Tested-by: Chanwoo Choi <cw00.choi@samsung.com>

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-09-01  4:36       ` Chanwoo Choi
  -1 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01  4:36 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell

Hi Maxime,

On 7/9/20 2:42 AM, Maxime Ripard wrote:
> The HSM clock needs to be setup at around 101% of the pixel rate. This
> was done previously by setting the clock rate to 163.7MHz at probe time and
> only check in mode_valid whether the mode pixel clock was under the pixel
> clock +1% or not.
> 
> However, with 4k we need to change that frequency to a higher frequency
> than 163.7MHz, and yet want to have the lowest clock as possible to have a
> decent power saving.
> 
> Let's change that logic a bit by setting the clock rate of the HSM clock
> to the pixel rate at encoder_enable time. This would work for the
> BCM2711 that support 4k resolutions and has a clock that can provide it,
> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> that wouldn't be able to use those modes, so let's define the limit in
> the variant.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>  2 files changed, 41 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 17797b14cde4..9f30fab744f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -53,7 +53,6 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>  
> -#define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>  
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>  	HDMI_WRITE(HDMI_VID_CTL,
>  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>  
> +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
>  
>  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>  	bool debug_dump_regs = false;
> +	unsigned long pixel_rate, hsm_rate;
>  	int ret;
>  
>  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  		return;
>  	}
>  
> -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
> -			   mode->clock * 1000 *
> -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>  	if (ret) {
>  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>  		return;
> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  		return;
>  	}
>  
> +	/*
> +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> +	 * be faster than pixel clock, infinitesimally faster, tested in
> +	 * simulation. Otherwise, exact value is unimportant for HDMI
> +	 * operation." This conflicts with bcm2835's vc4 documentation, which
> +	 * states HSM's clock has to be at least 108% of the pixel clock.
> +	 *
> +	 * Real life tests reveal that vc4's firmware statement holds up, and
> +	 * users are able to use pixel clocks closer to HSM's, namely for
> +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> +	 * 162MHz.
> +	 *
> +	 * Additionally, the AXI clock needs to be at least 25% of
> +	 * pixel clock, but HSM ends up being the limiting factor.
> +	 */
> +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +	if (ret) {
> +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> +	if (ret) {
> +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
> +		return;
> +	}

About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
with clk_prepare_enable() and then touch the clock like clk_set_rate().
I think that need to enable the clock before calling clk_set_rate().

When I tested this patchset, it is well working because I think that
vc4_hdmi->hsm_clock was already enabled on other side.

> +
>  	if (vc4_hdmi->variant->reset)
>  		vc4_hdmi->variant->reset(vc4_hdmi);
>  
> @@ -559,23 +589,9 @@ static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>  			    const struct drm_display_mode *mode)
>  {
> -	/*
> -	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> -	 * be faster than pixel clock, infinitesimally faster, tested in
> -	 * simulation. Otherwise, exact value is unimportant for HDMI
> -	 * operation." This conflicts with bcm2835's vc4 documentation, which
> -	 * states HSM's clock has to be at least 108% of the pixel clock.
> -	 *
> -	 * Real life tests reveal that vc4's firmware statement holds up, and
> -	 * users are able to use pixel clocks closer to HSM's, namely for
> -	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> -	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> -	 * 162MHz.
> -	 *
> -	 * Additionally, the AXI clock needs to be at least 25% of
> -	 * pixel clock, but HSM ends up being the limiting factor.
> -	 */
> -	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
> +	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +
> +	if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
>  		return MODE_CLOCK_HIGH;
>  
>  	return MODE_OK;
> @@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  		return -EPROBE_DEFER;
>  	}
>  
> -	/* This is the rate that is set by the firmware.  The number
> -	 * needs to be a bit higher than the pixel clock rate
> -	 * (generally 148.5Mhz).
> -	 */
> -	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
> -	if (ret) {
> -		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> -		goto err_put_i2c;
> -	}
> -
> -	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> -	if (ret) {
> -		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
> -			  ret);
> -		goto err_put_i2c;
> -	}
> -
>  	/* Only use the GPIO HPD pin if present in the DT, otherwise
>  	 * we'll use the HDMI core's register.
>  	 */
> @@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_destroy_encoder:
>  	drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> -	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	pm_runtime_disable(dev);
> -err_put_i2c:
>  	put_device(&vc4_hdmi->ddc->dev);
>  
>  	return ret;
> @@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>  	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>  	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>  
> -	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	pm_runtime_disable(dev);
>  
>  	put_device(&vc4_hdmi->ddc->dev);
> @@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>  	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
>  	.debugfs_name		= "hdmi_regs",
> +	.max_pixel_clock	= 162000000,
>  	.cec_available		= true,
>  	.registers		= vc4_hdmi_fields,
>  	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 3f07aebe89f1..342f6e0227a2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
>  	/* Set to true when the CEC support is available */
>  	bool cec_available;
>  
> +	/* Maximum pixel clock supported by the controller (in Hz) */
> +	unsigned long long max_pixel_clock;
> +
>  	/* List of the registers available on that variant */
>  	const struct vc4_hdmi_register *registers;
>  
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-09-01  4:36       ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01  4:36 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

Hi Maxime,

On 7/9/20 2:42 AM, Maxime Ripard wrote:
> The HSM clock needs to be setup at around 101% of the pixel rate. This
> was done previously by setting the clock rate to 163.7MHz at probe time and
> only check in mode_valid whether the mode pixel clock was under the pixel
> clock +1% or not.
> 
> However, with 4k we need to change that frequency to a higher frequency
> than 163.7MHz, and yet want to have the lowest clock as possible to have a
> decent power saving.
> 
> Let's change that logic a bit by setting the clock rate of the HSM clock
> to the pixel rate at encoder_enable time. This would work for the
> BCM2711 that support 4k resolutions and has a clock that can provide it,
> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> that wouldn't be able to use those modes, so let's define the limit in
> the variant.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>  2 files changed, 41 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 17797b14cde4..9f30fab744f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -53,7 +53,6 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>  
> -#define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>  
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>  	HDMI_WRITE(HDMI_VID_CTL,
>  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>  
> +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
>  
>  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>  	bool debug_dump_regs = false;
> +	unsigned long pixel_rate, hsm_rate;
>  	int ret;
>  
>  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  		return;
>  	}
>  
> -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
> -			   mode->clock * 1000 *
> -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>  	if (ret) {
>  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>  		return;
> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  		return;
>  	}
>  
> +	/*
> +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> +	 * be faster than pixel clock, infinitesimally faster, tested in
> +	 * simulation. Otherwise, exact value is unimportant for HDMI
> +	 * operation." This conflicts with bcm2835's vc4 documentation, which
> +	 * states HSM's clock has to be at least 108% of the pixel clock.
> +	 *
> +	 * Real life tests reveal that vc4's firmware statement holds up, and
> +	 * users are able to use pixel clocks closer to HSM's, namely for
> +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> +	 * 162MHz.
> +	 *
> +	 * Additionally, the AXI clock needs to be at least 25% of
> +	 * pixel clock, but HSM ends up being the limiting factor.
> +	 */
> +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +	if (ret) {
> +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> +	if (ret) {
> +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
> +		return;
> +	}

About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
with clk_prepare_enable() and then touch the clock like clk_set_rate().
I think that need to enable the clock before calling clk_set_rate().

When I tested this patchset, it is well working because I think that
vc4_hdmi->hsm_clock was already enabled on other side.

> +
>  	if (vc4_hdmi->variant->reset)
>  		vc4_hdmi->variant->reset(vc4_hdmi);
>  
> @@ -559,23 +589,9 @@ static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>  			    const struct drm_display_mode *mode)
>  {
> -	/*
> -	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> -	 * be faster than pixel clock, infinitesimally faster, tested in
> -	 * simulation. Otherwise, exact value is unimportant for HDMI
> -	 * operation." This conflicts with bcm2835's vc4 documentation, which
> -	 * states HSM's clock has to be at least 108% of the pixel clock.
> -	 *
> -	 * Real life tests reveal that vc4's firmware statement holds up, and
> -	 * users are able to use pixel clocks closer to HSM's, namely for
> -	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> -	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> -	 * 162MHz.
> -	 *
> -	 * Additionally, the AXI clock needs to be at least 25% of
> -	 * pixel clock, but HSM ends up being the limiting factor.
> -	 */
> -	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
> +	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +
> +	if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
>  		return MODE_CLOCK_HIGH;
>  
>  	return MODE_OK;
> @@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  		return -EPROBE_DEFER;
>  	}
>  
> -	/* This is the rate that is set by the firmware.  The number
> -	 * needs to be a bit higher than the pixel clock rate
> -	 * (generally 148.5Mhz).
> -	 */
> -	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
> -	if (ret) {
> -		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> -		goto err_put_i2c;
> -	}
> -
> -	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> -	if (ret) {
> -		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
> -			  ret);
> -		goto err_put_i2c;
> -	}
> -
>  	/* Only use the GPIO HPD pin if present in the DT, otherwise
>  	 * we'll use the HDMI core's register.
>  	 */
> @@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_destroy_encoder:
>  	drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> -	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	pm_runtime_disable(dev);
> -err_put_i2c:
>  	put_device(&vc4_hdmi->ddc->dev);
>  
>  	return ret;
> @@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>  	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>  	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>  
> -	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	pm_runtime_disable(dev);
>  
>  	put_device(&vc4_hdmi->ddc->dev);
> @@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>  	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
>  	.debugfs_name		= "hdmi_regs",
> +	.max_pixel_clock	= 162000000,
>  	.cec_available		= true,
>  	.registers		= vc4_hdmi_fields,
>  	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 3f07aebe89f1..342f6e0227a2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
>  	/* Set to true when the CEC support is available */
>  	bool cec_available;
>  
> +	/* Maximum pixel clock supported by the controller (in Hz) */
> +	unsigned long long max_pixel_clock;
> +
>  	/* List of the registers available on that variant */
>  	const struct vc4_hdmi_register *registers;
>  
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-09-01  4:36       ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01  4:36 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

Hi Maxime,

On 7/9/20 2:42 AM, Maxime Ripard wrote:
> The HSM clock needs to be setup at around 101% of the pixel rate. This
> was done previously by setting the clock rate to 163.7MHz at probe time and
> only check in mode_valid whether the mode pixel clock was under the pixel
> clock +1% or not.
> 
> However, with 4k we need to change that frequency to a higher frequency
> than 163.7MHz, and yet want to have the lowest clock as possible to have a
> decent power saving.
> 
> Let's change that logic a bit by setting the clock rate of the HSM clock
> to the pixel rate at encoder_enable time. This would work for the
> BCM2711 that support 4k resolutions and has a clock that can provide it,
> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> that wouldn't be able to use those modes, so let's define the limit in
> the variant.
> 
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>  2 files changed, 41 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index 17797b14cde4..9f30fab744f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -53,7 +53,6 @@
>  #include "vc4_hdmi_regs.h"
>  #include "vc4_regs.h"
>  
> -#define HSM_CLOCK_FREQ 163682864
>  #define CEC_CLOCK_FREQ 40000
>  
>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>  	HDMI_WRITE(HDMI_VID_CTL,
>  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>  
> +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
>  
>  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>  	bool debug_dump_regs = false;
> +	unsigned long pixel_rate, hsm_rate;
>  	int ret;
>  
>  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  		return;
>  	}
>  
> -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
> -			   mode->clock * 1000 *
> -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>  	if (ret) {
>  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>  		return;
> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>  		return;
>  	}
>  
> +	/*
> +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> +	 * be faster than pixel clock, infinitesimally faster, tested in
> +	 * simulation. Otherwise, exact value is unimportant for HDMI
> +	 * operation." This conflicts with bcm2835's vc4 documentation, which
> +	 * states HSM's clock has to be at least 108% of the pixel clock.
> +	 *
> +	 * Real life tests reveal that vc4's firmware statement holds up, and
> +	 * users are able to use pixel clocks closer to HSM's, namely for
> +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> +	 * 162MHz.
> +	 *
> +	 * Additionally, the AXI clock needs to be at least 25% of
> +	 * pixel clock, but HSM ends up being the limiting factor.
> +	 */
> +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> +	if (ret) {
> +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> +		return;
> +	}
> +
> +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> +	if (ret) {
> +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
> +		return;
> +	}

About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
with clk_prepare_enable() and then touch the clock like clk_set_rate().
I think that need to enable the clock before calling clk_set_rate().

When I tested this patchset, it is well working because I think that
vc4_hdmi->hsm_clock was already enabled on other side.

> +
>  	if (vc4_hdmi->variant->reset)
>  		vc4_hdmi->variant->reset(vc4_hdmi);
>  
> @@ -559,23 +589,9 @@ static enum drm_mode_status
>  vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
>  			    const struct drm_display_mode *mode)
>  {
> -	/*
> -	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> -	 * be faster than pixel clock, infinitesimally faster, tested in
> -	 * simulation. Otherwise, exact value is unimportant for HDMI
> -	 * operation." This conflicts with bcm2835's vc4 documentation, which
> -	 * states HSM's clock has to be at least 108% of the pixel clock.
> -	 *
> -	 * Real life tests reveal that vc4's firmware statement holds up, and
> -	 * users are able to use pixel clocks closer to HSM's, namely for
> -	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> -	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> -	 * 162MHz.
> -	 *
> -	 * Additionally, the AXI clock needs to be at least 25% of
> -	 * pixel clock, but HSM ends up being the limiting factor.
> -	 */
> -	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
> +	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> +
> +	if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock)
>  		return MODE_CLOCK_HIGH;
>  
>  	return MODE_OK;
> @@ -1349,23 +1365,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  		return -EPROBE_DEFER;
>  	}
>  
> -	/* This is the rate that is set by the firmware.  The number
> -	 * needs to be a bit higher than the pixel clock rate
> -	 * (generally 148.5Mhz).
> -	 */
> -	ret = clk_set_rate(vc4_hdmi->hsm_clock, HSM_CLOCK_FREQ);
> -	if (ret) {
> -		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> -		goto err_put_i2c;
> -	}
> -
> -	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> -	if (ret) {
> -		DRM_ERROR("Failed to turn on HDMI state machine clock: %d\n",
> -			  ret);
> -		goto err_put_i2c;
> -	}
> -
>  	/* Only use the GPIO HPD pin if present in the DT, otherwise
>  	 * we'll use the HDMI core's register.
>  	 */
> @@ -1413,9 +1412,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
>  err_destroy_encoder:
>  	drm_encoder_cleanup(encoder);
>  err_unprepare_hsm:
> -	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	pm_runtime_disable(dev);
> -err_put_i2c:
>  	put_device(&vc4_hdmi->ddc->dev);
>  
>  	return ret;
> @@ -1454,7 +1451,6 @@ static void vc4_hdmi_unbind(struct device *dev, struct device *master,
>  	vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
>  	drm_encoder_cleanup(&vc4_hdmi->encoder.base.base);
>  
> -	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>  	pm_runtime_disable(dev);
>  
>  	put_device(&vc4_hdmi->ddc->dev);
> @@ -1479,6 +1475,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
>  static const struct vc4_hdmi_variant bcm2835_variant = {
>  	.encoder_type		= VC4_ENCODER_TYPE_HDMI0,
>  	.debugfs_name		= "hdmi_regs",
> +	.max_pixel_clock	= 162000000,
>  	.cec_available		= true,
>  	.registers		= vc4_hdmi_fields,
>  	.num_registers		= ARRAY_SIZE(vc4_hdmi_fields),
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
> index 3f07aebe89f1..342f6e0227a2 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.h
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
> @@ -36,6 +36,9 @@ struct vc4_hdmi_variant {
>  	/* Set to true when the CEC support is available */
>  	bool cec_available;
>  
> +	/* Maximum pixel clock supported by the controller (in Hz) */
> +	unsigned long long max_pixel_clock;
> +
>  	/* List of the registers available on that variant */
>  	const struct vc4_hdmi_register *registers;
>  
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
  2020-07-08 17:42     ` Maxime Ripard
  (?)
@ 2020-09-01  4:45       ` Chanwoo Choi
  -1 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01  4:45 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell, Rob Herring

Hi Maxime,

On 7/9/20 2:42 AM, Maxime Ripard wrote:
> The HDMI controllers found in the BCM2711 SoC need some adjustments to the
> bindings, especially since the registers have been shuffled around in more
> register ranges.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 109 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> new file mode 100644
> index 000000000000..6091fe3d315b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: https://protect2.fireeye.com/url?k=556aeb05-08b8fda0-556b604a-0cc47a31bee8-c3a0ebd1d22c3183&q=1&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbrcm%2Cbcm2711-hdmi.yaml%23
> +$schema: https://protect2.fireeye.com/url?k=24fa660c-792870a9-24fbed43-0cc47a31bee8-0bf16f4fd60f0ab4&q=1&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23
> +
> +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
> +
> +maintainers:
> +  - Eric Anholt <eric@anholt.net>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - brcm,bcm2711-hdmi0
> +      - brcm,bcm2711-hdmi1
> +
> +  reg:
> +    items:
> +      - description: HDMI controller register range
> +      - description: DVP register range
> +      - description: HDMI PHY register range
> +      - description: Rate Manager register range
> +      - description: Packet RAM register range
> +      - description: Metadata RAM register range
> +      - description: CSC register range
> +      - description: CEC register range
> +      - description: HD register range
> +
> +  reg-names:
> +    items:
> +      - const: hdmi
> +      - const: dvp
> +      - const: phy
> +      - const: rm
> +      - const: packet
> +      - const: metadata
> +      - const: csc
> +      - const: cec
> +      - const: hd
> +
> +  clocks:
> +    description: The HDMI state machine clock

I'm not sure the following description is correct.
But, this description doesn't contain the information of audio clock.

	description: The HDMI state machine and audio clock

> +
> +  clock-names:
> +    const: hdmi

This patch is missing the following clock information for audio clock.

	const: clk-108M

> +
> +  ddc:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: >
> +      Phandle of the I2C controller used for DDC EDID probing
> +
> +  hpd-gpios:
> +    description: >
> +      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
> +      as an interrupt/status bit in the HDMI controller itself)
> +
> +  dmas:
> +    maxItems: 1
> +    description: >
> +      Should contain one entry pointing to the DMA channel used to
> +      transfer audio data.
> +
> +  dma-names:
> +    const: audio-rx
> +
> +  resets:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - resets
> +  - ddc
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    hdmi0: hdmi@7ef00700 {
> +        compatible = "brcm,bcm2711-hdmi0";
> +        reg = <0x7ef00700 0x300>,
> +              <0x7ef00300 0x200>,
> +              <0x7ef00f00 0x80>,
> +              <0x7ef00f80 0x80>,
> +              <0x7ef01b00 0x200>,
> +              <0x7ef01f00 0x400>,
> +              <0x7ef00200 0x80>,
> +              <0x7ef04300 0x100>,
> +              <0x7ef20000 0x100>;
> +        reg-names = "hdmi",
> +                    "dvp",
> +                    "phy",
> +                    "rm",
> +                    "packet",
> +                    "metadata",
> +                    "csc",
> +                    "cec",
> +                    "hd";
> +        clocks = <&firmware_clocks 13>;
> +        clock-names = "hdmi";

Also, this example doesn't include the instance of audio clock.
Need to edit them as following:

	clock-names = "hdmi", "clk-108M";
	clocks = <&firmware_clocks 13>, <&dvp 0>;


> +        resets = <&dvp 0>;
> +        ddc = <&ddc0>;
> +    };
> +
> +...
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
@ 2020-09-01  4:45       ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01  4:45 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Rob Herring, Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

Hi Maxime,

On 7/9/20 2:42 AM, Maxime Ripard wrote:
> The HDMI controllers found in the BCM2711 SoC need some adjustments to the
> bindings, especially since the registers have been shuffled around in more
> register ranges.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 109 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> new file mode 100644
> index 000000000000..6091fe3d315b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: https://protect2.fireeye.com/url?k=556aeb05-08b8fda0-556b604a-0cc47a31bee8-c3a0ebd1d22c3183&q=1&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbrcm%2Cbcm2711-hdmi.yaml%23
> +$schema: https://protect2.fireeye.com/url?k=24fa660c-792870a9-24fbed43-0cc47a31bee8-0bf16f4fd60f0ab4&q=1&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23
> +
> +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
> +
> +maintainers:
> +  - Eric Anholt <eric@anholt.net>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - brcm,bcm2711-hdmi0
> +      - brcm,bcm2711-hdmi1
> +
> +  reg:
> +    items:
> +      - description: HDMI controller register range
> +      - description: DVP register range
> +      - description: HDMI PHY register range
> +      - description: Rate Manager register range
> +      - description: Packet RAM register range
> +      - description: Metadata RAM register range
> +      - description: CSC register range
> +      - description: CEC register range
> +      - description: HD register range
> +
> +  reg-names:
> +    items:
> +      - const: hdmi
> +      - const: dvp
> +      - const: phy
> +      - const: rm
> +      - const: packet
> +      - const: metadata
> +      - const: csc
> +      - const: cec
> +      - const: hd
> +
> +  clocks:
> +    description: The HDMI state machine clock

I'm not sure the following description is correct.
But, this description doesn't contain the information of audio clock.

	description: The HDMI state machine and audio clock

> +
> +  clock-names:
> +    const: hdmi

This patch is missing the following clock information for audio clock.

	const: clk-108M

> +
> +  ddc:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: >
> +      Phandle of the I2C controller used for DDC EDID probing
> +
> +  hpd-gpios:
> +    description: >
> +      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
> +      as an interrupt/status bit in the HDMI controller itself)
> +
> +  dmas:
> +    maxItems: 1
> +    description: >
> +      Should contain one entry pointing to the DMA channel used to
> +      transfer audio data.
> +
> +  dma-names:
> +    const: audio-rx
> +
> +  resets:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - resets
> +  - ddc
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    hdmi0: hdmi@7ef00700 {
> +        compatible = "brcm,bcm2711-hdmi0";
> +        reg = <0x7ef00700 0x300>,
> +              <0x7ef00300 0x200>,
> +              <0x7ef00f00 0x80>,
> +              <0x7ef00f80 0x80>,
> +              <0x7ef01b00 0x200>,
> +              <0x7ef01f00 0x400>,
> +              <0x7ef00200 0x80>,
> +              <0x7ef04300 0x100>,
> +              <0x7ef20000 0x100>;
> +        reg-names = "hdmi",
> +                    "dvp",
> +                    "phy",
> +                    "rm",
> +                    "packet",
> +                    "metadata",
> +                    "csc",
> +                    "cec",
> +                    "hd";
> +        clocks = <&firmware_clocks 13>;
> +        clock-names = "hdmi";

Also, this example doesn't include the instance of audio clock.
Need to edit them as following:

	clock-names = "hdmi", "clk-108M";
	clocks = <&firmware_clocks 13>, <&dvp 0>;


> +        resets = <&dvp 0>;
> +        ddc = <&ddc0>;
> +    };
> +
> +...
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
@ 2020-09-01  4:45       ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01  4:45 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

Hi Maxime,

On 7/9/20 2:42 AM, Maxime Ripard wrote:
> The HDMI controllers found in the BCM2711 SoC need some adjustments to the
> bindings, especially since the registers have been shuffled around in more
> register ranges.
> 
> Reviewed-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 109 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> 
> diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> new file mode 100644
> index 000000000000..6091fe3d315b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> @@ -0,0 +1,109 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: https://protect2.fireeye.com/url?k=556aeb05-08b8fda0-556b604a-0cc47a31bee8-c3a0ebd1d22c3183&q=1&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbrcm%2Cbcm2711-hdmi.yaml%23
> +$schema: https://protect2.fireeye.com/url?k=24fa660c-792870a9-24fbed43-0cc47a31bee8-0bf16f4fd60f0ab4&q=1&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23
> +
> +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
> +
> +maintainers:
> +  - Eric Anholt <eric@anholt.net>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - brcm,bcm2711-hdmi0
> +      - brcm,bcm2711-hdmi1
> +
> +  reg:
> +    items:
> +      - description: HDMI controller register range
> +      - description: DVP register range
> +      - description: HDMI PHY register range
> +      - description: Rate Manager register range
> +      - description: Packet RAM register range
> +      - description: Metadata RAM register range
> +      - description: CSC register range
> +      - description: CEC register range
> +      - description: HD register range
> +
> +  reg-names:
> +    items:
> +      - const: hdmi
> +      - const: dvp
> +      - const: phy
> +      - const: rm
> +      - const: packet
> +      - const: metadata
> +      - const: csc
> +      - const: cec
> +      - const: hd
> +
> +  clocks:
> +    description: The HDMI state machine clock

I'm not sure the following description is correct.
But, this description doesn't contain the information of audio clock.

	description: The HDMI state machine and audio clock

> +
> +  clock-names:
> +    const: hdmi

This patch is missing the following clock information for audio clock.

	const: clk-108M

> +
> +  ddc:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: >
> +      Phandle of the I2C controller used for DDC EDID probing
> +
> +  hpd-gpios:
> +    description: >
> +      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
> +      as an interrupt/status bit in the HDMI controller itself)
> +
> +  dmas:
> +    maxItems: 1
> +    description: >
> +      Should contain one entry pointing to the DMA channel used to
> +      transfer audio data.
> +
> +  dma-names:
> +    const: audio-rx
> +
> +  resets:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - resets
> +  - ddc
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    hdmi0: hdmi@7ef00700 {
> +        compatible = "brcm,bcm2711-hdmi0";
> +        reg = <0x7ef00700 0x300>,
> +              <0x7ef00300 0x200>,
> +              <0x7ef00f00 0x80>,
> +              <0x7ef00f80 0x80>,
> +              <0x7ef01b00 0x200>,
> +              <0x7ef01f00 0x400>,
> +              <0x7ef00200 0x80>,
> +              <0x7ef04300 0x100>,
> +              <0x7ef20000 0x100>;
> +        reg-names = "hdmi",
> +                    "dvp",
> +                    "phy",
> +                    "rm",
> +                    "packet",
> +                    "metadata",
> +                    "csc",
> +                    "cec",
> +                    "hd";
> +        clocks = <&firmware_clocks 13>;
> +        clock-names = "hdmi";

Also, this example doesn't include the instance of audio clock.
Need to edit them as following:

	clock-names = "hdmi", "clk-108M";
	clocks = <&firmware_clocks 13>, <&dvp 0>;


> +        resets = <&dvp 0>;
> +        ddc = <&ddc0>;
> +    };
> +
> +...
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  2020-09-01  4:36       ` Chanwoo Choi
  (?)
@ 2020-09-01  9:45         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:45 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Nicolas Saenz Julienne, Eric Anholt, dri-devel, linux-rpi-kernel,
	bcm-kernel-feedback-list, linux-arm-kernel, linux-kernel,
	Dave Stevenson, Tim Gover, Phil Elwell

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

Hi Chanwoo,

On Tue, Sep 01, 2020 at 01:36:17PM +0900, Chanwoo Choi wrote:
> On 7/9/20 2:42 AM, Maxime Ripard wrote:
> > The HSM clock needs to be setup at around 101% of the pixel rate. This
> > was done previously by setting the clock rate to 163.7MHz at probe time and
> > only check in mode_valid whether the mode pixel clock was under the pixel
> > clock +1% or not.
> > 
> > However, with 4k we need to change that frequency to a higher frequency
> > than 163.7MHz, and yet want to have the lowest clock as possible to have a
> > decent power saving.
> > 
> > Let's change that logic a bit by setting the clock rate of the HSM clock
> > to the pixel rate at encoder_enable time. This would work for the
> > BCM2711 that support 4k resolutions and has a clock that can provide it,
> > but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> > that wouldn't be able to use those modes, so let's define the limit in
> > the variant.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
> >  2 files changed, 41 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 17797b14cde4..9f30fab744f2 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -53,7 +53,6 @@
> >  #include "vc4_hdmi_regs.h"
> >  #include "vc4_regs.h"
> >  
> > -#define HSM_CLOCK_FREQ 163682864
> >  #define CEC_CLOCK_FREQ 40000
> >  
> >  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> > @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> >  	HDMI_WRITE(HDMI_VID_CTL,
> >  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
> >  
> > +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
> >  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
> >  
> >  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> > @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> >  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> >  	bool debug_dump_regs = false;
> > +	unsigned long pixel_rate, hsm_rate;
> >  	int ret;
> >  
> >  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> > @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  		return;
> >  	}
> >  
> > -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
> > -			   mode->clock * 1000 *
> > -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> > +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> > +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
> >  	if (ret) {
> >  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
> >  		return;
> > @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  		return;
> >  	}
> >  
> > +	/*
> > +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> > +	 * be faster than pixel clock, infinitesimally faster, tested in
> > +	 * simulation. Otherwise, exact value is unimportant for HDMI
> > +	 * operation." This conflicts with bcm2835's vc4 documentation, which
> > +	 * states HSM's clock has to be at least 108% of the pixel clock.
> > +	 *
> > +	 * Real life tests reveal that vc4's firmware statement holds up, and
> > +	 * users are able to use pixel clocks closer to HSM's, namely for
> > +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> > +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> > +	 * 162MHz.
> > +	 *
> > +	 * Additionally, the AXI clock needs to be at least 25% of
> > +	 * pixel clock, but HSM ends up being the limiting factor.
> > +	 */
> > +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> > +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> > +		return;
> > +	}
> > +
> > +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> > +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
> > +		return;
> > +	}
> 
> About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
> with clk_prepare_enable() and then touch the clock like clk_set_rate().
> I think that need to enable the clock before calling clk_set_rate().
> 
> When I tested this patchset, it is well working because I think that
> vc4_hdmi->hsm_clock was already enabled on other side.

There's no clear rule here on the ordering (at least enforced by the
framework). There's clocks that need to be disabled to change their rate
(CLK_SET_RATE_GATE) and some that need to be enabled to change their
rate (CLK_SET_RATE_UNGATE).

Generally speaking, it seems more logical to me to have first the rate
changed and then the clock enabled since it won't create any "hiccup",
but I could very well see the opposite to be preferred.

Maxime

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

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-09-01  9:45         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:45 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi Chanwoo,

On Tue, Sep 01, 2020 at 01:36:17PM +0900, Chanwoo Choi wrote:
> On 7/9/20 2:42 AM, Maxime Ripard wrote:
> > The HSM clock needs to be setup at around 101% of the pixel rate. This
> > was done previously by setting the clock rate to 163.7MHz at probe time and
> > only check in mode_valid whether the mode pixel clock was under the pixel
> > clock +1% or not.
> > 
> > However, with 4k we need to change that frequency to a higher frequency
> > than 163.7MHz, and yet want to have the lowest clock as possible to have a
> > decent power saving.
> > 
> > Let's change that logic a bit by setting the clock rate of the HSM clock
> > to the pixel rate at encoder_enable time. This would work for the
> > BCM2711 that support 4k resolutions and has a clock that can provide it,
> > but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> > that wouldn't be able to use those modes, so let's define the limit in
> > the variant.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
> >  2 files changed, 41 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 17797b14cde4..9f30fab744f2 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -53,7 +53,6 @@
> >  #include "vc4_hdmi_regs.h"
> >  #include "vc4_regs.h"
> >  
> > -#define HSM_CLOCK_FREQ 163682864
> >  #define CEC_CLOCK_FREQ 40000
> >  
> >  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> > @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> >  	HDMI_WRITE(HDMI_VID_CTL,
> >  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
> >  
> > +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
> >  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
> >  
> >  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> > @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> >  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> >  	bool debug_dump_regs = false;
> > +	unsigned long pixel_rate, hsm_rate;
> >  	int ret;
> >  
> >  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> > @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  		return;
> >  	}
> >  
> > -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
> > -			   mode->clock * 1000 *
> > -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> > +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> > +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
> >  	if (ret) {
> >  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
> >  		return;
> > @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  		return;
> >  	}
> >  
> > +	/*
> > +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> > +	 * be faster than pixel clock, infinitesimally faster, tested in
> > +	 * simulation. Otherwise, exact value is unimportant for HDMI
> > +	 * operation." This conflicts with bcm2835's vc4 documentation, which
> > +	 * states HSM's clock has to be at least 108% of the pixel clock.
> > +	 *
> > +	 * Real life tests reveal that vc4's firmware statement holds up, and
> > +	 * users are able to use pixel clocks closer to HSM's, namely for
> > +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> > +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> > +	 * 162MHz.
> > +	 *
> > +	 * Additionally, the AXI clock needs to be at least 25% of
> > +	 * pixel clock, but HSM ends up being the limiting factor.
> > +	 */
> > +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> > +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> > +		return;
> > +	}
> > +
> > +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> > +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
> > +		return;
> > +	}
> 
> About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
> with clk_prepare_enable() and then touch the clock like clk_set_rate().
> I think that need to enable the clock before calling clk_set_rate().
> 
> When I tested this patchset, it is well working because I think that
> vc4_hdmi->hsm_clock was already enabled on other side.

There's no clear rule here on the ordering (at least enforced by the
framework). There's clocks that need to be disabled to change their rate
(CLK_SET_RATE_GATE) and some that need to be enabled to change their
rate (CLK_SET_RATE_UNGATE).

Generally speaking, it seems more logical to me to have first the rate
changed and then the clock enabled since it won't create any "hiccup",
but I could very well see the opposite to be preferred.

Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-09-01  9:45         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:45 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi Chanwoo,

On Tue, Sep 01, 2020 at 01:36:17PM +0900, Chanwoo Choi wrote:
> On 7/9/20 2:42 AM, Maxime Ripard wrote:
> > The HSM clock needs to be setup at around 101% of the pixel rate. This
> > was done previously by setting the clock rate to 163.7MHz at probe time and
> > only check in mode_valid whether the mode pixel clock was under the pixel
> > clock +1% or not.
> > 
> > However, with 4k we need to change that frequency to a higher frequency
> > than 163.7MHz, and yet want to have the lowest clock as possible to have a
> > decent power saving.
> > 
> > Let's change that logic a bit by setting the clock rate of the HSM clock
> > to the pixel rate at encoder_enable time. This would work for the
> > BCM2711 that support 4k resolutions and has a clock that can provide it,
> > but we still have to take care of a 4k panel plugged on a BCM283x SoCs
> > that wouldn't be able to use those modes, so let's define the limit in
> > the variant.
> > 
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
> >  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
> >  2 files changed, 41 insertions(+), 41 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > index 17797b14cde4..9f30fab744f2 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> > @@ -53,7 +53,6 @@
> >  #include "vc4_hdmi_regs.h"
> >  #include "vc4_regs.h"
> >  
> > -#define HSM_CLOCK_FREQ 163682864
> >  #define CEC_CLOCK_FREQ 40000
> >  
> >  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
> > @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
> >  	HDMI_WRITE(HDMI_VID_CTL,
> >  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
> >  
> > +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
> >  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
> >  
> >  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
> > @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
> >  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
> >  	bool debug_dump_regs = false;
> > +	unsigned long pixel_rate, hsm_rate;
> >  	int ret;
> >  
> >  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
> > @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  		return;
> >  	}
> >  
> > -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
> > -			   mode->clock * 1000 *
> > -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
> > +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
> > +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
> >  	if (ret) {
> >  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
> >  		return;
> > @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
> >  		return;
> >  	}
> >  
> > +	/*
> > +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
> > +	 * be faster than pixel clock, infinitesimally faster, tested in
> > +	 * simulation. Otherwise, exact value is unimportant for HDMI
> > +	 * operation." This conflicts with bcm2835's vc4 documentation, which
> > +	 * states HSM's clock has to be at least 108% of the pixel clock.
> > +	 *
> > +	 * Real life tests reveal that vc4's firmware statement holds up, and
> > +	 * users are able to use pixel clocks closer to HSM's, namely for
> > +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
> > +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
> > +	 * 162MHz.
> > +	 *
> > +	 * Additionally, the AXI clock needs to be at least 25% of
> > +	 * pixel clock, but HSM ends up being the limiting factor.
> > +	 */
> > +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
> > +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
> > +		return;
> > +	}
> > +
> > +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
> > +	if (ret) {
> > +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
> > +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
> > +		return;
> > +	}
> 
> About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
> with clk_prepare_enable() and then touch the clock like clk_set_rate().
> I think that need to enable the clock before calling clk_set_rate().
> 
> When I tested this patchset, it is well working because I think that
> vc4_hdmi->hsm_clock was already enabled on other side.

There's no clear rule here on the ordering (at least enforced by the
framework). There's clocks that need to be disabled to change their rate
(CLK_SET_RATE_GATE) and some that need to be enabled to change their
rate (CLK_SET_RATE_UNGATE).

Generally speaking, it seems more logical to me to have first the rate
changed and then the clock enabled since it won't create any "hiccup",
but I could very well see the opposite to be preferred.

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
  2020-09-01  4:45       ` Chanwoo Choi
  (?)
@ 2020-09-01  9:52         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:52 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Nicolas Saenz Julienne, Eric Anholt, dri-devel, linux-rpi-kernel,
	bcm-kernel-feedback-list, linux-arm-kernel, linux-kernel,
	Dave Stevenson, Tim Gover, Phil Elwell, Rob Herring

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

Hi,

On Tue, Sep 01, 2020 at 01:45:07PM +0900, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:42 AM, Maxime Ripard wrote:
> > The HDMI controllers found in the BCM2711 SoC need some adjustments to the
> > bindings, especially since the registers have been shuffled around in more
> > register ranges.
> > 
> > Reviewed-by: Rob Herring <robh@kernel.org>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 109 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > new file mode 100644
> > index 000000000000..6091fe3d315b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > @@ -0,0 +1,109 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: https://protect2.fireeye.com/url?k=556aeb05-08b8fda0-556b604a-0cc47a31bee8-c3a0ebd1d22c3183&q=1&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbrcm%2Cbcm2711-hdmi.yaml%23
> > +$schema: https://protect2.fireeye.com/url?k=24fa660c-792870a9-24fbed43-0cc47a31bee8-0bf16f4fd60f0ab4&q=1&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23
> > +
> > +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
> > +
> > +maintainers:
> > +  - Eric Anholt <eric@anholt.net>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - brcm,bcm2711-hdmi0
> > +      - brcm,bcm2711-hdmi1
> > +
> > +  reg:
> > +    items:
> > +      - description: HDMI controller register range
> > +      - description: DVP register range
> > +      - description: HDMI PHY register range
> > +      - description: Rate Manager register range
> > +      - description: Packet RAM register range
> > +      - description: Metadata RAM register range
> > +      - description: CSC register range
> > +      - description: CEC register range
> > +      - description: HD register range
> > +
> > +  reg-names:
> > +    items:
> > +      - const: hdmi
> > +      - const: dvp
> > +      - const: phy
> > +      - const: rm
> > +      - const: packet
> > +      - const: metadata
> > +      - const: csc
> > +      - const: cec
> > +      - const: hd
> > +
> > +  clocks:
> > +    description: The HDMI state machine clock
> 
> I'm not sure the following description is correct.
> But, this description doesn't contain the information of audio clock.
> 
> 	description: The HDMI state machine and audio clock
> 
> > +
> > +  clock-names:
> > +    const: hdmi
> 
> This patch is missing the following clock information for audio clock.
> 
> 	const: clk-108M
> 
> > +
> > +  ddc:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: >
> > +      Phandle of the I2C controller used for DDC EDID probing
> > +
> > +  hpd-gpios:
> > +    description: >
> > +      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
> > +      as an interrupt/status bit in the HDMI controller itself)
> > +
> > +  dmas:
> > +    maxItems: 1
> > +    description: >
> > +      Should contain one entry pointing to the DMA channel used to
> > +      transfer audio data.
> > +
> > +  dma-names:
> > +    const: audio-rx
> > +
> > +  resets:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - reg-names
> > +  - clocks
> > +  - resets
> > +  - ddc
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    hdmi0: hdmi@7ef00700 {
> > +        compatible = "brcm,bcm2711-hdmi0";
> > +        reg = <0x7ef00700 0x300>,
> > +              <0x7ef00300 0x200>,
> > +              <0x7ef00f00 0x80>,
> > +              <0x7ef00f80 0x80>,
> > +              <0x7ef01b00 0x200>,
> > +              <0x7ef01f00 0x400>,
> > +              <0x7ef00200 0x80>,
> > +              <0x7ef04300 0x100>,
> > +              <0x7ef20000 0x100>;
> > +        reg-names = "hdmi",
> > +                    "dvp",
> > +                    "phy",
> > +                    "rm",
> > +                    "packet",
> > +                    "metadata",
> > +                    "csc",
> > +                    "cec",
> > +                    "hd";
> > +        clocks = <&firmware_clocks 13>;
> > +        clock-names = "hdmi";
> 
> Also, this example doesn't include the instance of audio clock.
> Need to edit them as following:
> 
> 	clock-names = "hdmi", "clk-108M";
> 	clocks = <&firmware_clocks 13>, <&dvp 0>;

Indeed, thanks for pointing it out

Maxime

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

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

* Re: [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
@ 2020-09-01  9:52         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:52 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Rob Herring, Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	Eric Anholt, bcm-kernel-feedback-list, Nicolas Saenz Julienne,
	Phil Elwell, linux-arm-kernel, linux-rpi-kernel


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

Hi,

On Tue, Sep 01, 2020 at 01:45:07PM +0900, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:42 AM, Maxime Ripard wrote:
> > The HDMI controllers found in the BCM2711 SoC need some adjustments to the
> > bindings, especially since the registers have been shuffled around in more
> > register ranges.
> > 
> > Reviewed-by: Rob Herring <robh@kernel.org>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 109 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > new file mode 100644
> > index 000000000000..6091fe3d315b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > @@ -0,0 +1,109 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: https://protect2.fireeye.com/url?k=556aeb05-08b8fda0-556b604a-0cc47a31bee8-c3a0ebd1d22c3183&q=1&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbrcm%2Cbcm2711-hdmi.yaml%23
> > +$schema: https://protect2.fireeye.com/url?k=24fa660c-792870a9-24fbed43-0cc47a31bee8-0bf16f4fd60f0ab4&q=1&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23
> > +
> > +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
> > +
> > +maintainers:
> > +  - Eric Anholt <eric@anholt.net>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - brcm,bcm2711-hdmi0
> > +      - brcm,bcm2711-hdmi1
> > +
> > +  reg:
> > +    items:
> > +      - description: HDMI controller register range
> > +      - description: DVP register range
> > +      - description: HDMI PHY register range
> > +      - description: Rate Manager register range
> > +      - description: Packet RAM register range
> > +      - description: Metadata RAM register range
> > +      - description: CSC register range
> > +      - description: CEC register range
> > +      - description: HD register range
> > +
> > +  reg-names:
> > +    items:
> > +      - const: hdmi
> > +      - const: dvp
> > +      - const: phy
> > +      - const: rm
> > +      - const: packet
> > +      - const: metadata
> > +      - const: csc
> > +      - const: cec
> > +      - const: hd
> > +
> > +  clocks:
> > +    description: The HDMI state machine clock
> 
> I'm not sure the following description is correct.
> But, this description doesn't contain the information of audio clock.
> 
> 	description: The HDMI state machine and audio clock
> 
> > +
> > +  clock-names:
> > +    const: hdmi
> 
> This patch is missing the following clock information for audio clock.
> 
> 	const: clk-108M
> 
> > +
> > +  ddc:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: >
> > +      Phandle of the I2C controller used for DDC EDID probing
> > +
> > +  hpd-gpios:
> > +    description: >
> > +      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
> > +      as an interrupt/status bit in the HDMI controller itself)
> > +
> > +  dmas:
> > +    maxItems: 1
> > +    description: >
> > +      Should contain one entry pointing to the DMA channel used to
> > +      transfer audio data.
> > +
> > +  dma-names:
> > +    const: audio-rx
> > +
> > +  resets:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - reg-names
> > +  - clocks
> > +  - resets
> > +  - ddc
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    hdmi0: hdmi@7ef00700 {
> > +        compatible = "brcm,bcm2711-hdmi0";
> > +        reg = <0x7ef00700 0x300>,
> > +              <0x7ef00300 0x200>,
> > +              <0x7ef00f00 0x80>,
> > +              <0x7ef00f80 0x80>,
> > +              <0x7ef01b00 0x200>,
> > +              <0x7ef01f00 0x400>,
> > +              <0x7ef00200 0x80>,
> > +              <0x7ef04300 0x100>,
> > +              <0x7ef20000 0x100>;
> > +        reg-names = "hdmi",
> > +                    "dvp",
> > +                    "phy",
> > +                    "rm",
> > +                    "packet",
> > +                    "metadata",
> > +                    "csc",
> > +                    "cec",
> > +                    "hd";
> > +        clocks = <&firmware_clocks 13>;
> > +        clock-names = "hdmi";
> 
> Also, this example doesn't include the instance of audio clock.
> Need to edit them as following:
> 
> 	clock-names = "hdmi", "clk-108M";
> 	clocks = <&firmware_clocks 13>, <&dvp 0>;

Indeed, thanks for pointing it out

Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
@ 2020-09-01  9:52         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:52 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi,

On Tue, Sep 01, 2020 at 01:45:07PM +0900, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:42 AM, Maxime Ripard wrote:
> > The HDMI controllers found in the BCM2711 SoC need some adjustments to the
> > bindings, especially since the registers have been shuffled around in more
> > register ranges.
> > 
> > Reviewed-by: Rob Herring <robh@kernel.org>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 109 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > 
> > diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > new file mode 100644
> > index 000000000000..6091fe3d315b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/brcm,bcm2711-hdmi.yaml
> > @@ -0,0 +1,109 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: https://protect2.fireeye.com/url?k=556aeb05-08b8fda0-556b604a-0cc47a31bee8-c3a0ebd1d22c3183&q=1&u=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbrcm%2Cbcm2711-hdmi.yaml%23
> > +$schema: https://protect2.fireeye.com/url?k=24fa660c-792870a9-24fbed43-0cc47a31bee8-0bf16f4fd60f0ab4&q=1&u=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23
> > +
> > +title: Broadcom BCM2711 HDMI Controller Device Tree Bindings
> > +
> > +maintainers:
> > +  - Eric Anholt <eric@anholt.net>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - brcm,bcm2711-hdmi0
> > +      - brcm,bcm2711-hdmi1
> > +
> > +  reg:
> > +    items:
> > +      - description: HDMI controller register range
> > +      - description: DVP register range
> > +      - description: HDMI PHY register range
> > +      - description: Rate Manager register range
> > +      - description: Packet RAM register range
> > +      - description: Metadata RAM register range
> > +      - description: CSC register range
> > +      - description: CEC register range
> > +      - description: HD register range
> > +
> > +  reg-names:
> > +    items:
> > +      - const: hdmi
> > +      - const: dvp
> > +      - const: phy
> > +      - const: rm
> > +      - const: packet
> > +      - const: metadata
> > +      - const: csc
> > +      - const: cec
> > +      - const: hd
> > +
> > +  clocks:
> > +    description: The HDMI state machine clock
> 
> I'm not sure the following description is correct.
> But, this description doesn't contain the information of audio clock.
> 
> 	description: The HDMI state machine and audio clock
> 
> > +
> > +  clock-names:
> > +    const: hdmi
> 
> This patch is missing the following clock information for audio clock.
> 
> 	const: clk-108M
> 
> > +
> > +  ddc:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: >
> > +      Phandle of the I2C controller used for DDC EDID probing
> > +
> > +  hpd-gpios:
> > +    description: >
> > +      The GPIO pin for the HDMI hotplug detect (if it doesn't appear
> > +      as an interrupt/status bit in the HDMI controller itself)
> > +
> > +  dmas:
> > +    maxItems: 1
> > +    description: >
> > +      Should contain one entry pointing to the DMA channel used to
> > +      transfer audio data.
> > +
> > +  dma-names:
> > +    const: audio-rx
> > +
> > +  resets:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - reg-names
> > +  - clocks
> > +  - resets
> > +  - ddc
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    hdmi0: hdmi@7ef00700 {
> > +        compatible = "brcm,bcm2711-hdmi0";
> > +        reg = <0x7ef00700 0x300>,
> > +              <0x7ef00300 0x200>,
> > +              <0x7ef00f00 0x80>,
> > +              <0x7ef00f80 0x80>,
> > +              <0x7ef01b00 0x200>,
> > +              <0x7ef01f00 0x400>,
> > +              <0x7ef00200 0x80>,
> > +              <0x7ef04300 0x100>,
> > +              <0x7ef20000 0x100>;
> > +        reg-names = "hdmi",
> > +                    "dvp",
> > +                    "phy",
> > +                    "rm",
> > +                    "packet",
> > +                    "metadata",
> > +                    "csc",
> > +                    "cec",
> > +                    "hd";
> > +        clocks = <&firmware_clocks 13>;
> > +        clock-names = "hdmi";
> 
> Also, this example doesn't include the instance of audio clock.
> Need to edit them as following:
> 
> 	clock-names = "hdmi", "clk-108M";
> 	clocks = <&firmware_clocks 13>, <&dvp 0>;

Indeed, thanks for pointing it out

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-08-25 21:30               ` Stefan Wahren
  (?)
@ 2020-09-01  9:58                 ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:58 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel

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

Hi Stefan

On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> > Hi Stefan,
> >
> > On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> >> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> >>> Hi,
> >>>
> >>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>>>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>>>> let's use that.
> >>>>>
> >>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>>>> ---
> >>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>>>  1 file changed, 2 insertions(+)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> index d0b326e1df0a..7b178d67187f 100644
> >>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>>>
> >>>>> +       mdelay(20);
> >>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >>>> not msleep instead?
> >>> Since the timing was fairly critical, sleeping didn't seem like a good
> >>> solution since there's definitely some chance you overshoot and end up
> >>> with a higher time than the one you targeted.
> >> usleep_range(min, max) isn't a solution?
> > My understanding of usleep_range was that you can still overshoot, even
> > though it's backed by an HR timer so the resolution is not a jiffy. Are
> > we certain that we're going to be in that range?
> 
> you are right there is no guarantee about the upper wake up time.
> 
> And it's not worth the effort to poll the FIFO state until its empty
> (using 20 ms as timeout)?

I know this isn't really a great argument there, but getting this to
work has been quite painful, and the timing is very sensitive. If we
fail to wait for enough time, there's going to be a pixel shift that we
can't get rid of unless we reboot, which is pretty bad (and would fail
any CI test that checks for the output integrity).

I know busy-looping for 20ms isn't ideal, but it's not really in a
hot-path (it's only done when changing a mode), with the sync time of
the display likely to be much more than that, and if it can avoid having
to look into it ever again or avoid random failures, I'd say it's worth
it.

Maxime

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

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-09-01  9:58                 ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:58 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi Stefan

On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> > Hi Stefan,
> >
> > On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> >> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> >>> Hi,
> >>>
> >>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>>>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>>>> let's use that.
> >>>>>
> >>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>>>> ---
> >>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>>>  1 file changed, 2 insertions(+)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> index d0b326e1df0a..7b178d67187f 100644
> >>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>>>
> >>>>> +       mdelay(20);
> >>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >>>> not msleep instead?
> >>> Since the timing was fairly critical, sleeping didn't seem like a good
> >>> solution since there's definitely some chance you overshoot and end up
> >>> with a higher time than the one you targeted.
> >> usleep_range(min, max) isn't a solution?
> > My understanding of usleep_range was that you can still overshoot, even
> > though it's backed by an HR timer so the resolution is not a jiffy. Are
> > we certain that we're going to be in that range?
> 
> you are right there is no guarantee about the upper wake up time.
> 
> And it's not worth the effort to poll the FIFO state until its empty
> (using 20 ms as timeout)?

I know this isn't really a great argument there, but getting this to
work has been quite painful, and the timing is very sensitive. If we
fail to wait for enough time, there's going to be a pixel shift that we
can't get rid of unless we reboot, which is pretty bad (and would fail
any CI test that checks for the output integrity).

I know busy-looping for 20ms isn't ideal, but it's not really in a
hot-path (it's only done when changing a mode), with the sync time of
the display likely to be much more than that, and if it can avoid having
to look into it ever again or avoid random failures, I'd say it's worth
it.

Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-09-01  9:58                 ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01  9:58 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi Stefan

On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> > Hi Stefan,
> >
> > On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> >> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> >>> Hi,
> >>>
> >>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>>>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>>>> let's use that.
> >>>>>
> >>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>>>> ---
> >>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>>>  1 file changed, 2 insertions(+)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> index d0b326e1df0a..7b178d67187f 100644
> >>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>>>
> >>>>> +       mdelay(20);
> >>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >>>> not msleep instead?
> >>> Since the timing was fairly critical, sleeping didn't seem like a good
> >>> solution since there's definitely some chance you overshoot and end up
> >>> with a higher time than the one you targeted.
> >> usleep_range(min, max) isn't a solution?
> > My understanding of usleep_range was that you can still overshoot, even
> > though it's backed by an HR timer so the resolution is not a jiffy. Are
> > we certain that we're going to be in that range?
> 
> you are right there is no guarantee about the upper wake up time.
> 
> And it's not worth the effort to poll the FIFO state until its empty
> (using 20 ms as timeout)?

I know this isn't really a great argument there, but getting this to
work has been quite painful, and the timing is very sensitive. If we
fail to wait for enough time, there's going to be a pixel shift that we
can't get rid of unless we reboot, which is pretty bad (and would fail
any CI test that checks for the output integrity).

I know busy-looping for 20ms isn't ideal, but it's not really in a
hot-path (it's only done when changing a mode), with the sync time of
the display likely to be much more than that, and if it can avoid having
to look into it ever again or avoid random failures, I'd say it's worth
it.

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
  2020-07-28 15:30       ` Dave Stevenson
  (?)
@ 2020-09-01 10:19         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01 10:19 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

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

Hi Dave,

On Tue, Jul 28, 2020 at 04:30:16PM +0100, Dave Stevenson wrote:
> > @@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
> >         struct vc4_load_tracker_state *load_state;
> >         int ret;
> >
> > -       /* Start with the load tracker enabled. Can be disabled through the
> > -        * debugfs load_tracker file.
> > -        */
> > -       vc4->load_tracker_enabled = true;
> > +       if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
> 
> Is it better to look up the compatible string, or pass something via
> the .data element of the of_device_id table? Probably down to personal
> preference?

It's pretty much equivalent, so I'm not sure one is arguably better than
the other. However, checking for the compatible can be pretty cumbersome
when you have to do it repeatedly (like we do in the HDMI controller),
and when you don't it a lot, having a structure associated to the
compatible is also fairly cumbersome.

> > +               vc4->load_tracker_available = true;
> > +
> > +               /* Start with the load tracker enabled. Can be
> > +                * disabled through the debugfs load_tracker file.
> > +                */
> > +               vc4->load_tracker_enabled = true;
> > +       }
> >
> >         sema_init(&vc4->async_modeset, 1);
> >
> > @@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
> >                 return ret;
> >         }
> >
> > -       dev->mode_config.max_width = 2048;
> > -       dev->mode_config.max_height = 2048;
> > +       if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
> 
> We're making the same of_device_is_compatible call twice within
> vc4_kms_load. Set a flag based on it and check that instead?

Good idea, thanks!
Maxime

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

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

* Re: [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
@ 2020-09-01 10:19         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01 10:19 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi Dave,

On Tue, Jul 28, 2020 at 04:30:16PM +0100, Dave Stevenson wrote:
> > @@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
> >         struct vc4_load_tracker_state *load_state;
> >         int ret;
> >
> > -       /* Start with the load tracker enabled. Can be disabled through the
> > -        * debugfs load_tracker file.
> > -        */
> > -       vc4->load_tracker_enabled = true;
> > +       if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
> 
> Is it better to look up the compatible string, or pass something via
> the .data element of the of_device_id table? Probably down to personal
> preference?

It's pretty much equivalent, so I'm not sure one is arguably better than
the other. However, checking for the compatible can be pretty cumbersome
when you have to do it repeatedly (like we do in the HDMI controller),
and when you don't it a lot, having a structure associated to the
compatible is also fairly cumbersome.

> > +               vc4->load_tracker_available = true;
> > +
> > +               /* Start with the load tracker enabled. Can be
> > +                * disabled through the debugfs load_tracker file.
> > +                */
> > +               vc4->load_tracker_enabled = true;
> > +       }
> >
> >         sema_init(&vc4->async_modeset, 1);
> >
> > @@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
> >                 return ret;
> >         }
> >
> > -       dev->mode_config.max_width = 2048;
> > -       dev->mode_config.max_height = 2048;
> > +       if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
> 
> We're making the same of_device_is_compatible call twice within
> vc4_kms_load. Set a flag based on it and check that instead?

Good idea, thanks!
Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 77/78] drm/vc4: drv: Support BCM2711
@ 2020-09-01 10:19         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-01 10:19 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel


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

Hi Dave,

On Tue, Jul 28, 2020 at 04:30:16PM +0100, Dave Stevenson wrote:
> > @@ -681,10 +684,14 @@ int vc4_kms_load(struct drm_device *dev)
> >         struct vc4_load_tracker_state *load_state;
> >         int ret;
> >
> > -       /* Start with the load tracker enabled. Can be disabled through the
> > -        * debugfs load_tracker file.
> > -        */
> > -       vc4->load_tracker_enabled = true;
> > +       if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
> 
> Is it better to look up the compatible string, or pass something via
> the .data element of the of_device_id table? Probably down to personal
> preference?

It's pretty much equivalent, so I'm not sure one is arguably better than
the other. However, checking for the compatible can be pretty cumbersome
when you have to do it repeatedly (like we do in the HDMI controller),
and when you don't it a lot, having a structure associated to the
compatible is also fairly cumbersome.

> > +               vc4->load_tracker_available = true;
> > +
> > +               /* Start with the load tracker enabled. Can be
> > +                * disabled through the debugfs load_tracker file.
> > +                */
> > +               vc4->load_tracker_enabled = true;
> > +       }
> >
> >         sema_init(&vc4->async_modeset, 1);
> >
> > @@ -698,8 +705,14 @@ int vc4_kms_load(struct drm_device *dev)
> >                 return ret;
> >         }
> >
> > -       dev->mode_config.max_width = 2048;
> > -       dev->mode_config.max_height = 2048;
> > +       if (of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) {
> 
> We're making the same of_device_is_compatible call twice within
> vc4_kms_load. Set a flag based on it and check that instead?

Good idea, thanks!
Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
  2020-09-01  9:45         ` Maxime Ripard
  (?)
@ 2020-09-01 10:48           ` Chanwoo Choi
  -1 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 10:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Nicolas Saenz Julienne, Eric Anholt, dri-devel, linux-rpi-kernel,
	bcm-kernel-feedback-list, linux-arm-kernel, linux-kernel,
	Dave Stevenson, Tim Gover, Phil Elwell

Hi Maxime,

On 9/1/20 6:45 PM, Maxime Ripard wrote:
> Hi Chanwoo,
> 
> On Tue, Sep 01, 2020 at 01:36:17PM +0900, Chanwoo Choi wrote:
>> On 7/9/20 2:42 AM, Maxime Ripard wrote:
>>> The HSM clock needs to be setup at around 101% of the pixel rate. This
>>> was done previously by setting the clock rate to 163.7MHz at probe time and
>>> only check in mode_valid whether the mode pixel clock was under the pixel
>>> clock +1% or not.
>>>
>>> However, with 4k we need to change that frequency to a higher frequency
>>> than 163.7MHz, and yet want to have the lowest clock as possible to have a
>>> decent power saving.
>>>
>>> Let's change that logic a bit by setting the clock rate of the HSM clock
>>> to the pixel rate at encoder_enable time. This would work for the
>>> BCM2711 that support 4k resolutions and has a clock that can provide it,
>>> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
>>> that wouldn't be able to use those modes, so let's define the limit in
>>> the variant.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>>>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>>>  2 files changed, 41 insertions(+), 41 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> index 17797b14cde4..9f30fab744f2 100644
>>> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> @@ -53,7 +53,6 @@
>>>  #include "vc4_hdmi_regs.h"
>>>  #include "vc4_regs.h"
>>>  
>>> -#define HSM_CLOCK_FREQ 163682864
>>>  #define CEC_CLOCK_FREQ 40000
>>>  
>>>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>>> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>>>  	HDMI_WRITE(HDMI_VID_CTL,
>>>  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>>>  
>>> +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>>>  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
>>>  
>>>  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
>>> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>>>  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>>>  	bool debug_dump_regs = false;
>>> +	unsigned long pixel_rate, hsm_rate;
>>>  	int ret;
>>>  
>>>  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
>>> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  		return;
>>>  	}
>>>  
>>> -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
>>> -			   mode->clock * 1000 *
>>> -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
>>> +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
>>> +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>>>  	if (ret) {
>>>  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>>>  		return;
>>> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  		return;
>>>  	}
>>>  
>>> +	/*
>>> +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
>>> +	 * be faster than pixel clock, infinitesimally faster, tested in
>>> +	 * simulation. Otherwise, exact value is unimportant for HDMI
>>> +	 * operation." This conflicts with bcm2835's vc4 documentation, which
>>> +	 * states HSM's clock has to be at least 108% of the pixel clock.
>>> +	 *
>>> +	 * Real life tests reveal that vc4's firmware statement holds up, and
>>> +	 * users are able to use pixel clocks closer to HSM's, namely for
>>> +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
>>> +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
>>> +	 * 162MHz.
>>> +	 *
>>> +	 * Additionally, the AXI clock needs to be at least 25% of
>>> +	 * pixel clock, but HSM ends up being the limiting factor.
>>> +	 */
>>> +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
>>> +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
>>> +	if (ret) {
>>> +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
>>> +		return;
>>> +	}
>>> +
>>> +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
>>> +	if (ret) {
>>> +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
>>> +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
>>> +		return;
>>> +	}
>>
>> About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
>> with clk_prepare_enable() and then touch the clock like clk_set_rate().
>> I think that need to enable the clock before calling clk_set_rate().
>>
>> When I tested this patchset, it is well working because I think that
>> vc4_hdmi->hsm_clock was already enabled on other side.
> 
> There's no clear rule here on the ordering (at least enforced by the
> framework). There's clocks that need to be disabled to change their rate
> (CLK_SET_RATE_GATE) and some that need to be enabled to change their
> rate (CLK_SET_RATE_UNGATE).
> 
> Generally speaking, it seems more logical to me to have first the rate
> changed and then the clock enabled since it won't create any "hiccup",
> but I could very well see the opposite to be preferred.

If it doesn't cause the problem on h/w, I agree. Thanks for the explanation.

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-09-01 10:48           ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 10:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

On 9/1/20 6:45 PM, Maxime Ripard wrote:
> Hi Chanwoo,
> 
> On Tue, Sep 01, 2020 at 01:36:17PM +0900, Chanwoo Choi wrote:
>> On 7/9/20 2:42 AM, Maxime Ripard wrote:
>>> The HSM clock needs to be setup at around 101% of the pixel rate. This
>>> was done previously by setting the clock rate to 163.7MHz at probe time and
>>> only check in mode_valid whether the mode pixel clock was under the pixel
>>> clock +1% or not.
>>>
>>> However, with 4k we need to change that frequency to a higher frequency
>>> than 163.7MHz, and yet want to have the lowest clock as possible to have a
>>> decent power saving.
>>>
>>> Let's change that logic a bit by setting the clock rate of the HSM clock
>>> to the pixel rate at encoder_enable time. This would work for the
>>> BCM2711 that support 4k resolutions and has a clock that can provide it,
>>> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
>>> that wouldn't be able to use those modes, so let's define the limit in
>>> the variant.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>>>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>>>  2 files changed, 41 insertions(+), 41 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> index 17797b14cde4..9f30fab744f2 100644
>>> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> @@ -53,7 +53,6 @@
>>>  #include "vc4_hdmi_regs.h"
>>>  #include "vc4_regs.h"
>>>  
>>> -#define HSM_CLOCK_FREQ 163682864
>>>  #define CEC_CLOCK_FREQ 40000
>>>  
>>>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>>> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>>>  	HDMI_WRITE(HDMI_VID_CTL,
>>>  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>>>  
>>> +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>>>  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
>>>  
>>>  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
>>> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>>>  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>>>  	bool debug_dump_regs = false;
>>> +	unsigned long pixel_rate, hsm_rate;
>>>  	int ret;
>>>  
>>>  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
>>> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  		return;
>>>  	}
>>>  
>>> -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
>>> -			   mode->clock * 1000 *
>>> -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
>>> +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
>>> +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>>>  	if (ret) {
>>>  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>>>  		return;
>>> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  		return;
>>>  	}
>>>  
>>> +	/*
>>> +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
>>> +	 * be faster than pixel clock, infinitesimally faster, tested in
>>> +	 * simulation. Otherwise, exact value is unimportant for HDMI
>>> +	 * operation." This conflicts with bcm2835's vc4 documentation, which
>>> +	 * states HSM's clock has to be at least 108% of the pixel clock.
>>> +	 *
>>> +	 * Real life tests reveal that vc4's firmware statement holds up, and
>>> +	 * users are able to use pixel clocks closer to HSM's, namely for
>>> +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
>>> +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
>>> +	 * 162MHz.
>>> +	 *
>>> +	 * Additionally, the AXI clock needs to be at least 25% of
>>> +	 * pixel clock, but HSM ends up being the limiting factor.
>>> +	 */
>>> +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
>>> +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
>>> +	if (ret) {
>>> +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
>>> +		return;
>>> +	}
>>> +
>>> +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
>>> +	if (ret) {
>>> +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
>>> +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
>>> +		return;
>>> +	}
>>
>> About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
>> with clk_prepare_enable() and then touch the clock like clk_set_rate().
>> I think that need to enable the clock before calling clk_set_rate().
>>
>> When I tested this patchset, it is well working because I think that
>> vc4_hdmi->hsm_clock was already enabled on other side.
> 
> There's no clear rule here on the ordering (at least enforced by the
> framework). There's clocks that need to be disabled to change their rate
> (CLK_SET_RATE_GATE) and some that need to be enabled to change their
> rate (CLK_SET_RATE_UNGATE).
> 
> Generally speaking, it seems more logical to me to have first the rate
> changed and then the clock enabled since it won't create any "hiccup",
> but I could very well see the opposite to be preferred.

If it doesn't cause the problem on h/w, I agree. Thanks for the explanation.

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate
@ 2020-09-01 10:48           ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 10:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

On 9/1/20 6:45 PM, Maxime Ripard wrote:
> Hi Chanwoo,
> 
> On Tue, Sep 01, 2020 at 01:36:17PM +0900, Chanwoo Choi wrote:
>> On 7/9/20 2:42 AM, Maxime Ripard wrote:
>>> The HSM clock needs to be setup at around 101% of the pixel rate. This
>>> was done previously by setting the clock rate to 163.7MHz at probe time and
>>> only check in mode_valid whether the mode pixel clock was under the pixel
>>> clock +1% or not.
>>>
>>> However, with 4k we need to change that frequency to a higher frequency
>>> than 163.7MHz, and yet want to have the lowest clock as possible to have a
>>> decent power saving.
>>>
>>> Let's change that logic a bit by setting the clock rate of the HSM clock
>>> to the pixel rate at encoder_enable time. This would work for the
>>> BCM2711 that support 4k resolutions and has a clock that can provide it,
>>> but we still have to take care of a 4k panel plugged on a BCM283x SoCs
>>> that wouldn't be able to use those modes, so let's define the limit in
>>> the variant.
>>>
>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>> ---
>>>  drivers/gpu/drm/vc4/vc4_hdmi.c | 79 ++++++++++++++++-------------------
>>>  drivers/gpu/drm/vc4/vc4_hdmi.h |  3 +-
>>>  2 files changed, 41 insertions(+), 41 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> index 17797b14cde4..9f30fab744f2 100644
>>> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>> @@ -53,7 +53,6 @@
>>>  #include "vc4_hdmi_regs.h"
>>>  #include "vc4_regs.h"
>>>  
>>> -#define HSM_CLOCK_FREQ 163682864
>>>  #define CEC_CLOCK_FREQ 40000
>>>  
>>>  static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
>>> @@ -326,6 +325,7 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder)
>>>  	HDMI_WRITE(HDMI_VID_CTL,
>>>  		   HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE);
>>>  
>>> +	clk_disable_unprepare(vc4_hdmi->hsm_clock);
>>>  	clk_disable_unprepare(vc4_hdmi->pixel_clock);
>>>  
>>>  	ret = pm_runtime_put(&vc4_hdmi->pdev->dev);
>>> @@ -423,6 +423,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  	struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
>>>  	struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder);
>>>  	bool debug_dump_regs = false;
>>> +	unsigned long pixel_rate, hsm_rate;
>>>  	int ret;
>>>  
>>>  	ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev);
>>> @@ -431,9 +432,8 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  		return;
>>>  	}
>>>  
>>> -	ret = clk_set_rate(vc4_hdmi->pixel_clock,
>>> -			   mode->clock * 1000 *
>>> -			   ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1));
>>> +	pixel_rate = mode->clock * 1000 * ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1);
>>> +	ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate);
>>>  	if (ret) {
>>>  		DRM_ERROR("Failed to set pixel clock rate: %d\n", ret);
>>>  		return;
>>> @@ -445,6 +445,36 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder)
>>>  		return;
>>>  	}
>>>  
>>> +	/*
>>> +	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
>>> +	 * be faster than pixel clock, infinitesimally faster, tested in
>>> +	 * simulation. Otherwise, exact value is unimportant for HDMI
>>> +	 * operation." This conflicts with bcm2835's vc4 documentation, which
>>> +	 * states HSM's clock has to be at least 108% of the pixel clock.
>>> +	 *
>>> +	 * Real life tests reveal that vc4's firmware statement holds up, and
>>> +	 * users are able to use pixel clocks closer to HSM's, namely for
>>> +	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
>>> +	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
>>> +	 * 162MHz.
>>> +	 *
>>> +	 * Additionally, the AXI clock needs to be at least 25% of
>>> +	 * pixel clock, but HSM ends up being the limiting factor.
>>> +	 */
>>> +	hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101);
>>> +	ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate);
>>> +	if (ret) {
>>> +		DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
>>> +		return;
>>> +	}
>>> +
>>> +	ret = clk_prepare_enable(vc4_hdmi->hsm_clock);
>>> +	if (ret) {
>>> +		DRM_ERROR("Failed to turn on HSM clock: %d\n", ret);
>>> +		clk_disable_unprepare(vc4_hdmi->pixel_clock);
>>> +		return;
>>> +	}
>>
>> About vc4_hdmi->hsm_clock instance, usually, we need to enable the clock
>> with clk_prepare_enable() and then touch the clock like clk_set_rate().
>> I think that need to enable the clock before calling clk_set_rate().
>>
>> When I tested this patchset, it is well working because I think that
>> vc4_hdmi->hsm_clock was already enabled on other side.
> 
> There's no clear rule here on the ordering (at least enforced by the
> framework). There's clocks that need to be disabled to change their rate
> (CLK_SET_RATE_GATE) and some that need to be enabled to change their
> rate (CLK_SET_RATE_UNGATE).
> 
> Generally speaking, it seems more logical to me to have first the rate
> changed and then the clock enabled since it won't create any "hiccup",
> but I could very well see the opposite to be preferred.

If it doesn't cause the problem on h/w, I agree. Thanks for the explanation.

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
  2020-07-08 17:41     ` Maxime Ripard
  (?)
@ 2020-09-01 11:21       ` Chanwoo Choi
  -1 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 11:21 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell

Hi Maxime,

On 7/9/20 2:41 AM, Maxime Ripard wrote:
> In order to prevent timeouts and stalls in the pipeline, the core clock
> needs to be maxed at 500MHz during a modeset on the BCM2711.
> 
> Reviewed-by: Eric Anholt <eric@anholt.net>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
>  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
>  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
>  3 files changed, 20 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index e4cde1f9224b..6358f6ca8d56 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -320,6 +320,8 @@ struct vc4_hvs {
>  	void __iomem *regs;
>  	u32 __iomem *dlist;
>  
> +	struct clk *core_clk;
> +
>  	/* Memory manager for CRTCs to allocate space in the display
>  	 * list.  Units are dwords.
>  	 */
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 836d8799d79e..091fdf4908aa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -19,6 +19,7 @@
>   * each CRTC.
>   */
>  
> +#include <linux/clk.h>
>  #include <linux/component.h>
>  #include <linux/platform_device.h>
>  
> @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>  	hvs->regset.regs = hvs_regs;
>  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>  
> +	if (hvs->hvs5) {
> +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> +		if (IS_ERR(hvs->core_clk)) {
> +			dev_err(&pdev->dev, "Couldn't get core clock\n");
> +			return PTR_ERR(hvs->core_clk);
> +		}
> +	}
> +
>  	if (!hvs->hvs5)
>  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
>  	else
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 08318e69061b..210cc2408087 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -11,6 +11,8 @@
>   * crtc, HDMI encoder).
>   */
>  
> +#include <linux/clk.h>
> +
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  {
>  	struct drm_device *dev = state->dev;
>  	struct vc4_dev *vc4 = to_vc4_dev(dev);
> +	struct vc4_hvs *hvs = vc4->hvs;
>  	struct vc4_crtc *vc4_crtc;
>  	int i;
>  
> @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>  	}
>  
> +	if (vc4->hvs->hvs5)
> +		clk_set_min_rate(hvs->core_clk, 500000000);
> +
>  	drm_atomic_helper_wait_for_fences(dev, state, false);
>  
>  	drm_atomic_helper_wait_for_dependencies(state);
> @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  
>  	drm_atomic_helper_commit_cleanup_done(state);
>  
> +	if (vc4->hvs->hvs5)
> +		clk_set_min_rate(hvs->core_clk, 0);
> +
>  	drm_atomic_state_put(state);
>  
>  	up(&vc4->async_modeset);
> 

This patch doesn't control the enable/disable of core_clk.
So, I think that it need to handle the clock as following:

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 4ef88c0b51ab..355d67fd8beb 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
                        dev_err(&pdev->dev, "Couldn't get core clock\n");
                        return PTR_ERR(hvs->core_clk);
                }
+
+               ret = clk_prepare_enable(hvs->core_clk);
+               if (ret) {
+                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
+                       return ret;
+               }
        }
 
        if (!hvs->hvs5)
@@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
        drm_mm_takedown(&vc4->hvs->dlist_mm);
        drm_mm_takedown(&vc4->hvs->lbm_mm);
 
+       clk_prepare_enable(vc4->hvs->core_clk);
+
        vc4->hvs = NULL;
 }



-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-09-01 11:21       ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 11:21 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

Hi Maxime,

On 7/9/20 2:41 AM, Maxime Ripard wrote:
> In order to prevent timeouts and stalls in the pipeline, the core clock
> needs to be maxed at 500MHz during a modeset on the BCM2711.
> 
> Reviewed-by: Eric Anholt <eric@anholt.net>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
>  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
>  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
>  3 files changed, 20 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index e4cde1f9224b..6358f6ca8d56 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -320,6 +320,8 @@ struct vc4_hvs {
>  	void __iomem *regs;
>  	u32 __iomem *dlist;
>  
> +	struct clk *core_clk;
> +
>  	/* Memory manager for CRTCs to allocate space in the display
>  	 * list.  Units are dwords.
>  	 */
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 836d8799d79e..091fdf4908aa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -19,6 +19,7 @@
>   * each CRTC.
>   */
>  
> +#include <linux/clk.h>
>  #include <linux/component.h>
>  #include <linux/platform_device.h>
>  
> @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>  	hvs->regset.regs = hvs_regs;
>  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>  
> +	if (hvs->hvs5) {
> +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> +		if (IS_ERR(hvs->core_clk)) {
> +			dev_err(&pdev->dev, "Couldn't get core clock\n");
> +			return PTR_ERR(hvs->core_clk);
> +		}
> +	}
> +
>  	if (!hvs->hvs5)
>  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
>  	else
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 08318e69061b..210cc2408087 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -11,6 +11,8 @@
>   * crtc, HDMI encoder).
>   */
>  
> +#include <linux/clk.h>
> +
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  {
>  	struct drm_device *dev = state->dev;
>  	struct vc4_dev *vc4 = to_vc4_dev(dev);
> +	struct vc4_hvs *hvs = vc4->hvs;
>  	struct vc4_crtc *vc4_crtc;
>  	int i;
>  
> @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>  	}
>  
> +	if (vc4->hvs->hvs5)
> +		clk_set_min_rate(hvs->core_clk, 500000000);
> +
>  	drm_atomic_helper_wait_for_fences(dev, state, false);
>  
>  	drm_atomic_helper_wait_for_dependencies(state);
> @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  
>  	drm_atomic_helper_commit_cleanup_done(state);
>  
> +	if (vc4->hvs->hvs5)
> +		clk_set_min_rate(hvs->core_clk, 0);
> +
>  	drm_atomic_state_put(state);
>  
>  	up(&vc4->async_modeset);
> 

This patch doesn't control the enable/disable of core_clk.
So, I think that it need to handle the clock as following:

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 4ef88c0b51ab..355d67fd8beb 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
                        dev_err(&pdev->dev, "Couldn't get core clock\n");
                        return PTR_ERR(hvs->core_clk);
                }
+
+               ret = clk_prepare_enable(hvs->core_clk);
+               if (ret) {
+                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
+                       return ret;
+               }
        }
 
        if (!hvs->hvs5)
@@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
        drm_mm_takedown(&vc4->hvs->dlist_mm);
        drm_mm_takedown(&vc4->hvs->lbm_mm);
 
+       clk_prepare_enable(vc4->hvs->core_clk);
+
        vc4->hvs = NULL;
 }



-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-09-01 11:21       ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 11:21 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

Hi Maxime,

On 7/9/20 2:41 AM, Maxime Ripard wrote:
> In order to prevent timeouts and stalls in the pipeline, the core clock
> needs to be maxed at 500MHz during a modeset on the BCM2711.
> 
> Reviewed-by: Eric Anholt <eric@anholt.net>
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
>  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
>  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
>  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
>  3 files changed, 20 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index e4cde1f9224b..6358f6ca8d56 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -320,6 +320,8 @@ struct vc4_hvs {
>  	void __iomem *regs;
>  	u32 __iomem *dlist;
>  
> +	struct clk *core_clk;
> +
>  	/* Memory manager for CRTCs to allocate space in the display
>  	 * list.  Units are dwords.
>  	 */
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 836d8799d79e..091fdf4908aa 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -19,6 +19,7 @@
>   * each CRTC.
>   */
>  
> +#include <linux/clk.h>
>  #include <linux/component.h>
>  #include <linux/platform_device.h>
>  
> @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>  	hvs->regset.regs = hvs_regs;
>  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>  
> +	if (hvs->hvs5) {
> +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> +		if (IS_ERR(hvs->core_clk)) {
> +			dev_err(&pdev->dev, "Couldn't get core clock\n");
> +			return PTR_ERR(hvs->core_clk);
> +		}
> +	}
> +
>  	if (!hvs->hvs5)
>  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
>  	else
> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 08318e69061b..210cc2408087 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -11,6 +11,8 @@
>   * crtc, HDMI encoder).
>   */
>  
> +#include <linux/clk.h>
> +
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
>  #include <drm/drm_crtc.h>
> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  {
>  	struct drm_device *dev = state->dev;
>  	struct vc4_dev *vc4 = to_vc4_dev(dev);
> +	struct vc4_hvs *hvs = vc4->hvs;
>  	struct vc4_crtc *vc4_crtc;
>  	int i;
>  
> @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>  	}
>  
> +	if (vc4->hvs->hvs5)
> +		clk_set_min_rate(hvs->core_clk, 500000000);
> +
>  	drm_atomic_helper_wait_for_fences(dev, state, false);
>  
>  	drm_atomic_helper_wait_for_dependencies(state);
> @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>  
>  	drm_atomic_helper_commit_cleanup_done(state);
>  
> +	if (vc4->hvs->hvs5)
> +		clk_set_min_rate(hvs->core_clk, 0);
> +
>  	drm_atomic_state_put(state);
>  
>  	up(&vc4->async_modeset);
> 

This patch doesn't control the enable/disable of core_clk.
So, I think that it need to handle the clock as following:

diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 4ef88c0b51ab..355d67fd8beb 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
                        dev_err(&pdev->dev, "Couldn't get core clock\n");
                        return PTR_ERR(hvs->core_clk);
                }
+
+               ret = clk_prepare_enable(hvs->core_clk);
+               if (ret) {
+                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
+                       return ret;
+               }
        }
 
        if (!hvs->hvs5)
@@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
        drm_mm_takedown(&vc4->hvs->dlist_mm);
        drm_mm_takedown(&vc4->hvs->lbm_mm);
 
+       clk_prepare_enable(vc4->hvs->core_clk);
+
        vc4->hvs = NULL;
 }



-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
  2020-09-01 11:21       ` Chanwoo Choi
  (?)
@ 2020-09-01 11:48         ` Chanwoo Choi
  -1 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 11:48 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: dri-devel, linux-rpi-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel, linux-kernel, Dave Stevenson, Tim Gover,
	Phil Elwell

On 9/1/20 8:21 PM, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:41 AM, Maxime Ripard wrote:
>> In order to prevent timeouts and stalls in the pipeline, the core clock
>> needs to be maxed at 500MHz during a modeset on the BCM2711.
>>
>> Reviewed-by: Eric Anholt <eric@anholt.net>
>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>> ---
>>  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
>>  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
>>  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
>>  3 files changed, 20 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
>> index e4cde1f9224b..6358f6ca8d56 100644
>> --- a/drivers/gpu/drm/vc4/vc4_drv.h
>> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
>> @@ -320,6 +320,8 @@ struct vc4_hvs {
>>  	void __iomem *regs;
>>  	u32 __iomem *dlist;
>>  
>> +	struct clk *core_clk;
>> +
>>  	/* Memory manager for CRTCs to allocate space in the display
>>  	 * list.  Units are dwords.
>>  	 */
>> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
>> index 836d8799d79e..091fdf4908aa 100644
>> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
>> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
>> @@ -19,6 +19,7 @@
>>   * each CRTC.
>>   */
>>  
>> +#include <linux/clk.h>
>>  #include <linux/component.h>
>>  #include <linux/platform_device.h>
>>  
>> @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>>  	hvs->regset.regs = hvs_regs;
>>  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>>  
>> +	if (hvs->hvs5) {
>> +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
>> +		if (IS_ERR(hvs->core_clk)) {
>> +			dev_err(&pdev->dev, "Couldn't get core clock\n");
>> +			return PTR_ERR(hvs->core_clk);
>> +		}
>> +	}
>> +
>>  	if (!hvs->hvs5)
>>  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
>>  	else
>> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
>> index 08318e69061b..210cc2408087 100644
>> --- a/drivers/gpu/drm/vc4/vc4_kms.c
>> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
>> @@ -11,6 +11,8 @@
>>   * crtc, HDMI encoder).
>>   */
>>  
>> +#include <linux/clk.h>
>> +
>>  #include <drm/drm_atomic.h>
>>  #include <drm/drm_atomic_helper.h>
>>  #include <drm/drm_crtc.h>
>> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  {
>>  	struct drm_device *dev = state->dev;
>>  	struct vc4_dev *vc4 = to_vc4_dev(dev);
>> +	struct vc4_hvs *hvs = vc4->hvs;
>>  	struct vc4_crtc *vc4_crtc;
>>  	int i;
>>  
>> @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>>  	}
>>  
>> +	if (vc4->hvs->hvs5)
>> +		clk_set_min_rate(hvs->core_clk, 500000000);
>> +
>>  	drm_atomic_helper_wait_for_fences(dev, state, false);
>>  
>>  	drm_atomic_helper_wait_for_dependencies(state);
>> @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  
>>  	drm_atomic_helper_commit_cleanup_done(state);
>>  
>> +	if (vc4->hvs->hvs5)
>> +		clk_set_min_rate(hvs->core_clk, 0);
>> +
>>  	drm_atomic_state_put(state);
>>  
>>  	up(&vc4->async_modeset);
>>
> 
> This patch doesn't control the enable/disable of core_clk.
> So, I think that it need to handle the clock as following:
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ef88c0b51ab..355d67fd8beb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>                         dev_err(&pdev->dev, "Couldn't get core clock\n");
>                         return PTR_ERR(hvs->core_clk);
>                 }
> +
> +               ret = clk_prepare_enable(hvs->core_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
> +                       return ret;
> +               }
>         }
>  
>         if (!hvs->hvs5)
> @@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
>         drm_mm_takedown(&vc4->hvs->dlist_mm);
>         drm_mm_takedown(&vc4->hvs->lbm_mm);
>  
> +       clk_prepare_enable(vc4->hvs->core_clk);

I'm sorry. Change to clk_disable_unprepare(vc4->hvs->core_clk);

> +
>         vc4->hvs = NULL;
>  }
> 
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-09-01 11:48         ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 11:48 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

On 9/1/20 8:21 PM, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:41 AM, Maxime Ripard wrote:
>> In order to prevent timeouts and stalls in the pipeline, the core clock
>> needs to be maxed at 500MHz during a modeset on the BCM2711.
>>
>> Reviewed-by: Eric Anholt <eric@anholt.net>
>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>> ---
>>  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
>>  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
>>  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
>>  3 files changed, 20 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
>> index e4cde1f9224b..6358f6ca8d56 100644
>> --- a/drivers/gpu/drm/vc4/vc4_drv.h
>> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
>> @@ -320,6 +320,8 @@ struct vc4_hvs {
>>  	void __iomem *regs;
>>  	u32 __iomem *dlist;
>>  
>> +	struct clk *core_clk;
>> +
>>  	/* Memory manager for CRTCs to allocate space in the display
>>  	 * list.  Units are dwords.
>>  	 */
>> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
>> index 836d8799d79e..091fdf4908aa 100644
>> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
>> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
>> @@ -19,6 +19,7 @@
>>   * each CRTC.
>>   */
>>  
>> +#include <linux/clk.h>
>>  #include <linux/component.h>
>>  #include <linux/platform_device.h>
>>  
>> @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>>  	hvs->regset.regs = hvs_regs;
>>  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>>  
>> +	if (hvs->hvs5) {
>> +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
>> +		if (IS_ERR(hvs->core_clk)) {
>> +			dev_err(&pdev->dev, "Couldn't get core clock\n");
>> +			return PTR_ERR(hvs->core_clk);
>> +		}
>> +	}
>> +
>>  	if (!hvs->hvs5)
>>  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
>>  	else
>> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
>> index 08318e69061b..210cc2408087 100644
>> --- a/drivers/gpu/drm/vc4/vc4_kms.c
>> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
>> @@ -11,6 +11,8 @@
>>   * crtc, HDMI encoder).
>>   */
>>  
>> +#include <linux/clk.h>
>> +
>>  #include <drm/drm_atomic.h>
>>  #include <drm/drm_atomic_helper.h>
>>  #include <drm/drm_crtc.h>
>> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  {
>>  	struct drm_device *dev = state->dev;
>>  	struct vc4_dev *vc4 = to_vc4_dev(dev);
>> +	struct vc4_hvs *hvs = vc4->hvs;
>>  	struct vc4_crtc *vc4_crtc;
>>  	int i;
>>  
>> @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>>  	}
>>  
>> +	if (vc4->hvs->hvs5)
>> +		clk_set_min_rate(hvs->core_clk, 500000000);
>> +
>>  	drm_atomic_helper_wait_for_fences(dev, state, false);
>>  
>>  	drm_atomic_helper_wait_for_dependencies(state);
>> @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  
>>  	drm_atomic_helper_commit_cleanup_done(state);
>>  
>> +	if (vc4->hvs->hvs5)
>> +		clk_set_min_rate(hvs->core_clk, 0);
>> +
>>  	drm_atomic_state_put(state);
>>  
>>  	up(&vc4->async_modeset);
>>
> 
> This patch doesn't control the enable/disable of core_clk.
> So, I think that it need to handle the clock as following:
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ef88c0b51ab..355d67fd8beb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>                         dev_err(&pdev->dev, "Couldn't get core clock\n");
>                         return PTR_ERR(hvs->core_clk);
>                 }
> +
> +               ret = clk_prepare_enable(hvs->core_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
> +                       return ret;
> +               }
>         }
>  
>         if (!hvs->hvs5)
> @@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
>         drm_mm_takedown(&vc4->hvs->dlist_mm);
>         drm_mm_takedown(&vc4->hvs->lbm_mm);
>  
> +       clk_prepare_enable(vc4->hvs->core_clk);

I'm sorry. Change to clk_disable_unprepare(vc4->hvs->core_clk);

> +
>         vc4->hvs = NULL;
>  }
> 
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-09-01 11:48         ` Chanwoo Choi
  0 siblings, 0 replies; 432+ messages in thread
From: Chanwoo Choi @ 2020-09-01 11:48 UTC (permalink / raw)
  To: Maxime Ripard, Nicolas Saenz Julienne, Eric Anholt
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

On 9/1/20 8:21 PM, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:41 AM, Maxime Ripard wrote:
>> In order to prevent timeouts and stalls in the pipeline, the core clock
>> needs to be maxed at 500MHz during a modeset on the BCM2711.
>>
>> Reviewed-by: Eric Anholt <eric@anholt.net>
>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>> ---
>>  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
>>  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
>>  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
>>  3 files changed, 20 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
>> index e4cde1f9224b..6358f6ca8d56 100644
>> --- a/drivers/gpu/drm/vc4/vc4_drv.h
>> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
>> @@ -320,6 +320,8 @@ struct vc4_hvs {
>>  	void __iomem *regs;
>>  	u32 __iomem *dlist;
>>  
>> +	struct clk *core_clk;
>> +
>>  	/* Memory manager for CRTCs to allocate space in the display
>>  	 * list.  Units are dwords.
>>  	 */
>> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
>> index 836d8799d79e..091fdf4908aa 100644
>> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
>> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
>> @@ -19,6 +19,7 @@
>>   * each CRTC.
>>   */
>>  
>> +#include <linux/clk.h>
>>  #include <linux/component.h>
>>  #include <linux/platform_device.h>
>>  
>> @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>>  	hvs->regset.regs = hvs_regs;
>>  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
>>  
>> +	if (hvs->hvs5) {
>> +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
>> +		if (IS_ERR(hvs->core_clk)) {
>> +			dev_err(&pdev->dev, "Couldn't get core clock\n");
>> +			return PTR_ERR(hvs->core_clk);
>> +		}
>> +	}
>> +
>>  	if (!hvs->hvs5)
>>  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
>>  	else
>> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
>> index 08318e69061b..210cc2408087 100644
>> --- a/drivers/gpu/drm/vc4/vc4_kms.c
>> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
>> @@ -11,6 +11,8 @@
>>   * crtc, HDMI encoder).
>>   */
>>  
>> +#include <linux/clk.h>
>> +
>>  #include <drm/drm_atomic.h>
>>  #include <drm/drm_atomic_helper.h>
>>  #include <drm/drm_crtc.h>
>> @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  {
>>  	struct drm_device *dev = state->dev;
>>  	struct vc4_dev *vc4 = to_vc4_dev(dev);
>> +	struct vc4_hvs *hvs = vc4->hvs;
>>  	struct vc4_crtc *vc4_crtc;
>>  	int i;
>>  
>> @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
>>  	}
>>  
>> +	if (vc4->hvs->hvs5)
>> +		clk_set_min_rate(hvs->core_clk, 500000000);
>> +
>>  	drm_atomic_helper_wait_for_fences(dev, state, false);
>>  
>>  	drm_atomic_helper_wait_for_dependencies(state);
>> @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
>>  
>>  	drm_atomic_helper_commit_cleanup_done(state);
>>  
>> +	if (vc4->hvs->hvs5)
>> +		clk_set_min_rate(hvs->core_clk, 0);
>> +
>>  	drm_atomic_state_put(state);
>>  
>>  	up(&vc4->async_modeset);
>>
> 
> This patch doesn't control the enable/disable of core_clk.
> So, I think that it need to handle the clock as following:
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ef88c0b51ab..355d67fd8beb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>                         dev_err(&pdev->dev, "Couldn't get core clock\n");
>                         return PTR_ERR(hvs->core_clk);
>                 }
> +
> +               ret = clk_prepare_enable(hvs->core_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
> +                       return ret;
> +               }
>         }
>  
>         if (!hvs->hvs5)
> @@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
>         drm_mm_takedown(&vc4->hvs->dlist_mm);
>         drm_mm_takedown(&vc4->hvs->lbm_mm);
>  
> +       clk_prepare_enable(vc4->hvs->core_clk);

I'm sorry. Change to clk_disable_unprepare(vc4->hvs->core_clk);

> +
>         vc4->hvs = NULL;
>  }
> 
> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-09-01  9:58                 ` Maxime Ripard
  (?)
@ 2020-09-01 16:31                   ` Stefan Wahren
  -1 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-09-01 16:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel

Hi Maxime,

Am 01.09.20 um 11:58 schrieb Maxime Ripard:
> Hi Stefan
>
> On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
>> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
>>> Hi Stefan,
>>>
>>> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>>>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>>>> Hi,
>>>>>
>>>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>>>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>>>>>> let's use that.
>>>>>>>
>>>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>>>> ---
>>>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>>>>>  1 file changed, 2 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> index d0b326e1df0a..7b178d67187f 100644
>>>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>>>>>
>>>>>>> +       mdelay(20);
>>>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>>>>>> not msleep instead?
>>>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>>>> solution since there's definitely some chance you overshoot and end up
>>>>> with a higher time than the one you targeted.
>>>> usleep_range(min, max) isn't a solution?
>>> My understanding of usleep_range was that you can still overshoot, even
>>> though it's backed by an HR timer so the resolution is not a jiffy. Are
>>> we certain that we're going to be in that range?
>> you are right there is no guarantee about the upper wake up time.
>>
>> And it's not worth the effort to poll the FIFO state until its empty
>> (using 20 ms as timeout)?
> I know this isn't really a great argument there, but getting this to
> work has been quite painful, and the timing is very sensitive. If we
> fail to wait for enough time, there's going to be a pixel shift that we
> can't get rid of unless we reboot, which is pretty bad (and would fail
> any CI test that checks for the output integrity).
>
> I know busy-looping for 20ms isn't ideal, but it's not really in a
> hot-path (it's only done when changing a mode), with the sync time of
> the display likely to be much more than that, and if it can avoid having
> to look into it ever again or avoid random failures, I'd say it's worth
> it.

i don't want to delay this series.

Could you please add a small comment to the delay to clarify the timing
is very sensitive?

Thanks

>
> Maxime


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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-09-01 16:31                   ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-09-01 16:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

Am 01.09.20 um 11:58 schrieb Maxime Ripard:
> Hi Stefan
>
> On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
>> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
>>> Hi Stefan,
>>>
>>> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>>>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>>>> Hi,
>>>>>
>>>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>>>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>>>>>> let's use that.
>>>>>>>
>>>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>>>> ---
>>>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>>>>>  1 file changed, 2 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> index d0b326e1df0a..7b178d67187f 100644
>>>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>>>>>
>>>>>>> +       mdelay(20);
>>>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>>>>>> not msleep instead?
>>>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>>>> solution since there's definitely some chance you overshoot and end up
>>>>> with a higher time than the one you targeted.
>>>> usleep_range(min, max) isn't a solution?
>>> My understanding of usleep_range was that you can still overshoot, even
>>> though it's backed by an HR timer so the resolution is not a jiffy. Are
>>> we certain that we're going to be in that range?
>> you are right there is no guarantee about the upper wake up time.
>>
>> And it's not worth the effort to poll the FIFO state until its empty
>> (using 20 ms as timeout)?
> I know this isn't really a great argument there, but getting this to
> work has been quite painful, and the timing is very sensitive. If we
> fail to wait for enough time, there's going to be a pixel shift that we
> can't get rid of unless we reboot, which is pretty bad (and would fail
> any CI test that checks for the output integrity).
>
> I know busy-looping for 20ms isn't ideal, but it's not really in a
> hot-path (it's only done when changing a mode), with the sync time of
> the display likely to be much more than that, and if it can avoid having
> to look into it ever again or avoid random failures, I'd say it's worth
> it.

i don't want to delay this series.

Could you please add a small comment to the delay to clarify the timing
is very sensitive?

Thanks

>
> Maxime


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-09-01 16:31                   ` Stefan Wahren
  0 siblings, 0 replies; 432+ messages in thread
From: Stefan Wahren @ 2020-09-01 16:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi Maxime,

Am 01.09.20 um 11:58 schrieb Maxime Ripard:
> Hi Stefan
>
> On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
>> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
>>> Hi Stefan,
>>>
>>> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
>>>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
>>>>> Hi,
>>>>>
>>>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
>>>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
>>>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
>>>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
>>>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
>>>>>>> let's use that.
>>>>>>>
>>>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
>>>>>>> ---
>>>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
>>>>>>>  1 file changed, 2 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> index d0b326e1df0a..7b178d67187f 100644
>>>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
>>>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
>>>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
>>>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
>>>>>>>
>>>>>>> +       mdelay(20);
>>>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
>>>>>> not msleep instead?
>>>>> Since the timing was fairly critical, sleeping didn't seem like a good
>>>>> solution since there's definitely some chance you overshoot and end up
>>>>> with a higher time than the one you targeted.
>>>> usleep_range(min, max) isn't a solution?
>>> My understanding of usleep_range was that you can still overshoot, even
>>> though it's backed by an HR timer so the resolution is not a jiffy. Are
>>> we certain that we're going to be in that range?
>> you are right there is no guarantee about the upper wake up time.
>>
>> And it's not worth the effort to poll the FIFO state until its empty
>> (using 20 ms as timeout)?
> I know this isn't really a great argument there, but getting this to
> work has been quite painful, and the timing is very sensitive. If we
> fail to wait for enough time, there's going to be a pixel shift that we
> can't get rid of unless we reboot, which is pretty bad (and would fail
> any CI test that checks for the output integrity).
>
> I know busy-looping for 20ms isn't ideal, but it's not really in a
> hot-path (it's only done when changing a mode), with the sync time of
> the display likely to be much more than that, and if it can avoid having
> to look into it ever again or avoid random failures, I'd say it's worth
> it.

i don't want to delay this series.

Could you please add a small comment to the delay to clarify the timing
is very sensitive?

Thanks

>
> Maxime

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

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
  2020-08-21  7:18     ` Hoegeun Kwon
  (?)
@ 2020-09-02 13:32       ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 13:32 UTC (permalink / raw)
  To: Hoegeun Kwon
  Cc: Nicolas Saenz Julienne, Eric Anholt, devicetree, Tim Gover,
	Dave Stevenson, Stephen Boyd, Michael Turquette, Kamal Dasu,
	linux-kernel, dri-devel, linux-clk, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

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

Hi Hoegeun

On Fri, Aug 21, 2020 at 04:18:34PM +0900, Hoegeun Kwon wrote:
> Hi Maxime,
> 
> Thank you for your version 4 patch.
> I tested all 78 patches based on the next-20200708.
> 
> 
> Dual HDMI opearation does not work normally.
> flip_done timed out occurs and doesn't work.
> Could you check please it.
> 
> [  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [CRTC:64:crtc-3] flip_done timed out
> [  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [CONNECTOR:32:HDMI-A-1] flip_done timed out
> [  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [PLANE:60:plane-3] flip_done timed out

Thanks for testing and reporting this. I've been looking into it, and it
seems that it's not just the dual output that's broken, but HDMI1
entirely (so even a single display connected to HDMI1 doesn't work).

Is it happening for you as well?

Maxime

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

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-09-02 13:32       ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 13:32 UTC (permalink / raw)
  To: Hoegeun Kwon
  Cc: linux-arm-kernel, devicetree, Tim Gover, Dave Stevenson,
	Stephen Boyd, Michael Turquette, Kamal Dasu, linux-kernel,
	dri-devel, Phil Elwell, Eric Anholt, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, linux-clk,
	Nicolas Saenz Julienne


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

Hi Hoegeun

On Fri, Aug 21, 2020 at 04:18:34PM +0900, Hoegeun Kwon wrote:
> Hi Maxime,
> 
> Thank you for your version 4 patch.
> I tested all 78 patches based on the next-20200708.
> 
> 
> Dual HDMI opearation does not work normally.
> flip_done timed out occurs and doesn't work.
> Could you check please it.
> 
> [  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [CRTC:64:crtc-3] flip_done timed out
> [  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [CONNECTOR:32:HDMI-A-1] flip_done timed out
> [  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [PLANE:60:plane-3] flip_done timed out

Thanks for testing and reporting this. I've been looking into it, and it
seems that it's not just the dual output that's broken, but HDMI1
entirely (so even a single display connected to HDMI1 doesn't work).

Is it happening for you as well?

Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-09-02 13:32       ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 13:32 UTC (permalink / raw)
  To: Hoegeun Kwon
  Cc: linux-arm-kernel, devicetree, Tim Gover, Dave Stevenson,
	Stephen Boyd, Michael Turquette, Kamal Dasu, linux-kernel,
	dri-devel, Phil Elwell, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, linux-clk, Nicolas Saenz Julienne


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

Hi Hoegeun

On Fri, Aug 21, 2020 at 04:18:34PM +0900, Hoegeun Kwon wrote:
> Hi Maxime,
> 
> Thank you for your version 4 patch.
> I tested all 78 patches based on the next-20200708.
> 
> 
> Dual HDMI opearation does not work normally.
> flip_done timed out occurs and doesn't work.
> Could you check please it.
> 
> [  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [CRTC:64:crtc-3] flip_done timed out
> [  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [CONNECTOR:32:HDMI-A-1] flip_done timed out
> [  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> [PLANE:60:plane-3] flip_done timed out

Thanks for testing and reporting this. I've been looking into it, and it
seems that it's not just the dual output that's broken, but HDMI1
entirely (so even a single display connected to HDMI1 doesn't work).

Is it happening for you as well?

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
  2020-09-02 13:32       ` Maxime Ripard
  (?)
@ 2020-09-02 13:52         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 13:52 UTC (permalink / raw)
  To: Hoegeun Kwon
  Cc: Nicolas Saenz Julienne, Eric Anholt, devicetree, Tim Gover,
	Dave Stevenson, Stephen Boyd, Michael Turquette, Kamal Dasu,
	linux-kernel, dri-devel, linux-clk, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, Phil Elwell,
	linux-arm-kernel

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

On Wed, Sep 02, 2020 at 03:32:20PM +0200, Maxime Ripard wrote:
> Hi Hoegeun
> 
> On Fri, Aug 21, 2020 at 04:18:34PM +0900, Hoegeun Kwon wrote:
> > Hi Maxime,
> > 
> > Thank you for your version 4 patch.
> > I tested all 78 patches based on the next-20200708.
> > 
> > 
> > Dual HDMI opearation does not work normally.
> > flip_done timed out occurs and doesn't work.
> > Could you check please it.
> > 
> > [  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [CRTC:64:crtc-3] flip_done timed out
> > [  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [CONNECTOR:32:HDMI-A-1] flip_done timed out
> > [  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [PLANE:60:plane-3] flip_done timed out
> 
> Thanks for testing and reporting this. I've been looking into it, and it
> seems that it's not just the dual output that's broken, but HDMI1
> entirely (so even a single display connected to HDMI1 doesn't work).
> 
> Is it happening for you as well?

Nevermind, I had the DSI panel connected and it was interfering

Maxime


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

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-09-02 13:52         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 13:52 UTC (permalink / raw)
  To: Hoegeun Kwon
  Cc: linux-arm-kernel, devicetree, Tim Gover, Dave Stevenson,
	Stephen Boyd, Michael Turquette, Kamal Dasu, linux-kernel,
	dri-devel, Phil Elwell, Eric Anholt, Rob Herring,
	bcm-kernel-feedback-list, linux-rpi-kernel, linux-clk,
	Nicolas Saenz Julienne


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

On Wed, Sep 02, 2020 at 03:32:20PM +0200, Maxime Ripard wrote:
> Hi Hoegeun
> 
> On Fri, Aug 21, 2020 at 04:18:34PM +0900, Hoegeun Kwon wrote:
> > Hi Maxime,
> > 
> > Thank you for your version 4 patch.
> > I tested all 78 patches based on the next-20200708.
> > 
> > 
> > Dual HDMI opearation does not work normally.
> > flip_done timed out occurs and doesn't work.
> > Could you check please it.
> > 
> > [  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [CRTC:64:crtc-3] flip_done timed out
> > [  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [CONNECTOR:32:HDMI-A-1] flip_done timed out
> > [  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [PLANE:60:plane-3] flip_done timed out
> 
> Thanks for testing and reporting this. I've been looking into it, and it
> seems that it's not just the dual output that's broken, but HDMI1
> entirely (so even a single display connected to HDMI1 doesn't work).
> 
> Is it happening for you as well?

Nevermind, I had the DSI panel connected and it was interfering

Maxime


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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline
@ 2020-09-02 13:52         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 13:52 UTC (permalink / raw)
  To: Hoegeun Kwon
  Cc: linux-arm-kernel, devicetree, Tim Gover, Dave Stevenson,
	Stephen Boyd, Michael Turquette, Kamal Dasu, linux-kernel,
	dri-devel, Phil Elwell, Rob Herring, bcm-kernel-feedback-list,
	linux-rpi-kernel, linux-clk, Nicolas Saenz Julienne


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

On Wed, Sep 02, 2020 at 03:32:20PM +0200, Maxime Ripard wrote:
> Hi Hoegeun
> 
> On Fri, Aug 21, 2020 at 04:18:34PM +0900, Hoegeun Kwon wrote:
> > Hi Maxime,
> > 
> > Thank you for your version 4 patch.
> > I tested all 78 patches based on the next-20200708.
> > 
> > 
> > Dual HDMI opearation does not work normally.
> > flip_done timed out occurs and doesn't work.
> > Could you check please it.
> > 
> > [  105.694541] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [CRTC:64:crtc-3] flip_done timed out
> > [  115.934994] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [CONNECTOR:32:HDMI-A-1] flip_done timed out
> > [  126.174545] [drm:drm_atomic_helper_wait_for_dependencies] *ERROR* 
> > [PLANE:60:plane-3] flip_done timed out
> 
> Thanks for testing and reporting this. I've been looking into it, and it
> seems that it's not just the dual output that's broken, but HDMI1
> entirely (so even a single display connected to HDMI1 doesn't work).
> 
> Is it happening for you as well?

Nevermind, I had the DSI panel connected and it was interfering

Maxime


[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
  2020-09-01 11:21       ` Chanwoo Choi
  (?)
@ 2020-09-02 14:48         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 14:48 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Nicolas Saenz Julienne, Eric Anholt, dri-devel, linux-rpi-kernel,
	bcm-kernel-feedback-list, linux-arm-kernel, linux-kernel,
	Dave Stevenson, Tim Gover, Phil Elwell

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

Hi,

On Tue, Sep 01, 2020 at 08:21:36PM +0900, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:41 AM, Maxime Ripard wrote:
> > In order to prevent timeouts and stalls in the pipeline, the core clock
> > needs to be maxed at 500MHz during a modeset on the BCM2711.
> > 
> > Reviewed-by: Eric Anholt <eric@anholt.net>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
> >  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
> >  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
> >  3 files changed, 20 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index e4cde1f9224b..6358f6ca8d56 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -320,6 +320,8 @@ struct vc4_hvs {
> >  	void __iomem *regs;
> >  	u32 __iomem *dlist;
> >  
> > +	struct clk *core_clk;
> > +
> >  	/* Memory manager for CRTCs to allocate space in the display
> >  	 * list.  Units are dwords.
> >  	 */
> > diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> > index 836d8799d79e..091fdf4908aa 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> > @@ -19,6 +19,7 @@
> >   * each CRTC.
> >   */
> >  
> > +#include <linux/clk.h>
> >  #include <linux/component.h>
> >  #include <linux/platform_device.h>
> >  
> > @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
> >  	hvs->regset.regs = hvs_regs;
> >  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
> >  
> > +	if (hvs->hvs5) {
> > +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> > +		if (IS_ERR(hvs->core_clk)) {
> > +			dev_err(&pdev->dev, "Couldn't get core clock\n");
> > +			return PTR_ERR(hvs->core_clk);
> > +		}
> > +	}
> > +
> >  	if (!hvs->hvs5)
> >  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
> >  	else
> > diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> > index 08318e69061b..210cc2408087 100644
> > --- a/drivers/gpu/drm/vc4/vc4_kms.c
> > +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> > @@ -11,6 +11,8 @@
> >   * crtc, HDMI encoder).
> >   */
> >  
> > +#include <linux/clk.h>
> > +
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_crtc.h>
> > @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  {
> >  	struct drm_device *dev = state->dev;
> >  	struct vc4_dev *vc4 = to_vc4_dev(dev);
> > +	struct vc4_hvs *hvs = vc4->hvs;
> >  	struct vc4_crtc *vc4_crtc;
> >  	int i;
> >  
> > @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
> >  	}
> >  
> > +	if (vc4->hvs->hvs5)
> > +		clk_set_min_rate(hvs->core_clk, 500000000);
> > +
> >  	drm_atomic_helper_wait_for_fences(dev, state, false);
> >  
> >  	drm_atomic_helper_wait_for_dependencies(state);
> > @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  
> >  	drm_atomic_helper_commit_cleanup_done(state);
> >  
> > +	if (vc4->hvs->hvs5)
> > +		clk_set_min_rate(hvs->core_clk, 0);
> > +
> >  	drm_atomic_state_put(state);
> >  
> >  	up(&vc4->async_modeset);
> > 
> 
> This patch doesn't control the enable/disable of core_clk.
> So, I think that it need to handle the clock as following:
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ef88c0b51ab..355d67fd8beb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>                         dev_err(&pdev->dev, "Couldn't get core clock\n");
>                         return PTR_ERR(hvs->core_clk);
>                 }
> +
> +               ret = clk_prepare_enable(hvs->core_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
> +                       return ret;
> +               }
>         }
>  
>         if (!hvs->hvs5)
> @@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
>         drm_mm_takedown(&vc4->hvs->dlist_mm);
>         drm_mm_takedown(&vc4->hvs->lbm_mm);
>  
> +       clk_prepare_enable(vc4->hvs->core_clk);
> +
>         vc4->hvs = NULL;
>  }

Good catch, thanks!
Maxime

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

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-09-02 14:48         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 14:48 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi,

On Tue, Sep 01, 2020 at 08:21:36PM +0900, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:41 AM, Maxime Ripard wrote:
> > In order to prevent timeouts and stalls in the pipeline, the core clock
> > needs to be maxed at 500MHz during a modeset on the BCM2711.
> > 
> > Reviewed-by: Eric Anholt <eric@anholt.net>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
> >  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
> >  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
> >  3 files changed, 20 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index e4cde1f9224b..6358f6ca8d56 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -320,6 +320,8 @@ struct vc4_hvs {
> >  	void __iomem *regs;
> >  	u32 __iomem *dlist;
> >  
> > +	struct clk *core_clk;
> > +
> >  	/* Memory manager for CRTCs to allocate space in the display
> >  	 * list.  Units are dwords.
> >  	 */
> > diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> > index 836d8799d79e..091fdf4908aa 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> > @@ -19,6 +19,7 @@
> >   * each CRTC.
> >   */
> >  
> > +#include <linux/clk.h>
> >  #include <linux/component.h>
> >  #include <linux/platform_device.h>
> >  
> > @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
> >  	hvs->regset.regs = hvs_regs;
> >  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
> >  
> > +	if (hvs->hvs5) {
> > +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> > +		if (IS_ERR(hvs->core_clk)) {
> > +			dev_err(&pdev->dev, "Couldn't get core clock\n");
> > +			return PTR_ERR(hvs->core_clk);
> > +		}
> > +	}
> > +
> >  	if (!hvs->hvs5)
> >  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
> >  	else
> > diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> > index 08318e69061b..210cc2408087 100644
> > --- a/drivers/gpu/drm/vc4/vc4_kms.c
> > +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> > @@ -11,6 +11,8 @@
> >   * crtc, HDMI encoder).
> >   */
> >  
> > +#include <linux/clk.h>
> > +
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_crtc.h>
> > @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  {
> >  	struct drm_device *dev = state->dev;
> >  	struct vc4_dev *vc4 = to_vc4_dev(dev);
> > +	struct vc4_hvs *hvs = vc4->hvs;
> >  	struct vc4_crtc *vc4_crtc;
> >  	int i;
> >  
> > @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
> >  	}
> >  
> > +	if (vc4->hvs->hvs5)
> > +		clk_set_min_rate(hvs->core_clk, 500000000);
> > +
> >  	drm_atomic_helper_wait_for_fences(dev, state, false);
> >  
> >  	drm_atomic_helper_wait_for_dependencies(state);
> > @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  
> >  	drm_atomic_helper_commit_cleanup_done(state);
> >  
> > +	if (vc4->hvs->hvs5)
> > +		clk_set_min_rate(hvs->core_clk, 0);
> > +
> >  	drm_atomic_state_put(state);
> >  
> >  	up(&vc4->async_modeset);
> > 
> 
> This patch doesn't control the enable/disable of core_clk.
> So, I think that it need to handle the clock as following:
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ef88c0b51ab..355d67fd8beb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>                         dev_err(&pdev->dev, "Couldn't get core clock\n");
>                         return PTR_ERR(hvs->core_clk);
>                 }
> +
> +               ret = clk_prepare_enable(hvs->core_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
> +                       return ret;
> +               }
>         }
>  
>         if (!hvs->hvs5)
> @@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
>         drm_mm_takedown(&vc4->hvs->dlist_mm);
>         drm_mm_takedown(&vc4->hvs->lbm_mm);
>  
> +       clk_prepare_enable(vc4->hvs->core_clk);
> +
>         vc4->hvs = NULL;
>  }

Good catch, thanks!
Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset
@ 2020-09-02 14:48         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 14:48 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: Tim Gover, Dave Stevenson, linux-kernel, dri-devel,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

Hi,

On Tue, Sep 01, 2020 at 08:21:36PM +0900, Chanwoo Choi wrote:
> Hi Maxime,
> 
> On 7/9/20 2:41 AM, Maxime Ripard wrote:
> > In order to prevent timeouts and stalls in the pipeline, the core clock
> > needs to be maxed at 500MHz during a modeset on the BCM2711.
> > 
> > Reviewed-by: Eric Anholt <eric@anholt.net>
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
> >  drivers/gpu/drm/vc4/vc4_hvs.c |  9 +++++++++
> >  drivers/gpu/drm/vc4/vc4_kms.c |  9 +++++++++
> >  3 files changed, 20 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index e4cde1f9224b..6358f6ca8d56 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -320,6 +320,8 @@ struct vc4_hvs {
> >  	void __iomem *regs;
> >  	u32 __iomem *dlist;
> >  
> > +	struct clk *core_clk;
> > +
> >  	/* Memory manager for CRTCs to allocate space in the display
> >  	 * list.  Units are dwords.
> >  	 */
> > diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> > index 836d8799d79e..091fdf4908aa 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> > @@ -19,6 +19,7 @@
> >   * each CRTC.
> >   */
> >  
> > +#include <linux/clk.h>
> >  #include <linux/component.h>
> >  #include <linux/platform_device.h>
> >  
> > @@ -540,6 +541,14 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
> >  	hvs->regset.regs = hvs_regs;
> >  	hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
> >  
> > +	if (hvs->hvs5) {
> > +		hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
> > +		if (IS_ERR(hvs->core_clk)) {
> > +			dev_err(&pdev->dev, "Couldn't get core clock\n");
> > +			return PTR_ERR(hvs->core_clk);
> > +		}
> > +	}
> > +
> >  	if (!hvs->hvs5)
> >  		hvs->dlist = hvs->regs + SCALER_DLIST_START;
> >  	else
> > diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> > index 08318e69061b..210cc2408087 100644
> > --- a/drivers/gpu/drm/vc4/vc4_kms.c
> > +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> > @@ -11,6 +11,8 @@
> >   * crtc, HDMI encoder).
> >   */
> >  
> > +#include <linux/clk.h>
> > +
> >  #include <drm/drm_atomic.h>
> >  #include <drm/drm_atomic_helper.h>
> >  #include <drm/drm_crtc.h>
> > @@ -149,6 +151,7 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  {
> >  	struct drm_device *dev = state->dev;
> >  	struct vc4_dev *vc4 = to_vc4_dev(dev);
> > +	struct vc4_hvs *hvs = vc4->hvs;
> >  	struct vc4_crtc *vc4_crtc;
> >  	int i;
> >  
> > @@ -160,6 +163,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  		vc4_hvs_mask_underrun(dev, vc4_crtc->channel);
> >  	}
> >  
> > +	if (vc4->hvs->hvs5)
> > +		clk_set_min_rate(hvs->core_clk, 500000000);
> > +
> >  	drm_atomic_helper_wait_for_fences(dev, state, false);
> >  
> >  	drm_atomic_helper_wait_for_dependencies(state);
> > @@ -182,6 +188,9 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >  
> >  	drm_atomic_helper_commit_cleanup_done(state);
> >  
> > +	if (vc4->hvs->hvs5)
> > +		clk_set_min_rate(hvs->core_clk, 0);
> > +
> >  	drm_atomic_state_put(state);
> >  
> >  	up(&vc4->async_modeset);
> > 
> 
> This patch doesn't control the enable/disable of core_clk.
> So, I think that it need to handle the clock as following:
> 
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 4ef88c0b51ab..355d67fd8beb 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -588,6 +588,12 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
>                         dev_err(&pdev->dev, "Couldn't get core clock\n");
>                         return PTR_ERR(hvs->core_clk);
>                 }
> +
> +               ret = clk_prepare_enable(hvs->core_clk);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "Couldn't enable core clock\n");
> +                       return ret;
> +               }
>         }
>  
>         if (!hvs->hvs5)
> @@ -681,6 +687,8 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
>         drm_mm_takedown(&vc4->hvs->dlist_mm);
>         drm_mm_takedown(&vc4->hvs->lbm_mm);
>  
> +       clk_prepare_enable(vc4->hvs->core_clk);
> +
>         vc4->hvs = NULL;
>  }

Good catch, thanks!
Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
  2020-09-01 16:31                   ` Stefan Wahren
  (?)
@ 2020-09-02 15:08                     ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 15:08 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, linux-arm-kernel, Phil Elwell,
	Nicolas Saenz Julienne, linux-rpi-kernel

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

On Tue, Sep 01, 2020 at 06:31:07PM +0200, Stefan Wahren wrote:
> Hi Maxime,
> 
> Am 01.09.20 um 11:58 schrieb Maxime Ripard:
> > Hi Stefan
> >
> > On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
> >> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> >>> Hi Stefan,
> >>>
> >>> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> >>>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> >>>>> Hi,
> >>>>>
> >>>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >>>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>>>>>> let's use that.
> >>>>>>>
> >>>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>>>>>> ---
> >>>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>>>>>  1 file changed, 2 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> index d0b326e1df0a..7b178d67187f 100644
> >>>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>>>>>
> >>>>>>> +       mdelay(20);
> >>>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >>>>>> not msleep instead?
> >>>>> Since the timing was fairly critical, sleeping didn't seem like a good
> >>>>> solution since there's definitely some chance you overshoot and end up
> >>>>> with a higher time than the one you targeted.
> >>>> usleep_range(min, max) isn't a solution?
> >>> My understanding of usleep_range was that you can still overshoot, even
> >>> though it's backed by an HR timer so the resolution is not a jiffy. Are
> >>> we certain that we're going to be in that range?
> >> you are right there is no guarantee about the upper wake up time.
> >>
> >> And it's not worth the effort to poll the FIFO state until its empty
> >> (using 20 ms as timeout)?
> > I know this isn't really a great argument there, but getting this to
> > work has been quite painful, and the timing is very sensitive. If we
> > fail to wait for enough time, there's going to be a pixel shift that we
> > can't get rid of unless we reboot, which is pretty bad (and would fail
> > any CI test that checks for the output integrity).
> >
> > I know busy-looping for 20ms isn't ideal, but it's not really in a
> > hot-path (it's only done when changing a mode), with the sync time of
> > the display likely to be much more than that, and if it can avoid having
> > to look into it ever again or avoid random failures, I'd say it's worth
> > it.
> 
> i don't want to delay this series.
> 
> Could you please add a small comment to the delay to clarify the timing
> is very sensitive?

I will, thanks!
Maxime

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

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-09-02 15:08                     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 15:08 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

On Tue, Sep 01, 2020 at 06:31:07PM +0200, Stefan Wahren wrote:
> Hi Maxime,
> 
> Am 01.09.20 um 11:58 schrieb Maxime Ripard:
> > Hi Stefan
> >
> > On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
> >> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> >>> Hi Stefan,
> >>>
> >>> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> >>>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> >>>>> Hi,
> >>>>>
> >>>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >>>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>>>>>> let's use that.
> >>>>>>>
> >>>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>>>>>> ---
> >>>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>>>>>  1 file changed, 2 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> index d0b326e1df0a..7b178d67187f 100644
> >>>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>>>>>
> >>>>>>> +       mdelay(20);
> >>>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >>>>>> not msleep instead?
> >>>>> Since the timing was fairly critical, sleeping didn't seem like a good
> >>>>> solution since there's definitely some chance you overshoot and end up
> >>>>> with a higher time than the one you targeted.
> >>>> usleep_range(min, max) isn't a solution?
> >>> My understanding of usleep_range was that you can still overshoot, even
> >>> though it's backed by an HR timer so the resolution is not a jiffy. Are
> >>> we certain that we're going to be in that range?
> >> you are right there is no guarantee about the upper wake up time.
> >>
> >> And it's not worth the effort to poll the FIFO state until its empty
> >> (using 20 ms as timeout)?
> > I know this isn't really a great argument there, but getting this to
> > work has been quite painful, and the timing is very sensitive. If we
> > fail to wait for enough time, there's going to be a pixel shift that we
> > can't get rid of unless we reboot, which is pretty bad (and would fail
> > any CI test that checks for the output integrity).
> >
> > I know busy-looping for 20ms isn't ideal, but it's not really in a
> > hot-path (it's only done when changing a mode), with the sync time of
> > the display likely to be much more than that, and if it can avoid having
> > to look into it ever again or avoid random failures, I'd say it's worth
> > it.
> 
> i don't want to delay this series.
> 
> Could you please add a small comment to the delay to clarify the timing
> is very sensitive?

I will, thanks!
Maxime

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

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

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output
@ 2020-09-02 15:08                     ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 15:08 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Tim Gover, Dave Stevenson, LKML, DRI Development,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel


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

On Tue, Sep 01, 2020 at 06:31:07PM +0200, Stefan Wahren wrote:
> Hi Maxime,
> 
> Am 01.09.20 um 11:58 schrieb Maxime Ripard:
> > Hi Stefan
> >
> > On Tue, Aug 25, 2020 at 11:30:58PM +0200, Stefan Wahren wrote:
> >> Am 25.08.20 um 17:06 schrieb Maxime Ripard:
> >>> Hi Stefan,
> >>>
> >>> On Wed, Jul 29, 2020 at 05:50:31PM +0200, Stefan Wahren wrote:
> >>>> Am 29.07.20 um 16:42 schrieb Maxime Ripard:
> >>>>> Hi,
> >>>>>
> >>>>> On Wed, Jul 29, 2020 at 03:09:21PM +0100, Dave Stevenson wrote:
> >>>>>> On Wed, 8 Jul 2020 at 18:43, Maxime Ripard <maxime@cerno.tech> wrote:
> >>>>>>> In order to avoid pixels getting stuck in the (unflushable) FIFO between
> >>>>>>> the HVS and the PV, we need to add some delay after disabling the PV output
> >>>>>>> and before disabling the HDMI controller. 20ms seems to be good enough so
> >>>>>>> let's use that.
> >>>>>>>
> >>>>>>> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> >>>>>>> ---
> >>>>>>>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 ++
> >>>>>>>  1 file changed, 2 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> index d0b326e1df0a..7b178d67187f 100644
> >>>>>>> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> >>>>>>> @@ -403,6 +403,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
> >>>>>>>         ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1);
> >>>>>>>         WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n");
> >>>>>>>
> >>>>>>> +       mdelay(20);
> >>>>>> mdelay for 20ms seems a touch unfriendly as it's a busy wait. Can we
> >>>>>> not msleep instead?
> >>>>> Since the timing was fairly critical, sleeping didn't seem like a good
> >>>>> solution since there's definitely some chance you overshoot and end up
> >>>>> with a higher time than the one you targeted.
> >>>> usleep_range(min, max) isn't a solution?
> >>> My understanding of usleep_range was that you can still overshoot, even
> >>> though it's backed by an HR timer so the resolution is not a jiffy. Are
> >>> we certain that we're going to be in that range?
> >> you are right there is no guarantee about the upper wake up time.
> >>
> >> And it's not worth the effort to poll the FIFO state until its empty
> >> (using 20 ms as timeout)?
> > I know this isn't really a great argument there, but getting this to
> > work has been quite painful, and the timing is very sensitive. If we
> > fail to wait for enough time, there's going to be a pixel shift that we
> > can't get rid of unless we reboot, which is pretty bad (and would fail
> > any CI test that checks for the output integrity).
> >
> > I know busy-looping for 20ms isn't ideal, but it's not really in a
> > hot-path (it's only done when changing a mode), with the sync time of
> > the display likely to be much more than that, and if it can avoid having
> > to look into it ever again or avoid random failures, I'd say it's worth
> > it.
> 
> i don't want to delay this series.
> 
> Could you please add a small comment to the delay to clarify the timing
> is very sensitive?

I will, thanks!
Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 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] 432+ messages in thread

* Re: [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
  2020-07-29 15:02       ` Dave Stevenson
  (?)
@ 2020-09-02 17:59         ` Maxime Ripard
  -1 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 17:59 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Nicolas Saenz Julienne, Eric Anholt, DRI Development,
	linux-rpi-kernel, bcm-kernel-feedback-list, linux-arm-kernel,
	LKML, Tim Gover, Phil Elwell

Hi!

On Wed, Jul 29, 2020 at 04:02:06PM +0100, Dave Stevenson wrote:
> Hi Maxime
> 
> On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > The vc4 atomic commit loop has an handrolled loop that is basically
> > identical to for_each_new_crtc_state, let's convert it to that helper.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
> >  1 file changed, 4 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> > index 210cc2408087..717673b18132 100644
> > --- a/drivers/gpu/drm/vc4/vc4_kms.c
> > +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> > @@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >         struct drm_device *dev = state->dev;
> >         struct vc4_dev *vc4 = to_vc4_dev(dev);
> >         struct vc4_hvs *hvs = vc4->hvs;
> > -       struct vc4_crtc *vc4_crtc;
> > +       struct drm_crtc_state *new_crtc_state;
> > +       struct drm_crtc *crtc;
> >         int i;
> >
> > -       for (i = 0; i < dev->mode_config.num_crtc; i++) {
> > -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
> > -                       continue;
> > +       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> > +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> 
> for_each_new_crtc_in_state doesn't check !state->crtcs[i].commit as
> the hand rolled loop did. Sorry, this is my lack of knowledge, but
> does that actually make any real difference?
> 
> I see nothing wrong in calling vc4_hvs_mask_underrun multiple times
> anyway, so it's most likely going to be harmless anyway, but wanted to
> query it.

Sorry for not getting back to this earlier.

I don't really know :)

It looks like the commit pointer is always going to be !NULL in our case:
https://elixir.bootlin.com/linux/latest/source/include/drm/drm_crtc.h#L385

The only case where it seems to be checked is when using
for_each_old_crtc_in_state, and when the commit pointer is being
accessed, and we're in neither of those cases.

Since I don't really know though, I guess we can remain on the safe side
and keep it for now.

Maxime

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

* Re: [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
@ 2020-09-02 17:59         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 17:59 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, Eric Anholt,
	bcm-kernel-feedback-list, Nicolas Saenz Julienne, Phil Elwell,
	linux-arm-kernel, linux-rpi-kernel

Hi!

On Wed, Jul 29, 2020 at 04:02:06PM +0100, Dave Stevenson wrote:
> Hi Maxime
> 
> On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > The vc4 atomic commit loop has an handrolled loop that is basically
> > identical to for_each_new_crtc_state, let's convert it to that helper.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
> >  1 file changed, 4 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> > index 210cc2408087..717673b18132 100644
> > --- a/drivers/gpu/drm/vc4/vc4_kms.c
> > +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> > @@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >         struct drm_device *dev = state->dev;
> >         struct vc4_dev *vc4 = to_vc4_dev(dev);
> >         struct vc4_hvs *hvs = vc4->hvs;
> > -       struct vc4_crtc *vc4_crtc;
> > +       struct drm_crtc_state *new_crtc_state;
> > +       struct drm_crtc *crtc;
> >         int i;
> >
> > -       for (i = 0; i < dev->mode_config.num_crtc; i++) {
> > -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
> > -                       continue;
> > +       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> > +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> 
> for_each_new_crtc_in_state doesn't check !state->crtcs[i].commit as
> the hand rolled loop did. Sorry, this is my lack of knowledge, but
> does that actually make any real difference?
> 
> I see nothing wrong in calling vc4_hvs_mask_underrun multiple times
> anyway, so it's most likely going to be harmless anyway, but wanted to
> query it.

Sorry for not getting back to this earlier.

I don't really know :)

It looks like the commit pointer is always going to be !NULL in our case:
https://elixir.bootlin.com/linux/latest/source/include/drm/drm_crtc.h#L385

The only case where it seems to be checked is when using
for_each_old_crtc_in_state, and when the commit pointer is being
accessed, and we're in neither of those cases.

Since I don't really know though, I guess we can remain on the safe side
and keep it for now.

Maxime

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state
@ 2020-09-02 17:59         ` Maxime Ripard
  0 siblings, 0 replies; 432+ messages in thread
From: Maxime Ripard @ 2020-09-02 17:59 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Tim Gover, LKML, DRI Development, bcm-kernel-feedback-list,
	Nicolas Saenz Julienne, Phil Elwell, linux-arm-kernel,
	linux-rpi-kernel

Hi!

On Wed, Jul 29, 2020 at 04:02:06PM +0100, Dave Stevenson wrote:
> Hi Maxime
> 
> On Wed, 8 Jul 2020 at 18:42, Maxime Ripard <maxime@cerno.tech> wrote:
> >
> > The vc4 atomic commit loop has an handrolled loop that is basically
> > identical to for_each_new_crtc_state, let's convert it to that helper.
> >
> > Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> > ---
> >  drivers/gpu/drm/vc4/vc4_kms.c |  9 ++++-----
> >  1 file changed, 4 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> > index 210cc2408087..717673b18132 100644
> > --- a/drivers/gpu/drm/vc4/vc4_kms.c
> > +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> > @@ -152,14 +152,13 @@ vc4_atomic_complete_commit(struct drm_atomic_state *state)
> >         struct drm_device *dev = state->dev;
> >         struct vc4_dev *vc4 = to_vc4_dev(dev);
> >         struct vc4_hvs *hvs = vc4->hvs;
> > -       struct vc4_crtc *vc4_crtc;
> > +       struct drm_crtc_state *new_crtc_state;
> > +       struct drm_crtc *crtc;
> >         int i;
> >
> > -       for (i = 0; i < dev->mode_config.num_crtc; i++) {
> > -               if (!state->crtcs[i].ptr || !state->crtcs[i].commit)
> > -                       continue;
> > +       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> > +               struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
> 
> for_each_new_crtc_in_state doesn't check !state->crtcs[i].commit as
> the hand rolled loop did. Sorry, this is my lack of knowledge, but
> does that actually make any real difference?
> 
> I see nothing wrong in calling vc4_hvs_mask_underrun multiple times
> anyway, so it's most likely going to be harmless anyway, but wanted to
> query it.

Sorry for not getting back to this earlier.

I don't really know :)

It looks like the commit pointer is always going to be !NULL in our case:
https://elixir.bootlin.com/linux/latest/source/include/drm/drm_crtc.h#L385

The only case where it seems to be checked is when using
for_each_old_crtc_in_state, and when the commit pointer is being
accessed, and we're in neither of those cases.

Since I don't really know though, I guess we can remain on the safe side
and keep it for now.

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

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

end of thread, other threads:[~2020-09-03  8:50 UTC | newest]

Thread overview: 432+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20200709070649epcas1p13664bacc66a0f73443bf4d3e8940f933@epcas1p1.samsung.com>
2020-07-08 17:41 ` [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline Maxime Ripard
2020-07-08 17:41   ` Maxime Ripard
2020-07-08 17:41   ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 01/78] dt-bindings: display: Add support for the BCM2711 HVS Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 02/78] drm/vc4: Add support for the BCM2711 HVS5 Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 03/78] drm/vc4: hvs: Boost the core clock during modeset Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-09-01 11:21     ` Chanwoo Choi
2020-09-01 11:21       ` Chanwoo Choi
2020-09-01 11:21       ` Chanwoo Choi
2020-09-01 11:48       ` Chanwoo Choi
2020-09-01 11:48         ` Chanwoo Choi
2020-09-01 11:48         ` Chanwoo Choi
2020-09-02 14:48       ` Maxime Ripard
2020-09-02 14:48         ` Maxime Ripard
2020-09-02 14:48         ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 04/78] drm/vc4: plane: Change LBM alignment constraint on LBM Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 05/78] drm/vc4: plane: Optimize the LBM allocation size Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 06/78] drm/vc4: plane: Create more planes Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 07/78] drm/vc4: crtc: Deal with different number of pixel per clock Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 08/78] drm/vc4: crtc: Use a shared interrupt Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 09/78] drm/vc4: crtc: Move the cob allocation outside of bind Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 10/78] drm/vc4: crtc: Rename HVS channel to output Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28  9:48     ` Dave Stevenson
2020-07-28  9:48       ` Dave Stevenson
2020-07-28  9:48       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 11/78] drm/vc4: crtc: Use local chan variable Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28  9:50     ` Dave Stevenson
2020-07-28  9:50       ` Dave Stevenson
2020-07-28  9:50       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 12/78] drm/vc4: crtc: Enable and disable the PV in atomic_enable / disable Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28  9:57     ` Dave Stevenson
2020-07-28  9:57       ` Dave Stevenson
2020-07-28  9:57       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 13/78] drm/vc4: kms: Convert to for_each_new_crtc_state Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-29 15:02     ` Dave Stevenson
2020-07-29 15:02       ` Dave Stevenson
2020-07-29 15:02       ` Dave Stevenson
2020-09-02 17:59       ` Maxime Ripard
2020-09-02 17:59         ` Maxime Ripard
2020-09-02 17:59         ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 14/78] drm/vc4: crtc: Assign output to channel automatically Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-29 14:31     ` Dave Stevenson
2020-07-29 14:31       ` Dave Stevenson
2020-07-29 14:31       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 15/78] drm/vc4: crtc: Add FIFO depth to vc4_crtc_data Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 16/78] drm/vc4: crtc: Add function to compute FIFO level bits Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 17/78] drm/vc4: crtc: Rename HDMI encoder type to HDMI0 Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 18/78] drm/vc4: crtc: Add HDMI1 encoder type Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 19/78] drm/vc4: crtc: Disable color management for HVS5 Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 20/78] drm/vc4: crtc: Turn pixelvalve reset into a function Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 21/78] drm/vc4: crtc: Move PV dump to config_pv Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 10:30     ` Dave Stevenson
2020-07-28 10:30       ` Dave Stevenson
2020-07-28 10:30       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 22/78] drm/vc4: crtc: Move HVS init and close to a function Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 10:31     ` Dave Stevenson
2020-07-28 10:31       ` Dave Stevenson
2020-07-28 10:31       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 23/78] drm/vc4: crtc: Move the HVS gamma LUT setup to our init function Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-29 14:42     ` Dave Stevenson
2020-07-29 14:42       ` Dave Stevenson
2020-07-29 14:42       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 24/78] drm/vc4: hvs: Make sure our channel is reset Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 10:37     ` Dave Stevenson
2020-07-28 10:37       ` Dave Stevenson
2020-07-28 10:37       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 25/78] drm/vc4: crtc: Remove mode_set_nofb Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 10:38     ` Dave Stevenson
2020-07-28 10:38       ` Dave Stevenson
2020-07-28 10:38       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 26/78] drm/vc4: crtc: Remove redundant pixelvalve reset Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 10:39     ` Dave Stevenson
2020-07-28 10:39       ` Dave Stevenson
2020-07-28 10:39       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 27/78] drm/vc4: crtc: Move HVS channel init before the PV initialisation Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 10:40     ` Dave Stevenson
2020-07-28 10:40       ` Dave Stevenson
2020-07-28 10:40       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 28/78] drm/vc4: encoder: Add finer-grained encoder callbacks Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 11:25     ` Dave Stevenson
2020-07-28 11:25       ` Dave Stevenson
2020-07-28 11:25       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 29/78] drm/vc4: crtc: Add a delay after disabling the PixelValve output Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-29 14:09     ` Dave Stevenson
2020-07-29 14:09       ` Dave Stevenson
2020-07-29 14:09       ` Dave Stevenson
2020-07-29 14:42       ` Maxime Ripard
2020-07-29 14:42         ` Maxime Ripard
2020-07-29 14:42         ` Maxime Ripard
2020-07-29 14:45         ` Dave Stevenson
2020-07-29 14:45           ` Dave Stevenson
2020-07-29 14:45           ` Dave Stevenson
2020-07-29 15:50         ` Stefan Wahren
2020-07-29 15:50           ` Stefan Wahren
2020-07-29 15:50           ` Stefan Wahren
2020-08-25 15:06           ` Maxime Ripard
2020-08-25 15:06             ` Maxime Ripard
2020-08-25 15:06             ` Maxime Ripard
2020-08-25 21:30             ` Stefan Wahren
2020-08-25 21:30               ` Stefan Wahren
2020-08-25 21:30               ` Stefan Wahren
2020-09-01  9:58               ` Maxime Ripard
2020-09-01  9:58                 ` Maxime Ripard
2020-09-01  9:58                 ` Maxime Ripard
2020-09-01 16:31                 ` Stefan Wahren
2020-09-01 16:31                   ` Stefan Wahren
2020-09-01 16:31                   ` Stefan Wahren
2020-09-02 15:08                   ` Maxime Ripard
2020-09-02 15:08                     ` Maxime Ripard
2020-09-02 15:08                     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 30/78] drm/vc4: crtc: Clear the PixelValve FIFO on disable Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 11:40     ` Dave Stevenson
2020-07-28 11:40       ` Dave Stevenson
2020-07-28 11:40       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 31/78] drm/vc4: crtc: Clear the PixelValve FIFO during configuration Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 11:41     ` Dave Stevenson
2020-07-28 11:41       ` Dave Stevenson
2020-07-28 11:41       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 32/78] drm/vc4: hvs: Make the stop_channel function public Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 33/78] drm/vc4: hvs: Introduce a function to get the assigned FIFO Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 34/78] drm/vc4: crtc: Move the CRTC disable out Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 35/78] drm/vc4: drv: Disable the CRTC at boot time Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 36/78] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 37/78] drm/vc4: crtc: Add BCM2711 pixelvalves Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 38/78] drm/vc4: hdmi: Use debugfs private field Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 39/78] drm/vc4: hdmi: Move structure to header Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 40/78] drm/vc4: hdmi: rework connectors and encoders Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 11:58     ` Dave Stevenson
2020-07-28 11:58       ` Dave Stevenson
2020-07-28 11:58       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 41/78] drm/vc4: hdmi: Remove DDC argument to connector_init Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 42/78] drm/vc4: hdmi: Rename hdmi to vc4_hdmi Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 43/78] drm/vc4: hdmi: Move accessors " Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 44/78] drm/vc4: hdmi: Use local vc4_hdmi directly Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 45/78] drm/vc4: hdmi: Add container_of macros for encoders and connectors Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 46/78] drm/vc4: hdmi: Pass vc4_hdmi to CEC code Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 47/78] drm/vc4: hdmi: Retrieve the vc4_hdmi at unbind using our device Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 12:32     ` Dave Stevenson
2020-07-28 12:32       ` Dave Stevenson
2020-07-28 12:32       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 48/78] drm/vc4: hdmi: Remove vc4_dev hdmi pointer Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 49/78] drm/vc4: hdmi: Remove vc4_hdmi_connector Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41   ` [PATCH v4 50/78] drm/vc4: hdmi: Introduce resource init and variant Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 12:37     ` Dave Stevenson
2020-07-28 12:37       ` Dave Stevenson
2020-07-28 12:37       ` Dave Stevenson
2020-07-08 17:41   ` [PATCH v4 51/78] drm/vc4: hdmi: Implement a register layout abstraction Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-08 17:41     ` Maxime Ripard
2020-07-28 12:59     ` Dave Stevenson
2020-07-28 12:59       ` Dave Stevenson
2020-07-28 12:59       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 52/78] drm/vc4: hdmi: Add reset callback Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:00     ` Dave Stevenson
2020-07-28 13:00       ` Dave Stevenson
2020-07-28 13:00       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 53/78] drm/vc4: hdmi: Add PHY init and disable function Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:03     ` Dave Stevenson
2020-07-28 13:03       ` Dave Stevenson
2020-07-28 13:03       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 54/78] drm/vc4: hdmi: Add PHY RNG enable / " Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:04     ` Dave Stevenson
2020-07-28 13:04       ` Dave Stevenson
2020-07-28 13:04       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 55/78] drm/vc4: hdmi: Add a CSC setup callback Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:12     ` Dave Stevenson
2020-07-28 13:12       ` Dave Stevenson
2020-07-28 13:12       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 56/78] drm/vc4: hdmi: Store the encoder type in the variant structure Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:18     ` Dave Stevenson
2020-07-28 13:18       ` Dave Stevenson
2020-07-28 13:18       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 57/78] drm/vc4: hdmi: Deal with multiple debugfs files Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:20     ` Dave Stevenson
2020-07-28 13:20       ` Dave Stevenson
2020-07-28 13:20       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 58/78] drm/vc4: hdmi: Move CEC init to its own function Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:23     ` Dave Stevenson
2020-07-28 13:23       ` Dave Stevenson
2020-07-28 13:23       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 59/78] drm/vc4: hdmi: Add CEC support flag Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:25     ` Dave Stevenson
2020-07-28 13:25       ` Dave Stevenson
2020-07-28 13:25       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 60/78] drm/vc4: hdmi: Remove unused CEC_CLOCK_DIV define Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 13:26     ` Dave Stevenson
2020-07-28 13:26       ` Dave Stevenson
2020-07-28 13:26       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 61/78] drm/vc4: hdmi: Rename drm_encoder pointer in mode_valid Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 14:45     ` Dave Stevenson
2020-07-28 14:45       ` Dave Stevenson
2020-07-28 14:45       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 62/78] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 14:56     ` Dave Stevenson
2020-07-28 14:56       ` Dave Stevenson
2020-07-28 14:56       ` Dave Stevenson
2020-09-01  4:36     ` Chanwoo Choi
2020-09-01  4:36       ` Chanwoo Choi
2020-09-01  4:36       ` Chanwoo Choi
2020-09-01  9:45       ` Maxime Ripard
2020-09-01  9:45         ` Maxime Ripard
2020-09-01  9:45         ` Maxime Ripard
2020-09-01 10:48         ` Chanwoo Choi
2020-09-01 10:48           ` Chanwoo Choi
2020-09-01 10:48           ` Chanwoo Choi
2020-07-08 17:42   ` [PATCH v4 63/78] drm/vc4: hdmi: Use clk_set_min_rate instead Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 14:57     ` Dave Stevenson
2020-07-28 14:57       ` Dave Stevenson
2020-07-28 14:57       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 64/78] drm/vc4: hdmi: Use reg-names to retrieve the HDMI audio registers Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 65/78] drm/vc4: hdmi: Reset audio infoframe on encoder_enable if previously streaming Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 66/78] drm/vc4: hdmi: Set the b-frame marker to the match ALSA's default Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 67/78] drm/vc4: hdmi: Add audio-related callbacks Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 68/78] drm/vc4: hdmi: Deal with multiple ALSA cards Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:00     ` Dave Stevenson
2020-07-28 15:00       ` Dave Stevenson
2020-07-28 15:00       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 69/78] drm/vc4: hdmi: Remove register dumps in enable Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:01     ` Dave Stevenson
2020-07-28 15:01       ` Dave Stevenson
2020-07-28 15:01       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 70/78] drm/vc4: hdmi: Always recenter the HDMI FIFO Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:03     ` Dave Stevenson
2020-07-28 15:03       ` Dave Stevenson
2020-07-28 15:03       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 71/78] drm/vc4: hdmi: Implement finer-grained hooks Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:04     ` Dave Stevenson
2020-07-28 15:04       ` Dave Stevenson
2020-07-28 15:04       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 72/78] drm/vc4: hdmi: Do the VID_CTL configuration at once Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:06     ` Dave Stevenson
2020-07-28 15:06       ` Dave Stevenson
2020-07-28 15:06       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 73/78] drm/vc4: hdmi: Switch to blank pixels when disabled Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:09     ` Dave Stevenson
2020-07-28 15:09       ` Dave Stevenson
2020-07-28 15:09       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 74/78] drm/vc4: hdmi: Support the BCM2711 HDMI controllers Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:21     ` Dave Stevenson
2020-07-28 15:21       ` Dave Stevenson
2020-07-28 15:21       ` Dave Stevenson
2020-07-08 17:42   ` [PATCH v4 75/78] dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-09-01  4:45     ` Chanwoo Choi
2020-09-01  4:45       ` Chanwoo Choi
2020-09-01  4:45       ` Chanwoo Choi
2020-09-01  9:52       ` Maxime Ripard
2020-09-01  9:52         ` Maxime Ripard
2020-09-01  9:52         ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 76/78] dt-bindings: display: vc4: Document BCM2711 VC5 Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 77/78] drm/vc4: drv: Support BCM2711 Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:30     ` Dave Stevenson
2020-07-28 15:30       ` Dave Stevenson
2020-07-28 15:30       ` Dave Stevenson
2020-09-01 10:19       ` Maxime Ripard
2020-09-01 10:19         ` Maxime Ripard
2020-09-01 10:19         ` Maxime Ripard
2020-07-08 17:42   ` [PATCH v4 78/78] ARM: dts: bcm2711: Enable the display pipeline Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-08 17:42     ` Maxime Ripard
2020-07-28 15:35     ` Dave Stevenson
2020-07-28 15:35       ` Dave Stevenson
2020-07-28 15:35       ` Dave Stevenson
2020-07-10  7:37   ` [PATCH v4 00/78] drm/vc4: Support BCM2711 Display Pipeline Jian-Hong Pan
2020-07-10  7:37     ` Jian-Hong Pan
2020-07-10  7:37     ` Jian-Hong Pan
2020-07-10  9:58   ` Stefan Wahren
2020-07-10  9:58     ` Stefan Wahren
2020-07-10  9:58     ` Stefan Wahren
2020-08-21  7:18   ` Hoegeun Kwon
2020-08-21  7:18     ` Hoegeun Kwon
2020-08-21  7:18     ` Hoegeun Kwon
2020-09-02 13:32     ` Maxime Ripard
2020-09-02 13:32       ` Maxime Ripard
2020-09-02 13:32       ` Maxime Ripard
2020-09-02 13:52       ` Maxime Ripard
2020-09-02 13:52         ` Maxime Ripard
2020-09-02 13:52         ` Maxime Ripard
2020-08-31  2:36   ` Chanwoo Choi
2020-08-31  2:36     ` Chanwoo Choi
2020-08-31  2:36     ` Chanwoo Choi

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.