2020-02-24 09:17:44

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 00/89] drm/vc4: Support BCM2711 Display Pipeline

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 output has
been tested too). There's a couple of rough edges still that should be
addressed in the next versions:
- Dual output doesn't work
- The transposer (and thus writeback) doesn't work either and conflicts
with the output mux too.

Let me know if you have any comments
Maxime

Dave Stevenson (2):
drm/vc4: drv: Add support for the BCM2711 HVS5
drm/vc4: plane: Improve LBM usage

Maxime Ripard (87):
dt-bindings: i2c: brcmstb: Convert the BRCMSTB binding to a schema
dt-bindings: i2c: brcmstb: Add BCM2711 BSC/AUTO-I2C binding
i2c: brcmstb: Support BCM2711 HDMI BSC controllers
i2c: brcmstb: Allow to compile it on BCM2835
clk: Return error code when of provider pointer is NULL
dt-bindings: clock: Add a binding for the RPi Firmware clocks
clk: bcm: rpi: Allow the driver to be probed by DT
clk: bcm: rpi: Statically init clk_init_data
clk: bcm: rpi: Use clk_hw_register for pllb_arm
clk: bcm: rpi: Remove global pllb_arm clock pointer
clk: bcm: rpi: Make sure pllb_arm is removed
clk: bcm: rpi: Remove pllb_arm_lookup global pointer
clk: bcm: rpi: Switch to clk_hw_register_clkdev
clk: bcm: rpi: Make sure the clkdev lookup is removed
clk: bcm: rpi: Create a data structure for the clocks
clk: bcm: rpi: Add clock id to data
clk: bcm: rpi: Pass the clocks data to the firmware function
clk: bcm: rpi: Rename is_prepared function
clk: bcm: rpi: Split pllb clock hooks
clk: bcm: rpi: Make the PLLB registration function return a clk_hw
clk: bcm: rpi: Add DT provider for the clocks
clk: bcm: rpi: Discover the firmware clocks
ARM: dts: bcm2711: Add firmware clocks node
reset: Move reset-simple header out of drivers/reset
reset: simple: Add reset callback
dt-bindings: clock: Add BCM2711 DVP binding
clk: bcm: Add BCM2711 DVP driver
ARM: dts: bcm2711: Add HDMI DVP
dt-bindings: display: Convert VC4 bindings to schemas
dt-bindings: display: vc4: dpi: Add missing clock-names property
dt-bindings: display: vc4: dsi: Add missing clock properties
dt-bindings: display: vc4: hdmi: Add missing clock-names property
dt-bindings: display: vc4: Document BCM2711 VC5
drm/vc4: drv: Add include guards
drm/vc4: drv: Support BCM2711
drm/vc4: plane: Move planes creation to its own function
drm/vc4: plane: Move additional planes creation to driver
drm/vc4: plane: Register all the planes at once
drm/vc4: plane: Create overlays for any CRTC
drm/vc4: plane: Create more planes
drm/vc4: crtc: Rename SoC data structures
drm/vc4: crtc: Move crtc state to common header
drm/vc4: crtc: Deal with different number of pixel per clock
drm/vc4: crtc: Use a shared interrupt
drm/vc4: crtc: Turn static const variable into a define
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: 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: Remove redundant call to drm_crtc_enable_color_mgmt
drm/vc4: crtc: Disable color management for HVS5
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: 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: Add a set_timings callback
drm/vc4: hdmi: Add HDMI ID
drm/vc4: hdmi: Deal with multiple debugfs files
drm/vc4: hdmi: Add an audio support flag
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: Support the BCM2711 HDMI controllers
dt-bindings: display: vc4: hdmi: Add BCM2711 HDMI controllers bindings
ARM: dts: bcm2711: Enable the display pipeline

Documentation/devicetree/bindings/clock/brcm,bcm2711-dvp.yaml | 47 ++-
Documentation/devicetree/bindings/clock/raspberrypi,firmware-clocks.yaml | 39 ++-
Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt | 174 +---------
Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml | 72 ++++-
Documentation/devicetree/bindings/display/brcm,bcm2835-dsi0.yaml | 84 ++++-
Documentation/devicetree/bindings/display/brcm,bcm2835-hdmi.yaml | 180 ++++++++++-
Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml | 37 ++-
Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 45 ++-
Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml | 37 ++-
Documentation/devicetree/bindings/display/brcm,bcm2835-v3d.yaml | 42 ++-
Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml | 35 ++-
Documentation/devicetree/bindings/display/brcm,bcm2835-vec.yaml | 44 ++-
Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml | 97 +++++-
Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt | 26 +-
MAINTAINERS | 4 +-
arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 40 ++-
arch/arm/boot/dts/bcm2711.dtsi | 132 +++++++-
drivers/clk/bcm/Kconfig | 1 +-
drivers/clk/bcm/Makefile | 1 +-
drivers/clk/bcm/clk-bcm2711-dvp.c | 113 ++++++-
drivers/clk/bcm/clk-raspberrypi.c | 271 ++++++++++----
drivers/clk/clk.c | 14 +-
drivers/gpu/drm/vc4/Makefile | 1 +-
drivers/gpu/drm/vc4/vc4_crtc.c | 328 ++++++++++-------
drivers/gpu/drm/vc4/vc4_drv.c | 5 +-
drivers/gpu/drm/vc4/vc4_drv.h | 56 ++-
drivers/gpu/drm/vc4/vc4_hdmi.c | 1364 ++++++++++++++++++++++++++++++++++++++++++------------------------------
drivers/gpu/drm/vc4/vc4_hdmi.h | 175 +++++++++-
drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 509 +++++++++++++++++++++++++++-
drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 445 +++++++++++++++++++++++-
drivers/gpu/drm/vc4/vc4_hvs.c | 17 +-
drivers/gpu/drm/vc4/vc4_kms.c | 175 ++++++++-
drivers/gpu/drm/vc4/vc4_plane.c | 271 ++++++++++----
drivers/gpu/drm/vc4/vc4_regs.h | 173 ++++-----
drivers/i2c/busses/Kconfig | 2 +-
drivers/i2c/busses/i2c-brcmstb.c | 33 ++-
drivers/reset/reset-simple.c | 24 +-
drivers/reset/reset-simple.h | 41 +--
drivers/reset/reset-socfpga.c | 3 +-
drivers/reset/reset-sunxi.c | 3 +-
drivers/reset/reset-uniphier-glue.c | 3 +-
include/linux/reset/reset-simple.h | 45 ++-
include/soc/bcm2835/raspberrypi-firmware.h | 5 +-
43 files changed, 4020 insertions(+), 1193 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm2711-dvp.yaml
create mode 100644 Documentation/devicetree/bindings/clock/raspberrypi,firmware-clocks.yaml
delete mode 100644 Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-dsi0.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-hdmi.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-hvs.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-txp.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-v3d.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-vc4.yaml
create mode 100644 Documentation/devicetree/bindings/display/brcm,bcm2835-vec.yaml
create mode 100644 Documentation/devicetree/bindings/i2c/brcm,brcmstb-i2c.yaml
delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-brcmstb.txt
create mode 100644 drivers/clk/bcm/clk-bcm2711-dvp.c
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
delete mode 100644 drivers/reset/reset-simple.h
create mode 100644 include/linux/reset/reset-simple.h

base-commit: fca8fce14e6ce96f4d22783ab8ddea09c0f4de34
--
git-series 0.9.1


2020-02-24 09:26:41

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 11/89] clk: bcm: rpi: Make sure pllb_arm is removed

The pllb_arm clock was created at probe time, but was never removed if
something went wrong later in probe, or if the driver was ever removed from
the system.

Now that we are using clk_hw_register, we can just use its managed variant
to take care of that for us.

Cc: Michael Turquette <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: [email protected]
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/clk/bcm/clk-raspberrypi.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index 61a942f9a6a2..783c8c5e5373 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -240,7 +240,7 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
{
int ret;

- ret = clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw);
+ ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw);
if (ret) {
dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
return ret;
@@ -250,7 +250,6 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
NULL, "cpu0");
if (!rpi->pllb_arm_lookup) {
dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
- clk_hw_unregister_fixed_factor(&raspberrypi_clk_pllb_arm.hw);
return -ENOMEM;
}

--
git-series 0.9.1

2020-02-24 09:26:42

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 12/89] clk: bcm: rpi: Remove pllb_arm_lookup global pointer

The pllb_arm_lookup pointer in the struct raspberrypi_clk is not used for
anything but to store the returned pointer to clkdev_hw_create, and is not
used anywhere else in the driver.

Let's remove that global pointer from the structure.

Cc: Michael Turquette <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: [email protected]
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/clk/bcm/clk-raspberrypi.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index 783c8c5e5373..0c1d6c292302 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -40,7 +40,6 @@ struct raspberrypi_clk {
unsigned long max_rate;

struct clk_hw pllb;
- struct clk_lookup *pllb_arm_lookup;
};

/*
@@ -238,6 +237,7 @@ static struct clk_fixed_factor raspberrypi_clk_pllb_arm = {

static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
{
+ struct clk_lookup *pllb_arm_lookup;
int ret;

ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw);
@@ -246,9 +246,9 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
return ret;
}

- rpi->pllb_arm_lookup = clkdev_hw_create(&raspberrypi_clk_pllb_arm.hw,
- NULL, "cpu0");
- if (!rpi->pllb_arm_lookup) {
+ pllb_arm_lookup = clkdev_hw_create(&raspberrypi_clk_pllb_arm.hw,
+ NULL, "cpu0");
+ if (!pllb_arm_lookup) {
dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
return -ENOMEM;
}
--
git-series 0.9.1

2020-02-24 09:27:09

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 30/89] dt-bindings: display: vc4: dpi: Add missing clock-names property

While the device tree and the driver expected a clock-names property, it
wasn't explicitly documented in the previous binding. Make sure it is now.

Cc: Rob Herring <[email protected]>
Cc: [email protected]
Signed-off-by: Maxime Ripard <[email protected]>
---
Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml b/Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml
index 288494b70e82..58213c564e03 100644
--- a/Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml
+++ b/Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml
@@ -21,6 +21,11 @@ properties:
- description: The core clock the unit runs on
- description: The pixel clock that feeds the pixelvalve

+ clock-names:
+ items:
+ - const: core
+ - const: pixel
+
port:
type: object
description: >
@@ -31,6 +36,7 @@ required:
- compatible
- reg
- clocks
+ - clock-names
- port

additionalProperties: false
--
git-series 0.9.1

2020-02-24 09:27:35

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 56/89] drm/vc4: crtc: Add HDMI1 encoder type

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

Signed-off-by: Maxime Ripard <[email protected]>
---
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 c262c7a388a4..1e44a3a8c2b0 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -428,6 +428,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

2020-02-24 09:27:59

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 81/89] drm/vc4: hdmi: Add an audio support flag

The BCM2711 audio support doesn't work yet, so let's add a boolean to
indicate whether or not it's supported, and only register a sound card if
that boolean is set.

Signed-off-by: Maxime Ripard <[email protected]>
---
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 25fbe2fb72fb..a98661c12c24 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -930,6 +930,9 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
const __be32 *addr;
int ret;

+ if (!vc4_hdmi->variant->audio_available)
+ return 0;
+
if (!of_find_property(dev->of_node, "dmas", NULL)) {
dev_warn(dev,
"'dmas' DT property is missing, no HDMI audio\n");
@@ -1429,6 +1432,7 @@ static int vc4_hdmi_dev_remove(struct platform_device *pdev)
}

struct vc4_hdmi_variant bcm2835_variant = {
+ .audio_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 4d3117de383a..f41116507156 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -32,6 +32,9 @@ struct vc4_hdmi_variant {
*/
unsigned int id;

+ /* Set to true when the audio support is available */
+ bool audio_available;
+
/* List of the registers available on that variant */
const struct vc4_hdmi_register *registers;

--
git-series 0.9.1

2020-02-24 09:28:04

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 67/89] drm/vc4: hdmi: Use local vc4_hdmi directly

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.

Signed-off-by: Maxime Ripard <[email protected]>
---
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 ec3062c4469f..8b563bdd451d 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -124,20 +124,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

2020-02-24 09:28:47

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 80/89] drm/vc4: hdmi: Deal with multiple debugfs files

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 ID to avoid that name conflict.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index fffd1ce7cf90..25fbe2fb72fb 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1365,7 +1365,10 @@ 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->id ? "hdmi1_regs" : "hdmi_regs",
+ vc4_hdmi_debugfs_regs,
+ vc4_hdmi);

return 0;

--
git-series 0.9.1

2020-02-24 09:29:12

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 70/89] drm/vc4: hdmi: Remove vc4_dev hdmi pointer

Now that we don't have any users anymore, we can kill that pointer.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_drv.h | 1 -
drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++--------
2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 1e44a3a8c2b0..d5c832c99460 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 9fec97a328a7..8049a5ba291f 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -1184,7 +1184,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;
@@ -1272,8 +1271,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);
@@ -1354,9 +1351,12 @@ 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 = vc4->hdmi;
+ /*
+ * snd_soc_register_card will set the device drvdata pointer
+ * to the card being registered.
+ */
+ struct snd_soc_card *card = dev_get_drvdata(dev);
+ struct vc4_hdmi *vc4_hdmi = snd_soc_card_get_drvdata(card);

cec_unregister_adapter(vc4_hdmi->cec_adap);
vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
@@ -1366,8 +1366,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

2020-02-24 09:29:15

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 68/89] drm/vc4: hdmi: Add container_of macros for encoders and connectors

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.

Signed-off-by: Maxime Ripard <[email protected]>
---
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 8b563bdd451d..e3f81cbcbe6c 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -120,9 +120,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) ^
@@ -149,17 +147,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;

@@ -237,9 +231,7 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
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,
@@ -252,9 +244,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];
@@ -300,9 +290,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;
@@ -346,9 +335,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;

@@ -370,9 +357,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);
@@ -391,10 +376,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

2020-02-24 09:29:50

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 65/89] drm/vc4: hdmi: Rename hdmi to vc4_hdmi

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.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_hdmi.c | 265 +++++++++++++++++-----------------
1 file changed, 133 insertions(+), 132 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 4964ec6f5608..a08c25e0c056 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -108,11 +108,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;
}
@@ -299,8 +299,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;
@@ -345,7 +345,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;

@@ -354,7 +354,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);
}
@@ -369,7 +369,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);
@@ -378,9 +378,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);
}
@@ -391,7 +391,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;
@@ -413,13 +413,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) {
@@ -427,7 +427,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;
@@ -447,11 +447,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);
@@ -526,11 +526,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,
@@ -617,15 +617,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 >>
@@ -637,14 +637,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;

@@ -676,16 +676,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
@@ -707,11 +707,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;

@@ -727,14 +727,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 */
@@ -742,23 +742,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 |
@@ -767,23 +767,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));
@@ -807,7 +807,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;
}
@@ -815,8 +815,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);

@@ -827,7 +827,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;
@@ -859,8 +859,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);
@@ -872,8 +872,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));
@@ -941,9 +941,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;
}
@@ -969,11 +969,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;

@@ -991,9 +991,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) {
@@ -1016,9 +1016,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;
@@ -1043,7 +1043,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);
@@ -1056,20 +1056,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;
@@ -1095,23 +1096,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);
@@ -1213,44 +1214,44 @@ 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;

- hdmi->pdev = pdev;
- encoder = &hdmi->encoder.base.base;
+ vc4_hdmi->pdev = pdev;
+ encoder = &vc4_hdmi->encoder.base.base;
encoder->base.type = VC4_ENCODER_TYPE_HDMI0;

- 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)) {
+ vc4_hdmi->pixel_clock = devm_clk_get(dev, "pixel");
+ if (IS_ERR(vc4_hdmi->pixel_clock)) {
DRM_ERROR("Failed to get pixel clock\n");
- return PTR_ERR(hdmi->pixel_clock);
+ return PTR_ERR(vc4_hdmi->pixel_clock);
}
- 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);
@@ -1259,9 +1260,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;
}
@@ -1270,13 +1271,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);
@@ -1289,18 +1290,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,
+ vc4_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;
+ 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)) {
@@ -1321,11 +1322,11 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
goto err_destroy_encoder;

#ifdef CONFIG_DRM_VC4_HDMI_CEC
- hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
+ 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(hdmi->cec_adap);
+ ret = PTR_ERR_OR_ZERO(vc4_hdmi->cec_adap);
if (ret < 0)
goto err_destroy_conn;

@@ -1349,32 +1350,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:
vc4_hdmi_encoder_destroy(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;
}
@@ -1384,16 +1385,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);
- vc4_hdmi_encoder_destroy(&hdmi->encoder.base.base);
+ cec_unregister_adapter(vc4_hdmi->cec_adap);
+ vc4_hdmi_connector_destroy(&vc4_hdmi->connector.base);
+ vc4_hdmi_encoder_destroy(&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

2020-02-24 09:30:11

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 39/89] drm/vc4: plane: Move additional planes creation to driver

So far the plane creation was done when each CRTC was bound, and those
planes were only tied to the CRTC that was registering them.

This causes two main issues:
- The planes in the vc4 hardware are actually not tied to any CRTC, but
can be used with every combination

- More importantly, so far, we allocate 10 planes per CRTC, with 3 CRTCs.
However, the next generation of hardware will have 5 CRTCs, putting us
well above the maximum of 32 planes currently allowed by DRM.

This patch is the first one in a series of patches that will take down both
of these issues so that we can support the next generation of hardware
while keeping a good amount of planes.

We start by changing the way the planes are registered to first registering
the primary planes for each CRTC in the CRTC bind function as we used to,
but moving the overlay and cursor creation to the main driver bind
function, after all the CRTCs have been bound.

This will slightly change the ID order of the planes, since the primary
planes of all CRTCs will be first, and then a pattern of 8 overlays, 1
cursor plane for each CRTC.

This shouldn't cause any trouble since the ordering between the planes is
preserved though.

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 4 ----
drivers/gpu/drm/vc4/vc4_drv.c | 7 +++++++
2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 43cfc9ba18ba..fc9977bdf347 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1189,10 +1189,6 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
*/
drm_crtc_enable_color_mgmt(crtc, 0, true, crtc->gamma_size);

- ret = vc4_plane_create_additional_planes(drm, crtc);
- if (ret)
- goto err_destroy_planes;
-
vc4_crtc_get_cob_allocation(vc4_crtc);

CRTC_WRITE(PV_INTEN, 0);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 4aa6e4747346..d23e2ba86727 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -253,6 +253,7 @@ static int vc4_drm_bind(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct drm_device *drm;
+ struct drm_crtc *crtc;
struct vc4_dev *vc4;
struct device_node *node;
int ret = 0;
@@ -291,6 +292,12 @@ static int vc4_drm_bind(struct device *dev)
if (ret)
goto gem_destroy;

+ drm_for_each_crtc(crtc, drm) {
+ ret = vc4_plane_create_additional_planes(drm, crtc);
+ if (ret)
+ continue;
+ }
+
drm_fb_helper_remove_conflicting_framebuffers(NULL, "vc4drmfb", false);

ret = vc4_kms_load(drm);
--
git-series 0.9.1

2020-02-24 09:30:22

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 61/89] drm/vc4: hdmi: Use debugfs private field

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.

Signed-off-by: Maxime Ripard <[email protected]>
---
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 0c3cfa552239..7fad602217c1 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -182,9 +182,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

2020-02-24 09:30:26

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 60/89] drm/vc4: crtc: Add BCM2711 pixelvalves

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

Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 82 ++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/vc4/vc4_regs.h | 6 +++-
2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b10b267f56fe..82ae787fca58 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -273,6 +273,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 (vc4_crtc->data->hvs_output == 5)
+ return 32;
+
return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX;
}
}
@@ -281,8 +288,14 @@ 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);
+ u32 ret = 0;
+
+ if (level > 0x3f)
+ ret |= VC4_SET_FIELD((level >> 6) & 0x3,
+ PV5_CONTROL_FIFO_LEVEL_HIGH);
+
+ return ret | VC4_SET_FIELD(level & 0x3f,
+ PV_CONTROL_FIFO_LEVEL);
}

/*
@@ -328,6 +341,9 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc)
CRTC_WRITE(PV_CONTROL, PV_CONTROL_FIFO_CLR | PV_CONTROL_EN);
CRTC_WRITE(PV_CONTROL, 0);

+ CRTC_WRITE(PV_MUX_CFG,
+ VC4_SET_FIELD(8, PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
+
CRTC_WRITE(PV_HORZA,
VC4_SET_FIELD((mode->htotal - mode->hsync_end) * pixel_rep / ppc,
PV_HORZA_HBP) |
@@ -1114,10 +1130,72 @@ static const struct vc4_crtc_data bcm2835_pv2_data = {
},
};

+static const struct vc4_crtc_data bcm2711_pv0_data = {
+ .debugfs_name = "crtc0_regs",
+ .hvs_available_channels = BIT(0),
+ .hvs_output = 0,
+ .fifo_depth = 64,
+ .pixels_per_clock = 1,
+ .encoder_types = {
+ [0] = VC4_ENCODER_TYPE_DSI0,
+ [1] = VC4_ENCODER_TYPE_DPI,
+ },
+};
+
+static const struct vc4_crtc_data bcm2711_pv1_data = {
+ .debugfs_name = "crtc1_regs",
+ .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+ .hvs_output = 3,
+ .fifo_depth = 64,
+ .pixels_per_clock = 1,
+ .encoder_types = {
+ [0] = VC4_ENCODER_TYPE_DSI1,
+ [1] = VC4_ENCODER_TYPE_SMI,
+ },
+};
+
+static const struct vc4_crtc_data bcm2711_pv2_data = {
+ .debugfs_name = "crtc2_regs",
+ .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+ .hvs_output = 4,
+ .fifo_depth = 256,
+ .pixels_per_clock = 2,
+ .encoder_types = {
+ [0] = VC4_ENCODER_TYPE_HDMI0,
+ },
+};
+
+static const struct vc4_crtc_data bcm2711_pv3_data = {
+ .debugfs_name = "crtc3_regs",
+ .hvs_available_channels = BIT(1),
+ .hvs_output = 1,
+ .fifo_depth = 64,
+ .pixels_per_clock = 1,
+ .encoder_types = {
+ [0] = VC4_ENCODER_TYPE_VEC,
+ },
+};
+
+static const struct vc4_crtc_data bcm2711_pv4_data = {
+ .debugfs_name = "crtc4_regs",
+ .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
+ .hvs_output = 5,
+ .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 b96ebbb1354b..35279b118d41 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -130,6 +130,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
@@ -209,6 +211,10 @@

#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 SCALER_CHANNELS_COUNT 3

#define SCALER_DISPCTRL 0x00000000
--
git-series 0.9.1

2020-02-24 09:30:32

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 59/89] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves

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

Cc: Rob Herring <[email protected]>
Cc: [email protected]
Signed-off-by: Maxime Ripard <[email protected]>
---
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

2020-02-24 09:30:48

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 36/89] drm/vc4: drv: Add support for the BCM2711 HVS5

From: Dave Stevenson <[email protected]>

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 <[email protected]>
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/gpu/drm/vc4/vc4_crtc.c | 24 +++-
drivers/gpu/drm/vc4/vc4_drv.h | 4 +-
drivers/gpu/drm/vc4/vc4_hvs.c | 17 ++-
drivers/gpu/drm/vc4/vc4_plane.c | 194 ++++++++++++++++++++++++---------
drivers/gpu/drm/vc4/vc4_regs.h | 67 +++++++++++-
5 files changed, 247 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index b00e20f5ce05..381702b9f057 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -550,6 +550,7 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
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;
+ u32 dispctrl;

require_hvs_enabled(dev);

@@ -564,11 +565,24 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
* When feeding the transposer, we should operate in oneshot
* mode.
*/
- HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel),
- VC4_SET_FIELD(mode->hdisplay, SCALER_DISPCTRLX_WIDTH) |
- VC4_SET_FIELD(mode->vdisplay, SCALER_DISPCTRLX_HEIGHT) |
- SCALER_DISPCTRLX_ENABLE |
- (vc4_state->feed_txp ? SCALER_DISPCTRLX_ONESHOT : 0));
+ 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) |
+ (vc4_state->feed_txp ?
+ SCALER_DISPCTRLX_ONESHOT : 0);
+ else
+ dispctrl |= VC4_SET_FIELD(mode->hdisplay,
+ SCALER5_DISPCTRLX_WIDTH) |
+ VC4_SET_FIELD(mode->vdisplay,
+ SCALER5_DISPCTRLX_HEIGHT) |
+ (vc4_state->feed_txp ?
+ SCALER5_DISPCTRLX_ONESHOT : 0);
+
+ HVS_WRITE(SCALER_DISPCTRLX(vc4_crtc->channel), dispctrl);

/* When feeding the transposer block the pixelvalve is unneeded and
* should not be enabled.
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index c8dc04183c7b..63c05c764942 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -332,7 +332,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 5a43659da319..4ca831414c5e 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -223,6 +223,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
struct vc4_hvs *hvs = NULL;
int ret;
u32 dispctrl;
+ unsigned int hvs_version;

hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL);
if (!hvs)
@@ -238,7 +239,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);

- hvs->dlist = hvs->regs + SCALER_DLIST_START;
+ hvs_version = readl(hvs->regs + SCALER_DISPLSTAT) >> 24;
+ if (hvs_version >= 0x40)
+ hvs->hvs5 = true;
+
+ if (!hvs->hvs5)
+ hvs->dlist = hvs->regs + SCALER_DLIST_START;
+ else
+ hvs->dlist = hvs->regs + SCALER5_DLIST_START;

spin_lock_init(&hvs->mm_lock);

@@ -256,7 +264,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.
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 07a145e286f7..0b8309247dec 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,
},
{
@@ -781,35 +796,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.
@@ -817,20 +803,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
@@ -1208,6 +1294,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 b5a6b4cdd332..8a51baf681fe 100644
--- a/drivers/gpu/drm/vc4/vc4_regs.h
+++ b/drivers/gpu/drm/vc4/vc4_regs.h
@@ -328,6 +328,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)
@@ -461,6 +475,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
@@ -826,6 +842,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
@@ -880,6 +898,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

@@ -897,10 +919,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

@@ -910,12 +935,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
@@ -931,6 +992,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

2020-02-24 09:30:52

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 23/89] ARM: dts: bcm2711: Add firmware clocks node

Now that we have a clock driver for the clocks exposed by the firmware,
let's add the device tree nodes for it.

Signed-off-by: Maxime Ripard <[email protected]>
---
arch/arm/boot/dts/bcm2711.dtsi | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index d1e684d0acfd..4742e1a77a65 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -12,6 +12,12 @@

interrupt-parent = <&gicv2>;

+ firmware_clocks: firmware-clocks {
+ compatible = "raspberrypi,firmware-clocks";
+ raspberrypi,firmware = <&firmware>;
+ #clock-cells = <1>;
+ };
+
soc {
/*
* Defined ranges:
--
git-series 0.9.1

2020-02-24 09:30:55

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 22/89] clk: bcm: rpi: Discover the firmware clocks

The firmware has an interface to discover the clocks it exposes.

Let's use it to discover, register the clocks in the clocks framework and
then expose them through the device tree for consumers to use them.

Cc: Michael Turquette <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: [email protected]
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/clk/bcm/clk-raspberrypi.c | 105 +++++++++++++++++++---
include/soc/bcm2835/raspberrypi-firmware.h | 5 +-
2 files changed, 98 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index 3f21888a3e3e..bf6a1e2dc099 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -285,6 +285,95 @@ static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
return &raspberrypi_clk_pllb_arm.hw;
}

+static long raspberrypi_fw_dumb_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ return rate;
+}
+
+static const struct clk_ops raspberrypi_firmware_clk_ops = {
+ .is_prepared = raspberrypi_fw_is_prepared,
+ .recalc_rate = raspberrypi_fw_get_rate,
+ .round_rate = raspberrypi_fw_dumb_round_rate,
+ .set_rate = raspberrypi_fw_set_rate,
+};
+
+static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
+ unsigned int parent,
+ unsigned int id)
+{
+ struct raspberrypi_clk_data *data;
+ struct clk_init_data init = {};
+ int ret;
+
+ if (id == RPI_FIRMWARE_ARM_CLK_ID) {
+ struct clk_hw *hw;
+
+ hw = raspberrypi_register_pllb(rpi);
+ if (IS_ERR(hw)) {
+ dev_err(rpi->dev, "Failed to initialize pllb, %ld\n",
+ PTR_ERR(hw));
+ return hw;
+ }
+
+ hw = raspberrypi_register_pllb_arm(rpi);
+ if (IS_ERR(hw))
+ return hw;
+
+ return hw;
+ }
+
+ data = devm_kzalloc(rpi->dev, sizeof(data), GFP_KERNEL);
+ if (!data)
+ return ERR_PTR(-ENOMEM);
+ data->rpi = rpi;
+ data->id = id;
+
+ init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, "fw-clk-%u", id);
+ init.ops = &raspberrypi_firmware_clk_ops;
+ init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;
+
+ data->hw.init = &init;
+
+ ret = devm_clk_hw_register(rpi->dev, &data->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &data->hw;
+}
+
+static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
+ struct clk_hw_onecell_data *data)
+{
+ struct rpi_firmware_get_clocks_response *clks;
+ size_t clks_size = NUM_FW_CLKS * sizeof(*clks);
+ int ret;
+
+ clks = devm_kzalloc(rpi->dev, clks_size, GFP_KERNEL);
+ if (!clks)
+ return -ENOMEM;
+
+ ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
+ clks, clks_size);
+ if (ret)
+ return ret;
+
+ while (clks->id) {
+ struct clk_hw *hw;
+
+ hw = raspberrypi_clk_register(rpi, clks->parent, clks->id);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
+
+ data->hws[clks->id] = hw;
+ data->num = clks->id + 1;
+ clks++;
+ }
+
+ return 0;
+}
+
static int raspberrypi_clk_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *clk_data;
@@ -292,7 +381,7 @@ static int raspberrypi_clk_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rpi_firmware *firmware;
struct raspberrypi_clk *rpi;
- struct clk_hw *hw;
+ int ret;

firmware_node = of_parse_phandle(dev->of_node, "raspberrypi,firmware", 0);
if (!firmware_node) {
@@ -317,17 +406,9 @@ static int raspberrypi_clk_probe(struct platform_device *pdev)
if (!clk_data)
return -ENOMEM;

- hw = raspberrypi_register_pllb(rpi);
- if (IS_ERR(hw)) {
- dev_err(dev, "Failed to initialize pllb, %ld\n", PTR_ERR(hw));
- return PTR_ERR(hw);
- }
-
- hw = raspberrypi_register_pllb_arm(rpi);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- clk_data->hws[RPI_FIRMWARE_ARM_CLK_ID] = hw;
- clk_data->num = RPI_FIRMWARE_ARM_CLK_ID + 1;
+ ret = raspberrypi_discover_clocks(rpi, clk_data);
+ if (ret)
+ return ret;

ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
clk_data);
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
index 7800e12ee042..e5b7a41bba6b 100644
--- a/include/soc/bcm2835/raspberrypi-firmware.h
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
@@ -135,6 +135,11 @@ enum rpi_firmware_property_tag {
RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
};

+struct rpi_firmware_get_clocks_response {
+ __le32 parent;
+ __le32 id;
+};
+
#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
int rpi_firmware_property(struct rpi_firmware *fw,
u32 tag, void *data, size_t len);
--
git-series 0.9.1

2020-02-24 09:31:45

by Maxime Ripard

[permalink] [raw]
Subject: [PATCH 17/89] clk: bcm: rpi: Pass the clocks data to the firmware function

The raspberry_clock_property only takes the clock ID as an argument, but
now that we have a clock data structure it makes more sense to just pass
that structure instead.

Cc: Michael Turquette <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: [email protected]
Signed-off-by: Maxime Ripard <[email protected]>
---
drivers/clk/bcm/clk-raspberrypi.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index e796dabbc641..3b2da62a72f5 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -67,11 +67,12 @@ struct raspberrypi_firmware_prop {
__le32 disable_turbo;
} __packed;

-static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
- u32 clk, u32 *val)
+static int raspberrypi_clock_property(struct rpi_firmware *firmware,
+ struct raspberrypi_clk_data *data,
+ u32 tag, u32 *val)
{
struct raspberrypi_firmware_prop msg = {
- .id = cpu_to_le32(clk),
+ .id = cpu_to_le32(data->id),
.val = cpu_to_le32(*val),
.disable_turbo = cpu_to_le32(1),
};
@@ -94,9 +95,8 @@ static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
u32 val = 0;
int ret;

- ret = raspberrypi_clock_property(rpi->firmware,
- RPI_FIRMWARE_GET_CLOCK_STATE,
- data->id, &val);
+ ret = raspberrypi_clock_property(rpi->firmware, data,
+ RPI_FIRMWARE_GET_CLOCK_STATE, &val);
if (ret)
return 0;

@@ -113,9 +113,8 @@ static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
u32 val = 0;
int ret;

- ret = raspberrypi_clock_property(rpi->firmware,
- RPI_FIRMWARE_GET_CLOCK_RATE,
- data->id, &val);
+ ret = raspberrypi_clock_property(rpi->firmware, data,
+ RPI_FIRMWARE_GET_CLOCK_RATE, &val);
if (ret)
return ret;

@@ -131,9 +130,9 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
int ret;

- ret = raspberrypi_clock_property(rpi->firmware,
+ ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_SET_CLOCK_RATE,
- data->id, &new_rate);
+ &new_rate);
if (ret)
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
clk_hw_get_name(hw), ret);
@@ -198,18 +197,18 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;

/* Get min & max rates set by the firmware */
- ret = raspberrypi_clock_property(rpi->firmware,
+ ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
- data->id, &min_rate);
+ &min_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
init.name, ret);
return ret;
}

- ret = raspberrypi_clock_property(rpi->firmware,
+ ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
- data->id, &max_rate);
+ &max_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
init.name, ret);
--
git-series 0.9.1

2020-02-24 16:48:17

by kernel test robot

[permalink] [raw]
Subject: [PATCH] clk: bcm: rpi: fix noderef.cocci warnings

From: kbuild test robot <[email protected]>

drivers/clk/bcm/clk-raspberrypi.c:327:31-37: ERROR: application of sizeof to pointer

sizeof when applied to a pointer typed expression gives the size of
the pointer

Generated by: scripts/coccinelle/misc/noderef.cocci

Fixes: 56ccc5cfbb47 ("clk: bcm: rpi: Discover the firmware clocks")
CC: Maxime Ripard <[email protected]>
Signed-off-by: kbuild test robot <[email protected]>
---

url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/drm-vc4-Support-BCM2711-Display-Pipeline/20200224-172730
base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next

clk-raspberrypi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -324,7 +324,7 @@ static struct clk_hw *raspberrypi_clk_re
return hw;
}

- data = devm_kzalloc(rpi->dev, sizeof(data), GFP_KERNEL);
+ data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return ERR_PTR(-ENOMEM);
data->rpi = rpi;

2020-02-24 16:48:19

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 22/89] clk: bcm: rpi: Discover the firmware clocks

Hi Maxime,

I love your patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on robh/for-next anholt/for-next v5.6-rc3 next-20200224]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/drm-vc4-Support-BCM2711-Display-Pipeline/20200224-172730
base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <[email protected]>


coccinelle warnings: (new ones prefixed by >>)

>> drivers/clk/bcm/clk-raspberrypi.c:327:31-37: ERROR: application of sizeof to pointer

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]

2020-02-24 18:17:02

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH 22/89] clk: bcm: rpi: Discover the firmware clocks

On 2/24/20 1:06 AM, Maxime Ripard wrote:
> The firmware has an interface to discover the clocks it exposes.
>
> Let's use it to discover, register the clocks in the clocks framework and
> then expose them through the device tree for consumers to use them.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>

That seems like a re-implementaiton of SCMI without all of its
protocols, without being able to use the existing drivers, maybe a
firmware update should be considered so standard drivers can be leveraged?
--
Florian

2020-02-24 20:25:21

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 22/89] clk: bcm: rpi: Discover the firmware clocks

Hi Maxime,

I love your patch! Perhaps something to improve:

[auto build test WARNING on clk/clk-next]
[also build test WARNING on robh/for-next anholt/for-next v5.6-rc3 next-20200224]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url: https://github.com/0day-ci/linux/commits/Maxime-Ripard/drm-vc4-Support-BCM2711-Display-Pipeline/20200224-172730
base: https://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-next
reproduce:
# apt-get install sparse
# sparse version: v0.6.1-173-ge0787745-dirty
make ARCH=x86_64 allmodconfig
make C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__'

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <[email protected]>


sparse warnings: (new ones prefixed by >>)

>> drivers/clk/bcm/clk-raspberrypi.c:365:56: sparse: sparse: incorrect type in argument 2 (different base types)
>> drivers/clk/bcm/clk-raspberrypi.c:365:56: sparse: expected unsigned int parent
>> drivers/clk/bcm/clk-raspberrypi.c:365:56: sparse: got restricted __le32 [usertype] parent
drivers/clk/bcm/clk-raspberrypi.c:365:70: sparse: sparse: incorrect type in argument 3 (different base types)
>> drivers/clk/bcm/clk-raspberrypi.c:365:70: sparse: expected unsigned int id
>> drivers/clk/bcm/clk-raspberrypi.c:365:70: sparse: got restricted __le32 [usertype] id
>> drivers/clk/bcm/clk-raspberrypi.c:369:31: sparse: sparse: restricted __le32 degrades to integer
drivers/clk/bcm/clk-raspberrypi.c:370:33: sparse: sparse: restricted __le32 degrades to integer

vim +365 drivers/clk/bcm/clk-raspberrypi.c

345
346 static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
347 struct clk_hw_onecell_data *data)
348 {
349 struct rpi_firmware_get_clocks_response *clks;
350 size_t clks_size = NUM_FW_CLKS * sizeof(*clks);
351 int ret;
352
353 clks = devm_kzalloc(rpi->dev, clks_size, GFP_KERNEL);
354 if (!clks)
355 return -ENOMEM;
356
357 ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
358 clks, clks_size);
359 if (ret)
360 return ret;
361
362 while (clks->id) {
363 struct clk_hw *hw;
364
> 365 hw = raspberrypi_clk_register(rpi, clks->parent, clks->id);
366 if (IS_ERR(hw))
367 return PTR_ERR(hw);
368
> 369 data->hws[clks->id] = hw;
370 data->num = clks->id + 1;
371 clks++;
372 }
373
374 return 0;
375 }
376

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]

2020-02-25 16:16:35

by Nicolas Saenz Julienne

[permalink] [raw]
Subject: Re: [PATCH 11/89] clk: bcm: rpi: Make sure pllb_arm is removed

On Mon, 2020-02-24 at 10:06 +0100, Maxime Ripard wrote:
> The pllb_arm clock was created at probe time, but was never removed if
> something went wrong later in probe, or if the driver was ever removed from
> the system.
>
> Now that we are using clk_hw_register, we can just use its managed variant
> to take care of that for us.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>

Acked-by: Nicolas Saenz Julienne <[email protected]>

Thanks!
Nicolas


Attachments:
signature.asc (499.00 B)
This is a digitally signed message part

2020-02-25 16:17:43

by Nicolas Saenz Julienne

[permalink] [raw]
Subject: Re: [PATCH 12/89] clk: bcm: rpi: Remove pllb_arm_lookup global pointer

On Mon, 2020-02-24 at 10:06 +0100, Maxime Ripard wrote:
> The pllb_arm_lookup pointer in the struct raspberrypi_clk is not used for
> anything but to store the returned pointer to clkdev_hw_create, and is not
> used anywhere else in the driver.
>
> Let's remove that global pointer from the structure.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>

Acked-by: Nicolas Saenz Julienne <[email protected]>

Thanks!
Nicolas


Attachments:
signature.asc (499.00 B)
This is a digitally signed message part

2020-02-25 16:27:07

by Nicolas Saenz Julienne

[permalink] [raw]
Subject: Re: [PATCH 17/89] clk: bcm: rpi: Pass the clocks data to the firmware function

On Mon, 2020-02-24 at 10:06 +0100, Maxime Ripard wrote:
> The raspberry_clock_property only takes the clock ID as an argument, but
> now that we have a clock data structure it makes more sense to just pass
> that structure instead.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>

Acked-by: Nicolas Saenz Julienne <[email protected]>

Thanks!
Nicolas


Attachments:
signature.asc (499.00 B)
This is a digitally signed message part

2020-02-25 18:18:16

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 30/89] dt-bindings: display: vc4: dpi: Add missing clock-names property

On Mon, 24 Feb 2020 10:06:32 +0100, Maxime Ripard wrote:
> While the device tree and the driver expected a clock-names property, it
> wasn't explicitly documented in the previous binding. Make sure it is now.
>
> Cc: Rob Herring <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> Documentation/devicetree/bindings/display/brcm,bcm2835-dpi.yaml | 6 ++++++
> 1 file changed, 6 insertions(+)
>

Reviewed-by: Rob Herring <[email protected]>

2020-02-25 18:20:43

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH 59/89] dt-bindings: display: vc4: pv: Add BCM2711 pixel valves

On Mon, 24 Feb 2020 10:07:01 +0100, Maxime Ripard wrote:
> The BCM2711 comes with other pixelvalves that have different requirements
> and capabilities. Let's document their compatible.
>
> Cc: Rob Herring <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> Documentation/devicetree/bindings/display/brcm,bcm2835-pixelvalve0.yaml | 5 +++++
> 1 file changed, 5 insertions(+)
>

Acked-by: Rob Herring <[email protected]>

2020-02-26 14:15:56

by Maxime Ripard

[permalink] [raw]
Subject: Re: [PATCH 22/89] clk: bcm: rpi: Discover the firmware clocks

Hi Florian,

On Mon, Feb 24, 2020 at 10:15:32AM -0800, Florian Fainelli wrote:
> On 2/24/20 1:06 AM, Maxime Ripard wrote:
> > The firmware has an interface to discover the clocks it exposes.
> >
> > Let's use it to discover, register the clocks in the clocks framework and
> > then expose them through the device tree for consumers to use them.
> >
> > Cc: Michael Turquette <[email protected]>
> > Cc: Stephen Boyd <[email protected]>
> > Cc: [email protected]
> > Signed-off-by: Maxime Ripard <[email protected]>
>
> That seems like a re-implementaiton of SCMI without all of its
> protocols, without being able to use the existing drivers, maybe a
> firmware update should be considered so standard drivers can be leveraged?

I'm not really qualified to talk about how the firmware will evolve in
the future, but you're right that it looks a lot like what SCMI can
do.

Even if a firmware update was to support SCMI at some point, since the
firmware is flashed in an EEPROM, we'd still have to support that
interface.

Maxime


Attachments:
(No filename) (1.04 kB)
signature.asc (235.00 B)
Download all attachments

2020-03-05 10:01:49

by Jian-Hong Pan

[permalink] [raw]
Subject: Re: [PATCH 70/89] drm/vc4: hdmi: Remove vc4_dev hdmi pointer

> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 1e44a3a8c2b0..d5c832c99460 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;

Tested the building based on kernel v5.6-rc4 and linux-next/next-20200225.
The hdmi removed here still be used in drivers/gpu/drm/vc4/vc4_hdmi.c.
If DRM_VC4_HDMI_CEC is not disabled in building config, then it will hit
building error.

Jian-Hong Pan

> struct vc4_hvs *hvs;
> struct vc4_v3d *v3d;
> struct vc4_dpi *dpi;

2020-03-12 23:21:15

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH 11/89] clk: bcm: rpi: Make sure pllb_arm is removed

Quoting Maxime Ripard (2020-02-24 01:06:13)
> The pllb_arm clock was created at probe time, but was never removed if
> something went wrong later in probe, or if the driver was ever removed from
> the system.
>
> Now that we are using clk_hw_register, we can just use its managed variant
> to take care of that for us.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>
> ---

Reviewed-by: Stephen Boyd <[email protected]>

2020-03-12 23:22:13

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH 12/89] clk: bcm: rpi: Remove pllb_arm_lookup global pointer

Quoting Maxime Ripard (2020-02-24 01:06:14)
> The pllb_arm_lookup pointer in the struct raspberrypi_clk is not used for
> anything but to store the returned pointer to clkdev_hw_create, and is not
> used anywhere else in the driver.
>
> Let's remove that global pointer from the structure.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>
> ---

Reviewed-by: Stephen Boyd <[email protected]>

2020-03-13 01:09:00

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH 22/89] clk: bcm: rpi: Discover the firmware clocks

Quoting Maxime Ripard (2020-02-24 01:06:24)
> The firmware has an interface to discover the clocks it exposes.
>
> Let's use it to discover, register the clocks in the clocks framework and
> then expose them through the device tree for consumers to use them.

Everyone's doing it! :)

> diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
> index 3f21888a3e3e..bf6a1e2dc099 100644
> --- a/drivers/clk/bcm/clk-raspberrypi.c
> +++ b/drivers/clk/bcm/clk-raspberrypi.c
> @@ -285,6 +285,95 @@ static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
> return &raspberrypi_clk_pllb_arm.hw;
> }
>
> +static long raspberrypi_fw_dumb_round_rate(struct clk_hw *hw,
> + unsigned long rate,
> + unsigned long *parent_rate)
> +{
> + return rate;

Can we get a comment here like "The firmware does the rounding but
doesn't tell us so we have to assume anything goes!"

> +}
> +
> +static const struct clk_ops raspberrypi_firmware_clk_ops = {
> + .is_prepared = raspberrypi_fw_is_prepared,
> + .recalc_rate = raspberrypi_fw_get_rate,
> + .round_rate = raspberrypi_fw_dumb_round_rate,
> + .set_rate = raspberrypi_fw_set_rate,
> +};
> +
> +static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
> + unsigned int parent,
> + unsigned int id)
> +{
> + struct raspberrypi_clk_data *data;
> + struct clk_init_data init = {};
> + int ret;
> +
> + if (id == RPI_FIRMWARE_ARM_CLK_ID) {
> + struct clk_hw *hw;
> +
> + hw = raspberrypi_register_pllb(rpi);
> + if (IS_ERR(hw)) {
> + dev_err(rpi->dev, "Failed to initialize pllb, %ld\n",
> + PTR_ERR(hw));
> + return hw;
> + }
> +
> + hw = raspberrypi_register_pllb_arm(rpi);
> + if (IS_ERR(hw))
> + return hw;
> +
> + return hw;

Why the double return? Not just

return raspberrypi_register_pllb_arm(rpi);

> + }
> +
> + data = devm_kzalloc(rpi->dev, sizeof(data), GFP_KERNEL);
> + if (!data)
> + return ERR_PTR(-ENOMEM);
> + data->rpi = rpi;
> + data->id = id;
> +
> + init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, "fw-clk-%u", id);
> + init.ops = &raspberrypi_firmware_clk_ops;
> + init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;

Why ignore unused? Doesn't seem to support enable/disable anyway so not
sure this flag adds any value.

> +
> + data->hw.init = &init;
> +
> + ret = devm_clk_hw_register(rpi->dev, &data->hw);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return &data->hw;
> +}
> +
> +static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
> + struct clk_hw_onecell_data *data)
> +{
> + struct rpi_firmware_get_clocks_response *clks;
> + size_t clks_size = NUM_FW_CLKS * sizeof(*clks);
> + int ret;
> +
> + clks = devm_kzalloc(rpi->dev, clks_size, GFP_KERNEL);

Use devm_kcalloc to avoid overflow and indicate it's an array.

> + if (!clks)
> + return -ENOMEM;
> +
> + ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
> + clks, clks_size);
> + if (ret)
> + return ret;
> +
> + while (clks->id) {
> + struct clk_hw *hw;
> +
> + hw = raspberrypi_clk_register(rpi, clks->parent, clks->id);
> + if (IS_ERR(hw))
> + return PTR_ERR(hw);
> +
> + data->hws[clks->id] = hw;
> + data->num = clks->id + 1;
> + clks++;
> + }
> +
> + return 0;
> +}
> +
> static int raspberrypi_clk_probe(struct platform_device *pdev)
> {
> struct clk_hw_onecell_data *clk_data;
> diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
> index 7800e12ee042..e5b7a41bba6b 100644
> --- a/include/soc/bcm2835/raspberrypi-firmware.h
> +++ b/include/soc/bcm2835/raspberrypi-firmware.h
> @@ -135,6 +135,11 @@ enum rpi_firmware_property_tag {
> RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001,
> };
>
> +struct rpi_firmware_get_clocks_response {
> + __le32 parent;
> + __le32 id;

Why double spaced or tabbed out?

> +};
> +
> #if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE)
> int rpi_firmware_property(struct rpi_firmware *fw,

2020-03-13 01:10:35

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH 17/89] clk: bcm: rpi: Pass the clocks data to the firmware function

Quoting Maxime Ripard (2020-02-24 01:06:19)
> The raspberry_clock_property only takes the clock ID as an argument, but
> now that we have a clock data structure it makes more sense to just pass
> that structure instead.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>
> ---
> drivers/clk/bcm/clk-raspberrypi.c | 29 ++++++++++++++---------------
> 1 file changed, 14 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
> index e796dabbc641..3b2da62a72f5 100644
> --- a/drivers/clk/bcm/clk-raspberrypi.c
> +++ b/drivers/clk/bcm/clk-raspberrypi.c
> @@ -67,11 +67,12 @@ struct raspberrypi_firmware_prop {
> __le32 disable_turbo;
> } __packed;
>
> -static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
> - u32 clk, u32 *val)
> +static int raspberrypi_clock_property(struct rpi_firmware *firmware,
> + struct raspberrypi_clk_data *data,

Can data be const?

> + u32 tag, u32 *val)
> {
> struct raspberrypi_firmware_prop msg = {
> - .id = cpu_to_le32(clk),
> + .id = cpu_to_le32(data->id),
> .val = cpu_to_le32(*val),
> .disable_turbo = cpu_to_le32(1),
> };

2020-03-13 01:13:37

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH 12/89] clk: bcm: rpi: Remove pllb_arm_lookup global pointer

Quoting Maxime Ripard (2020-02-24 01:06:14)
> The pllb_arm_lookup pointer in the struct raspberrypi_clk is not used for
> anything but to store the returned pointer to clkdev_hw_create, and is not
> used anywhere else in the driver.
>
> Let's remove that global pointer from the structure.
>
> Cc: Michael Turquette <[email protected]>
> Cc: Stephen Boyd <[email protected]>
> Cc: [email protected]
> Signed-off-by: Maxime Ripard <[email protected]>
> ---

Reviewed-by: Stephen Boyd <[email protected]>