* Re: [PATCH v6 1/5] irqchip/aspeed-i2c-ic: binding docs for Aspeed I2C Interrupt Controller
From: Brendan Higgins @ 2017-03-29 20:51 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Wolfram Sang, Rob Herring, Mark Rutland, Thomas Gleixner,
Jason Cooper, Marc Zyngier, Joel Stanley, Vladimir Zapolskiy,
Kachalov Anton, Cédric Le Goater, linux-i2c, devicetree,
Linux Kernel Mailing List, OpenBMC Maillist
In-Reply-To: <1490789505.3177.184.camel@kernel.crashing.org>
> Regarding the other comment about the "fast mode", my main worry here
> is that somebody might come up with a 2Mhz capable device, we'll hit
> your 1Mhz test, enable fast mode, and shoot it with 3.4Mhz which it
> might not be happy at all about...
>
> I think the cut-off for switching to the "fast" mode should basically
> be the fast speed mode frequency (which isn't clear from the spec but
> seems to be 3.4Mhz). Otherwise people will end up with higher speeds
> than what they asked for and that's bad.
Ah, but see the documentation only says that high speed mode sets the
Base Clock divisor to zero; is does not say anything about tCKHigh or
tCKLow (clk_high and clk_low in my code respectively), which are the
only parameters which are manipulated for speeds greater than or equal
to 1.5MHz since:
# I forgot the "APB_freq /" part in the comment on my
aspeed_i2c_get_clk_reg_val(...)
# My function still does the computation correctly, I just forgot this
in the comment.
SCL_freq = APB_freq / (1 << base_clk) * (clk_high + 1 + clk_low + 1)
so if base_clk = 0, clk_high = 15, clk_low = 15, APB_freq = 50MHz
SCL_freq = APB_freq / (1 << base_clk) * (clk_high + 1 + clk_low + 1)
= 50000000 / (1 << 0) * (15 + 1 + 15 + 1)
= 50000000 / 32
= 1562500Hz
= ~1.5MHz
so maybe instead of setting a hard limit like I did, maybe the best
thing is to just check and see what the base_clk gets set to and if it
gets set to zero, we turn on high speed mode. What do you think?
Cheers
^ permalink raw reply
* Re: [PATCH v1 0/8] clk: meson: gxbb: more clock controller update for audio support
From: Michael Turquette @ 2017-03-29 20:42 UTC (permalink / raw)
To: Stephen Boyd, Kevin Hilman, Carlo Caione
Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel, devicetree,
narmstrong
In-Reply-To: <20170328144605.25278-1-jbrunet@baylibre.com>
Hi Jerome,
Adding Neil Armstong to Cc.
Quoting Jerome Brunet (2017-03-28 07:45:57)
> The patchset is the 2nd round of update to the meson gxbb clock controller
> to add initial audio support. The patchset is based on clk-next.
>
> There is not much out of the ordinary here (adding new clocks and exposing
> them) except maybe for 2 patches:
> Patch #2: Adds a safety check while registering clocks to protect against
> holes in clk_hw_onecell_data, if it ever happens. Same thing is
> done for the meson8b clock controller.
> Patch #3: Adds a new clock divider driver to implement the necessary
> policy for the i2s master clock (see patch changelog)
>
> This patchset has been test on the gxbb p200 and gxl p230.
First off, this series looks fine to me. Please add,
Acked-by: Michael Turquette <mturquette@baylibre.com>
Secondly, it seems the AmLogic clock drivers have mostly calmed down and
things are in the "add new clocks when we need them" phase, which is
nice. Since you and Neil are doing a lot of this work, might I suggest
that you both start collecting patches for the AmLogic/meson clock
drivers begin submitting pull requests to Stephen and myself?
As usual the rules are the same as always: all patches in the PR must
first be posted for review on the list. PRs should correspond to signed
tags. Stephen and I might ignore PRs sent after -rc4, and will
definitely ignore PRs sent after -rc6 since we want some stabilization
time before the merge window. Base your branch on -rc1, not on clk-next.
Also feel free to submit a patch to MAINTAINERS with either one or both
of you maintaining the meson clk stuff, assuming that you're OK to
review all of those patches and collect them into a PR.
Thoughts?
If it sounds good to you then I suggest grabbing the clk-meson branch
from the clk tree and using that as a baseline for your first PR. In the
future you'll just Linus' -rc1, but I have already created a branch for
this cycle. You can apply these 8 patches with my Ack and send a PR by
-rc6 (possibly with other stuff collected from Martin, etc).
Thanks,
Mike
>
> Jerome Brunet (8):
> dt-bindings: clock: gxbb: expose spdif clock gates
> clk: meson: gxbb: protect against holes in the onecell_data array
> clk: meson: add audio clock divider support
> clk: meson: gxbb: add cts_amclk
> clk: meson: gxbb: add cts_mclk_i958
> clk: meson: gxbb: add cts_i958 clock
> dt-bindings: clock: gxbb: expose i2s master clock
> dt-bindings: clock: gxbb: expose spdif master clock
>
> drivers/clk/meson/Makefile | 2 +-
> drivers/clk/meson/clk-audio-divider.c | 149 ++++++++++++++++++++++++++++++++++
> drivers/clk/meson/clkc.h | 10 +++
> drivers/clk/meson/gxbb.c | 144 ++++++++++++++++++++++++++++++++
> drivers/clk/meson/gxbb.h | 13 ++-
> include/dt-bindings/clock/gxbb-clkc.h | 5 ++
> 6 files changed, 319 insertions(+), 4 deletions(-)
> create mode 100644 drivers/clk/meson/clk-audio-divider.c
>
> --
> 2.9.3
>
^ permalink raw reply
* Re: [PATCH v2,1/3] meson_uart: expose CLKID_UARTx
From: Kevin Hilman @ 2017-03-29 20:21 UTC (permalink / raw)
To: Martin Blumenstingl
Cc: devicetree, mturquette, sboyd, linux-kernel, Helmut Klein,
linux-amlogic, linux-clk, linux-arm-kernel, Jerome Brunet
In-Reply-To: <CAFBinCDF29+kQpedsJPqRy6fztWrj91Qi6tCno_2S6UCkhW7XQ@mail.gmail.com>
Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
[...]
> for Helmut this would mean that instead of dropping this patch (or
> dropping CLKID_UART1 and CLKID_UART2 from this patch) he would rather
> have to *add* another patch (for meson-gxbb.dtsi and meson-gxl.dtsi)
> which passes the core clocks to the corresponding UART controllers
> (similar to the CLKID_SD_EMMC_ clocks).
Yes, this is what I would like to see.
If a new CLKID is exposed, I want to see the users of it at the same
time.
Kevin
^ permalink raw reply
* Re: [PATCH v6 2/5] irqchip/aspeed-i2c-ic: Add I2C IRQ controller for Aspeed
From: Brendan Higgins @ 2017-03-29 20:16 UTC (permalink / raw)
To: Joel Stanley
Cc: Wolfram Sang, Rob Herring, Mark Rutland, Thomas Gleixner,
Jason Cooper, Marc Zyngier, Vladimir Zapolskiy, Kachalov Anton,
Cédric Le Goater, linux-i2c, devicetree,
Linux Kernel Mailing List, OpenBMC Maillist,
Benjamin Herrenschmidt
In-Reply-To: <CACPK8XdYNi2mna=aBbYvMroujLOPbVkPdU-DeYGrevjRBjHodQ@mail.gmail.com>
> Nit: Make this aspeed-i2c-domain to make this consistent with the
> other Aspeed drivers in the kernel tree.
>
> Could this irq code be embedded in the i2c driver? We took a similar
> approach for the Aspeed GPIO driver, which has a similar IRQ structure
> of one hardware IRQ that tells the driver to check status registers
> for the precise irq source. The upside being all of the i2c code is in
> the same place in the kernel tree.
In the previous version of the patch, this code was embedded in the
I2C driver as the "struct aspeed_i2c_controller;" I really did not
change anything about it other than rename some stuff and change the
init method to match what irqchip code wants. I pulled it out into a
separate driver because I was asked to by Vladimir; nevertheless, it
does turn the I2C driver into a normal platforms driver, which is
nice. Another benefit: if we put our dummy irqchip code in with the
other irqchips, it makes it easier for the irqchip people to recognize
when we are reusing the same patterns; for example, I would not at all
be surprised if there are other dummy irqchips which have the same
exact map(...) operation (I looked and did not see anything), but it
is quite possibly something that other people want to do. If we put
this stuff in drivers/irqchip, it is more likely that the irqchip
people would recognize this as a common use case. I do not think
either of these reasons I provided are particularly compelling, but I
do not think the reasons to move it out are particularly compelling
either (unless we decide we do not want make our own irq_domain).
Cheers
^ permalink raw reply
* Re: [PATCH v3 0/3] mtd: nand: Rework/cleanup the Atmel NAND driver
From: Boris Brezillon @ 2017-03-29 20:05 UTC (permalink / raw)
To: Boris Brezillon, Richard Weinberger, linux-mtd, Nicolas Ferre,
Alexandre Belloni, Haavard Skinnemoen, Hans-Christian Egtvedt,
linux-kernel, Wenyou Yang, Josh Wu
Cc: Mark Rutland, devicetree, Pawel Moll, Marek Vasut, Ian Campbell,
Masahiro Yamada, Andy Shevchenko, Rob Herring, Kumar Gala,
Cyrille Pitchen, Brian Norris, David Woodhouse, linux-arm-kernel
In-Reply-To: <1489651362-17077-1-git-send-email-boris.brezillon@free-electrons.com>
On Thu, 16 Mar 2017 09:02:39 +0100
Boris Brezillon <boris.brezillon@free-electrons.com> wrote:
> This is a complete rewrite of the driver whose main purpose is to
> support the new DT representation where the NAND controller node is now
> really visible in the DT and appears under the EBI bus. With this new
> representation, we can add other devices under the EBI bus without
> risking pinmuxing conflicts (the NAND controller is under the EBI
> bus logic and as such, share some of its pins with other devices
> connected on this bus).
>
> Even though the goal of this rework was not necessarily to add new
> features, the new driver has been designed with this in mind. With a
> clearer separation between the different blocks and different IP
> revisions, adding new functionalities should be easier (we already
> have plans to support SMC timing configuration so that we no longer
> have to rely on the configuration done by the bootloader/bootstrap).
>
> Also note that we no longer have a custom ->cmdfunc() implementation,
> which means we can now benefit from new features added in the core
> implementation for free (support for new NAND operations for example).
>
> The last thing that we gain with this rework is support for multi-chips
> and multi-dies chips, thanks to the clean NAND controller <-> NAND
> devices representation.
>
> This new driver has been tested on several platforms (at91sam9261,
> at91sam9g45, at91sam9x5, sama5d3 and sama5d4) to make sure it did not
> introduce regressions, and it's worth mentioning that old bindings are
> still supported (which partly explain the positive diffstat).
Applied the whole series.
>
> Regards,
>
> Boris
>
> Changes since v2:
> - add error messages when the NFC reports an error
> - drop AVR32 compat code
> - add acks
> - minor coding style fixes
>
> Changes since v1:
> - change function/structure prefixes (asked by Nicolas)
> - drop applied patches
> - use new GPIO helpers
> - set ->chip_delay to 40 as done in the old driver (reported by Nicolas)
> - rework read_page to improve perfs
> - add a better commit message to patch 2
>
> Boris Brezillon (3):
> mtd: nand: Cleanup/rework the atmel_nand driver
> mtd: nand: atmel: Document the new DT bindings
> mtd: nand: Remove unused chip->write_page() hook
>
> .../devicetree/bindings/mtd/atmel-nand.txt | 107 +-
> MAINTAINERS | 2 +-
> drivers/mtd/nand/Kconfig | 6 +-
> drivers/mtd/nand/Makefile | 2 +-
> drivers/mtd/nand/atmel/Makefile | 4 +
> drivers/mtd/nand/atmel/nand-controller.c | 2198 +++++++++++++++++
> drivers/mtd/nand/atmel/pmecc.c | 1020 ++++++++
> drivers/mtd/nand/atmel/pmecc.h | 73 +
> drivers/mtd/nand/atmel_nand.c | 2479 --------------------
> drivers/mtd/nand/atmel_nand_ecc.h | 163 --
> drivers/mtd/nand/atmel_nand_nfc.h | 103 -
> drivers/mtd/nand/nand_base.c | 12 +-
> include/linux/mtd/nand.h | 4 -
> 13 files changed, 3411 insertions(+), 2762 deletions(-)
> create mode 100644 drivers/mtd/nand/atmel/Makefile
> create mode 100644 drivers/mtd/nand/atmel/nand-controller.c
> create mode 100644 drivers/mtd/nand/atmel/pmecc.c
> create mode 100644 drivers/mtd/nand/atmel/pmecc.h
> delete mode 100644 drivers/mtd/nand/atmel_nand.c
> delete mode 100644 drivers/mtd/nand/atmel_nand_ecc.h
> delete mode 100644 drivers/mtd/nand/atmel_nand_nfc.h
>
^ permalink raw reply
* [PATCH v3 11/11] [DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
A 480x272 QiaoDian QD43003C0-40-7LED panel is available from Lichee Pi.
This commit connects this panel to Lichee Pi Zero.
Lichee Pi also provides a 800x480 panel without accurate model number,
so do not merge this patch. It will finally come as device tree overlay.
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 +++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
index 387fc2aa546d..7ae72bf63cd0 100644
--- a/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts
@@ -75,6 +75,28 @@
gpios = <&pio 6 2 GPIO_ACTIVE_LOW>; /* PG2 */
};
};
+
+ panel: panel {
+ compatible = "qiaodian,qd43003c0-40", "simple-panel";
+ enable-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* Should be backlight */
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel_input: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_out_lcd>;
+ };
+ };
+ };
+};
+
+&de {
+ status = "okay";
};
&mmc0 {
@@ -86,6 +108,20 @@
status = "okay";
};
+&tcon0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_rgb666_pins>;
+ status = "okay";
+
+};
+
+&tcon0_out {
+ tcon0_out_lcd: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&panel_input>;
+ };
+};
+
&uart0 {
pinctrl-0 = <&uart0_pins_a>;
pinctrl-names = "default";
--
2.12.0
^ permalink raw reply related
* [PATCH v3 10/11] ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Allwinner V3s SoC features a set of pins that have functionality of RGB
LCD, the pins are at different pin ban than other SoCs.
Add pinctrl node for them.
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
arch/arm/boot/dts/sun8i-v3s.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index ae23746731a8..ac783a8a4fd3 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -297,6 +297,15 @@
function = "i2c0";
};
+ lcd_rgb666_pins: lcd_rgb666@0 {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9",
+ "PE10", "PE11", "PE12", "PE13", "PE14",
+ "PE15", "PE16", "PE17", "PE18", "PE19",
+ "PE23", "PE24";
+ function = "lcd";
+ };
+
uart0_pins_a: uart0@0 {
pins = "PB8", "PB9";
function = "uart0";
--
2.12.0
^ permalink raw reply related
* [PATCH v3 09/11] ARM: dts: sun8i: add DE2 nodes for V3s SoC
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Allwinner V3s SoC features a "Display Engine 2.0" with only one TCON
which have RGB LCD output.
Add device nodes for it as well as the TCON.
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v3:
- Change the size of de2_clocks regs according to the binding example.
arch/arm/boot/dts/sun8i-v3s.dtsi | 87 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi
index 71075969e5e6..ae23746731a8 100644
--- a/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ b/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -41,6 +41,10 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
/ {
#address-cells = <1>;
@@ -59,6 +63,12 @@
};
};
+ de: display-engine {
+ compatible = "allwinner,sun8i-v3s-display-engine";
+ allwinner,pipelines = <&de2_mixer0>;
+ status = "disabled";
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
@@ -93,6 +103,83 @@
#size-cells = <1>;
ranges;
+ de2_clocks: clock@01000000 {
+ compatible = "allwinner,sun50i-h5-de2-clk";
+ reg = <0x01000000 0x100000>;
+ clocks = <&ccu CLK_DE>,
+ <&ccu CLK_BUS_DE>;
+ clock-names = "mod",
+ "bus";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ de2_mixer0: mixer@01100000 {
+ compatible = "allwinner,sun8i-v3s-de2-mixer";
+ reg = <0x01100000 0x100000>;
+ clocks = <&de2_clocks CLK_MIXER0>,
+ <&de2_clocks CLK_BUS_MIXER0>;
+ clock-names = "mod",
+ "bus";
+ resets = <&de2_clocks RST_MIXER0>;
+ assigned-clocks = <&de2_clocks CLK_MIXER0>;
+ assigned-clock-rates = <150000000>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ mixer0_out_tcon0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_in_mixer0>;
+ };
+ };
+ };
+ };
+
+ tcon0: lcd-controller@01c0c000 {
+ compatible = "allwinner,sun8i-v3s-tcon";
+ reg = <0x01c0c000 0x1000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON0>,
+ <&ccu CLK_TCON0>;
+ clock-names = "ahb",
+ "tcon-ch0";
+ clock-output-names = "tcon-pixel-clock";
+ resets = <&ccu RST_BUS_TCON0>;
+ reset-names = "lcd";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon0_in_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&mixer0_out_tcon0>;
+ };
+ };
+
+ tcon0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
+
mmc0: mmc@01c0f000 {
compatible = "allwinner,sun7i-a20-mmc";
reg = <0x01c0f000 0x1000>;
--
2.12.0
^ permalink raw reply related
* [PATCH v3 08/11] drm/sun4i: tcon: add support for V3s TCON
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Allwinner V3s SoC features a TCON without channel 1.
Add support for it.
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 68c0b754cdb5..736b28e47281 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -176,7 +176,8 @@ static bool sun4i_drv_node_is_tcon(struct device_node *node)
return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
- of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
+ of_device_is_compatible(node, "allwinner,sun8i-a33-tcon") ||
+ of_device_is_compatible(node, "allwinner,sun8i-v3s-tcon");
}
static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 2f330e4e2ead..1a710d7d6a74 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -613,11 +613,16 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
/* nothing is supported */
};
+static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
+ /* nothing is supported */
+};
+
static const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
+ { .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
{ }
};
MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
--
2.12.0
^ permalink raw reply related
* [PATCH v3 07/11] drm/sun4i: Add compatible string for V3s display engine
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
Allwinner V3s features the new "Display Engine 2.0", which can now also
be driven with our subdrivers in sun4i-drm.
Add the compatible string for in sun4i_drv.c, in order to make the
display engine and its components probed.
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Patch splited in v3.
drivers/gpu/drm/sun4i/sun4i_drv.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 8ddd72cd5873..68c0b754cdb5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -294,6 +294,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun6i-a31-display-engine" },
{ .compatible = "allwinner,sun6i-a31s-display-engine" },
{ .compatible = "allwinner,sun8i-a33-display-engine" },
+ { .compatible = "allwinner,sun8i-v3s-display-engine" },
{ }
};
MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
--
2.12.0
^ permalink raw reply related
* [PATCH v3 06/11] drm/sun4i: add support for Allwinner DE2 mixers
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
Allwinner have a new "Display Engine 2.0" in their new SoCs, which comes
with mixers to do graphic processing and feed data to TCON, like the old
backends and frontends.
Add support for the mixer on Allwinner V3s SoC; it's the simplest one.
Currently a lot of functions are still missing -- more investigations
are needed to gain enough information for them.
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Refactored patch in v3.
drivers/gpu/drm/sun4i/Kconfig | 10 +
drivers/gpu/drm/sun4i/Makefile | 4 +
drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++++++++
drivers/gpu/drm/sun4i/sun8i_layer.h | 35 ++++
drivers/gpu/drm/sun4i/sun8i_mixer.c | 386 ++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/sun4i/sun8i_mixer.h | 131 ++++++++++++
6 files changed, 722 insertions(+)
create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 5a8227f37cc4..15557484520d 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -22,3 +22,13 @@ config DRM_SUN4I_BACKEND
original Allwinner Display Engine, which has a backend to
do some alpha blending and feed graphics to TCON. If M is
selected the module will be called sun4i-backend.
+
+config DRM_SUN4I_SUN8I_MIXER
+ tristate "Support for Allwinner Display Engine 2.0 Mixer"
+ depends on DRM_SUN4I
+ default MACH_SUN8I
+ help
+ Choose this option if you have an Allwinner SoC with the
+ Allwinner Display Engine 2.0, which has a mixer to do some
+ graphics mixture and feed graphics to TCON, If M is
+ selected the module will be called sun8i-mixer.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 1db1068b9be1..7625c2dad1bb 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -9,7 +9,11 @@ sun4i-tcon-y += sun4i_crtc.o
sun4i-backend-y += sun4i_layer.o
sun4i-backend-y += sun4i_backend.o
+sun8i-mixer-y += sun8i_layer.o
+sun8i-mixer-y += sun8i_mixer.o
+
obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o
obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o
+obj-$(CONFIG_DRM_SUN4I_SUN8I_MIXER) += sun8i-mixer.o
obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.c b/drivers/gpu/drm/sun4i/sun8i_layer.c
new file mode 100644
index 000000000000..5cc4a7f8a7ae
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * Based on sun4i_layer.h, which is:
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_crtc.h"
+#include "sun8i_layer.h"
+#include "sun8i_mixer.h"
+#include "sunxi_layer.h"
+
+struct sun8i_plane_desc {
+ enum drm_plane_type type;
+ const uint32_t *formats;
+ uint32_t nformats;
+};
+
+static int sun8i_mixer_layer_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ return 0;
+}
+
+static void sun8i_mixer_layer_atomic_disable(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+ struct sun8i_mixer *mixer = layer->mixer;
+
+ sun8i_mixer_layer_enable(mixer, layer->id, false);
+}
+
+static void sun8i_mixer_layer_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct sun8i_layer *layer = plane_to_sun8i_layer(plane);
+ struct sun8i_mixer *mixer = layer->mixer;
+
+ sun8i_mixer_update_layer_coord(mixer, layer->id, plane);
+ sun8i_mixer_update_layer_formats(mixer, layer->id, plane);
+ sun8i_mixer_update_layer_buffer(mixer, layer->id, plane);
+ sun8i_mixer_layer_enable(mixer, layer->id, true);
+}
+
+static struct drm_plane_helper_funcs sun8i_mixer_layer_helper_funcs = {
+ .atomic_check = sun8i_mixer_layer_atomic_check,
+ .atomic_disable = sun8i_mixer_layer_atomic_disable,
+ .atomic_update = sun8i_mixer_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun8i_mixer_layer_funcs = {
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .destroy = drm_plane_cleanup,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .reset = drm_atomic_helper_plane_reset,
+ .update_plane = drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun8i_mixer_layer_formats[] = {
+ DRM_FORMAT_RGB888,
+ DRM_FORMAT_XRGB8888,
+};
+
+static const struct sun8i_plane_desc sun8i_mixer_planes[] = {
+ {
+ .type = DRM_PLANE_TYPE_PRIMARY,
+ .formats = sun8i_mixer_layer_formats,
+ .nformats = ARRAY_SIZE(sun8i_mixer_layer_formats),
+ },
+};
+
+static struct drm_plane *sun8i_layer_get_plane(void *layer)
+{
+ struct sun8i_layer *sun8i_layer = layer;
+
+ return &sun8i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+ .get_plane = sun8i_layer_get_plane,
+};
+
+static struct sun8i_layer *sun8i_layer_init_one(struct drm_device *drm,
+ struct sun8i_mixer *mixer,
+ const struct sun8i_plane_desc *plane)
+{
+ struct sun8i_layer *layer;
+ int ret;
+
+ layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+ if (!layer)
+ return ERR_PTR(-ENOMEM);
+
+ /* possible crtcs are set later */
+ ret = drm_universal_plane_init(drm, &layer->plane, 0,
+ &sun8i_mixer_layer_funcs,
+ plane->formats, plane->nformats,
+ plane->type, NULL);
+ if (ret) {
+ dev_err(drm->dev, "Couldn't initialize layer\n");
+ return ERR_PTR(ret);
+ }
+
+ drm_plane_helper_add(&layer->plane,
+ &sun8i_mixer_layer_helper_funcs);
+ layer->mixer = mixer;
+
+ return layer;
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
+{
+ struct sun8i_layer **layers;
+ struct sun8i_mixer *mixer = crtc->mixer;
+ int i;
+
+ layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun8i_mixer_planes) + 1,
+ sizeof(*layers), GFP_KERNEL);
+ if (!layers)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < ARRAY_SIZE(sun8i_mixer_planes); i++) {
+ const struct sun8i_plane_desc *plane = &sun8i_mixer_planes[i];
+ struct sun8i_layer *layer;
+
+ layer = sun8i_layer_init_one(drm, mixer, plane);
+ if (IS_ERR(layer)) {
+ dev_err(drm->dev, "Couldn't initialize %s plane\n",
+ i ? "overlay" : "primary");
+ return ERR_CAST(layer);
+ };
+
+ layer->id = i;
+ layers[i] = layer;
+ };
+
+ /* Assign layer ops to the CRTC */
+ crtc->layer_ops = &layer_ops;
+
+ return (void **)layers;
+}
diff --git a/drivers/gpu/drm/sun4i/sun8i_layer.h b/drivers/gpu/drm/sun4i/sun8i_layer.h
new file mode 100644
index 000000000000..9f145ce842f2
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_layer.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * Based on sun4i_layer.h, which is:
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_LAYER_H_
+#define _SUN8I_LAYER_H_
+
+struct sun4i_crtc;
+
+struct sun8i_layer {
+ struct drm_plane plane;
+ struct sun4i_drv *drv;
+ struct sun8i_mixer *mixer;
+ int id;
+};
+
+static inline struct sun8i_layer *
+plane_to_sun8i_layer(struct drm_plane *plane)
+{
+ return container_of(plane, struct sun8i_layer, plane);
+}
+
+void **sun8i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
+#endif /* _SUN8I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
new file mode 100644
index 000000000000..1399d1a6c678
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * Based on sun4i_backend.c, which is:
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+#include <linux/of_device.h>
+
+#include "sun4i_drv.h"
+#include "sun8i_mixer.h"
+#include "sun8i_layer.h"
+#include "sunxi_mixer.h"
+
+void sun8i_mixer_commit(void *mixer)
+{
+ struct sun8i_mixer *sun8i_mixer = mixer;
+
+ DRM_DEBUG_DRIVER("Committing changes\n");
+
+ regmap_write(sun8i_mixer->regs, SUN8I_MIXER_GLOBAL_DBUFF,
+ SUN8I_MIXER_GLOBAL_DBUFF_ENABLE);
+}
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+ int layer, bool enable)
+{
+ u32 val;
+ /* Currently the first UI channel is used */
+ int chan = mixer->cfg->vi_num;
+
+ DRM_DEBUG_DRIVER("Enabling layer %d in channel %d\n", layer, chan);
+
+ if (enable)
+ val = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN;
+ else
+ val = 0;
+
+ regmap_update_bits(mixer->regs,
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+
+ /* Set the alpha configuration */
+ regmap_update_bits(mixer->regs,
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK,
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF);
+ regmap_update_bits(mixer->regs,
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK,
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF);
+}
+EXPORT_SYMBOL(sun8i_mixer_layer_enable);
+
+static int sun8i_mixer_drm_format_to_layer(struct drm_plane *plane,
+ u32 format, u32 *mode)
+{
+ switch (format) {
+ case DRM_FORMAT_XRGB8888:
+ *mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888;
+ break;
+
+ case DRM_FORMAT_RGB888:
+ *mode = SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+ int layer, struct drm_plane *plane)
+{
+ struct drm_plane_state *state = plane->state;
+ struct drm_framebuffer *fb = state->fb;
+ /* Currently the first UI channel is used */
+ int chan = mixer->cfg->vi_num;
+ int i;
+
+ DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+ if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+ DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+ state->crtc_w, state->crtc_h);
+ regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_SIZE,
+ SUN8I_MIXER_SIZE(state->crtc_w,
+ state->crtc_h));
+ DRM_DEBUG_DRIVER("Updating blender size\n");
+ for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+ regmap_write(mixer->regs,
+ SUN8I_MIXER_BLEND_ATTR_INSIZE(i),
+ SUN8I_MIXER_SIZE(state->crtc_w,
+ state->crtc_h));
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_OUTSIZE,
+ SUN8I_MIXER_SIZE(state->crtc_w,
+ state->crtc_h));
+ DRM_DEBUG_DRIVER("Updating channel size\n");
+ regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_OVL_SIZE(chan),
+ SUN8I_MIXER_SIZE(state->crtc_w,
+ state->crtc_h));
+ }
+
+ /* Set the line width */
+ DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
+ regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_PITCH(chan, layer),
+ fb->pitches[0]);
+
+ /* Set height and width */
+ DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+ state->crtc_w, state->crtc_h);
+ regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_SIZE(chan, layer),
+ SUN8I_MIXER_SIZE(state->crtc_w, state->crtc_h));
+
+ /* Set base coordinates */
+ DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+ state->crtc_x, state->crtc_y);
+ regmap_write(mixer->regs, SUN8I_MIXER_CHAN_UI_LAYER_COORD(chan, layer),
+ SUN8I_MIXER_COORD(state->crtc_x, state->crtc_y));
+
+ return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_coord);
+
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+ int layer, struct drm_plane *plane)
+{
+ struct drm_plane_state *state = plane->state;
+ struct drm_framebuffer *fb = state->fb;
+ bool interlaced = false;
+ u32 val;
+ /* Currently the first UI channel is used */
+ int chan = mixer->cfg->vi_num;
+ int ret;
+
+ if (plane->state->crtc)
+ interlaced = plane->state->crtc->state->adjusted_mode.flags
+ & DRM_MODE_FLAG_INTERLACE;
+
+ regmap_update_bits(mixer->regs, SUN8I_MIXER_BLEND_OUTCTL,
+ SUN8I_MIXER_BLEND_OUTCTL_INTERLACED,
+ interlaced ?
+ SUN8I_MIXER_BLEND_OUTCTL_INTERLACED : 0);
+
+ DRM_DEBUG_DRIVER("Switching display mixer interlaced mode %s\n",
+ interlaced ? "on" : "off");
+
+ ret = sun8i_mixer_drm_format_to_layer(plane, fb->format->format,
+ &val);
+ if (ret) {
+ DRM_DEBUG_DRIVER("Invalid format\n");
+ return ret;
+ }
+
+ regmap_update_bits(mixer->regs,
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR(chan, layer),
+ SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK, val);
+
+ return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_formats);
+
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+ int layer, struct drm_plane *plane)
+{
+ struct drm_plane_state *state = plane->state;
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_cma_object *gem;
+ dma_addr_t paddr;
+ uint32_t paddr_u32;
+ /* Currently the first UI channel is used */
+ int chan = mixer->cfg->vi_num;
+ int bpp;
+
+ /* Get the physical address of the buffer in memory */
+ gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+ DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+ /* Compute the start of the displayed memory */
+ bpp = fb->format->cpp[0];
+ paddr = gem->paddr + fb->offsets[0];
+ paddr += (state->src_x >> 16) * bpp;
+ paddr += (state->src_y >> 16) * fb->pitches[0];
+
+ DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+ paddr_u32 = (uint32_t) paddr;
+
+ regmap_write(mixer->regs,
+ SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(chan, layer),
+ paddr_u32);
+
+ return 0;
+}
+EXPORT_SYMBOL(sun8i_mixer_update_layer_buffer);
+
+static const struct sunxi_mixer_ops sun8i_mixer_mixer_ops = {
+ .commit = sun8i_mixer_commit,
+ .layers_init = sun8i_layers_init,
+};
+
+static struct regmap_config sun8i_mixer_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0xbffc, /* guessed */
+};
+
+static int sun8i_mixer_bind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct drm_device *drm = data;
+ struct sun4i_drv *drv = drm->dev_private;
+ struct sun8i_mixer *mixer;
+ struct resource *res;
+ void __iomem *regs;
+ int i, ret;
+
+ mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
+ if (!mixer)
+ return -ENOMEM;
+ dev_set_drvdata(dev, mixer);
+ drv->mixer = mixer;
+ drv->mixer_ops = &sun8i_mixer_mixer_ops;
+
+ mixer->cfg = of_device_get_match_data(dev);
+ if (!mixer->cfg)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ mixer->regs = devm_regmap_init_mmio(dev, regs,
+ &sun8i_mixer_regmap_config);
+ if (IS_ERR(mixer->regs)) {
+ dev_err(dev, "Couldn't create the mixer regmap\n");
+ return PTR_ERR(mixer->regs);
+ }
+
+ mixer->reset = devm_reset_control_get(dev, NULL);
+ if (IS_ERR(mixer->reset)) {
+ dev_err(dev, "Couldn't get our reset line\n");
+ return PTR_ERR(mixer->reset);
+ }
+
+ ret = reset_control_deassert(mixer->reset);
+ if (ret) {
+ dev_err(dev, "Couldn't deassert our reset line\n");
+ return ret;
+ }
+
+ mixer->bus_clk = devm_clk_get(dev, "bus");
+ if (IS_ERR(mixer->bus_clk)) {
+ dev_err(dev, "Couldn't get the mixer bus clock\n");
+ ret = PTR_ERR(mixer->bus_clk);
+ goto err_assert_reset;
+ }
+ clk_prepare_enable(mixer->bus_clk);
+
+ mixer->mod_clk = devm_clk_get(dev, "mod");
+ if (IS_ERR(mixer->mod_clk)) {
+ dev_err(dev, "Couldn't get the mixer module clock\n");
+ ret = PTR_ERR(mixer->mod_clk);
+ goto err_disable_bus_clk;
+ }
+ clk_prepare_enable(mixer->mod_clk);
+
+ /* Reset the registers */
+ for (i = 0x0; i < 0x20000; i += 4)
+ regmap_write(mixer->regs, i, 0);
+
+ /* Enable the mixer */
+ regmap_write(mixer->regs, SUN8I_MIXER_GLOBAL_CTL,
+ SUN8I_MIXER_GLOBAL_CTL_RT_EN);
+
+ /* Initialize blender */
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_FCOLOR_CTL,
+ SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF);
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_PREMULTIPLY,
+ SUN8I_MIXER_BLEND_PREMULTIPLY_DEF);
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_BKCOLOR,
+ SUN8I_MIXER_BLEND_BKCOLOR_DEF);
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(0),
+ SUN8I_MIXER_BLEND_MODE_DEF);
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_MODE(1),
+ SUN8I_MIXER_BLEND_MODE_DEF);
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_CK_CTL,
+ SUN8I_MIXER_BLEND_CK_CTL_DEF);
+
+ for (i = 0; i < SUN8I_MIXER_MAX_CHAN_COUNT; i++)
+ regmap_write(mixer->regs,
+ SUN8I_MIXER_BLEND_ATTR_FCOLOR(i),
+ SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF);
+
+ /* Select the first UI channel */
+ DRM_DEBUG_DRIVER("Selecting channel %d (first UI channel)\n",
+ mixer->cfg->vi_num);
+ regmap_write(mixer->regs, SUN8I_MIXER_BLEND_ROUTE,
+ mixer->cfg->vi_num);
+
+ return 0;
+
+ clk_disable_unprepare(mixer->mod_clk);
+err_disable_bus_clk:
+ clk_disable_unprepare(mixer->bus_clk);
+err_assert_reset:
+ reset_control_assert(mixer->reset);
+ return ret;
+}
+
+static void sun8i_mixer_unbind(struct device *dev, struct device *master,
+ void *data)
+{
+ struct sun8i_mixer *mixer = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(mixer->mod_clk);
+ clk_disable_unprepare(mixer->bus_clk);
+ reset_control_assert(mixer->reset);
+}
+
+static const struct component_ops sun8i_mixer_ops = {
+ .bind = sun8i_mixer_bind,
+ .unbind = sun8i_mixer_unbind,
+};
+
+static int sun8i_mixer_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &sun8i_mixer_ops);
+}
+
+static int sun8i_mixer_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &sun8i_mixer_ops);
+
+ return 0;
+}
+
+static const struct sun8i_mixer_cfg sun8i_v3s_mixer_cfg = {
+ .vi_num = 2,
+ .ui_num = 1,
+};
+
+static const struct of_device_id sun8i_mixer_of_table[] = {
+ {
+ .compatible = "allwinner,sun8i-v3s-de2-mixer",
+ .data = &sun8i_v3s_mixer_cfg,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
+
+static struct platform_driver sun8i_mixer_platform_driver = {
+ .probe = sun8i_mixer_probe,
+ .remove = sun8i_mixer_remove,
+ .driver = {
+ .name = "sun8i-mixer",
+ .of_match_table = sun8i_mixer_of_table,
+ },
+};
+module_platform_driver(sun8i_mixer_platform_driver);
+
+MODULE_AUTHOR("Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>");
+MODULE_DESCRIPTION("Allwinner DE2 Mixer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
new file mode 100644
index 000000000000..7b3b9d747d7d
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN8I_MIXER_H_
+#define _SUN8I_MIXER_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_layer.h"
+
+#define SUN8I_MIXER_MAX_CHAN_COUNT 4
+
+#define SUN8I_MIXER_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1))
+#define SUN8I_MIXER_COORD(x, y) ((y) << 16 | (x))
+
+#define SUN8I_MIXER_GLOBAL_CTL 0x0
+#define SUN8I_MIXER_GLOBAL_STATUS 0x4
+#define SUN8I_MIXER_GLOBAL_DBUFF 0x8
+#define SUN8I_MIXER_GLOBAL_SIZE 0xc
+
+#define SUN8I_MIXER_GLOBAL_CTL_RT_EN 0x1
+
+#define SUN8I_MIXER_GLOBAL_DBUFF_ENABLE 0x1
+
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL 0x1000
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR(x) (0x1004 + 0x10 * (x) + 0x0)
+#define SUN8I_MIXER_BLEND_ATTR_INSIZE(x) (0x1004 + 0x10 * (x) + 0x4)
+#define SUN8I_MIXER_BLEND_ATTR_OFFSET(x) (0x1004 + 0x10 * (x) + 0x8)
+#define SUN8I_MIXER_BLEND_ROUTE 0x1080
+#define SUN8I_MIXER_BLEND_PREMULTIPLY 0x1084
+#define SUN8I_MIXER_BLEND_BKCOLOR 0x1088
+#define SUN8I_MIXER_BLEND_OUTSIZE 0x108c
+#define SUN8I_MIXER_BLEND_MODE(x) (0x1090 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_CTL 0x10b0
+#define SUN8I_MIXER_BLEND_CK_CFG 0x10b4
+#define SUN8I_MIXER_BLEND_CK_MAX(x) (0x10c0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_CK_MIN(x) (0x10e0 + 0x04 * (x))
+#define SUN8I_MIXER_BLEND_OUTCTL 0x10fc
+
+/* The following numbers are some still unknown magic numbers */
+#define SUN8I_MIXER_BLEND_ATTR_FCOLOR_DEF 0xff000000
+#define SUN8I_MIXER_BLEND_FCOLOR_CTL_DEF 0x00000101
+#define SUN8I_MIXER_BLEND_PREMULTIPLY_DEF 0x0
+#define SUN8I_MIXER_BLEND_BKCOLOR_DEF 0xff000000
+#define SUN8I_MIXER_BLEND_MODE_DEF 0x03010301
+#define SUN8I_MIXER_BLEND_CK_CTL_DEF 0x0
+
+#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED BIT(1)
+
+/*
+ * VI channels are not used now, but the support of them may be introduced in
+ * the future.
+ */
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_SIZE(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x4)
+#define SUN8I_MIXER_CHAN_UI_LAYER_COORD(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0xc)
+#define SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x10)
+#define SUN8I_MIXER_CHAN_UI_LAYER_BOT_LADDR(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x14)
+#define SUN8I_MIXER_CHAN_UI_LAYER_FCOLOR(ch, layer) \
+ (0x2000 + 0x1000 * (ch) + 0x20 * (layer) + 0x18)
+#define SUN8I_MIXER_CHAN_UI_TOP_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x80)
+#define SUN8I_MIXER_CHAN_UI_BOT_HADDR(ch) (0x2000 + 0x1000 * (ch) + 0x84)
+#define SUN8I_MIXER_CHAN_UI_OVL_SIZE(ch) (0x2000 + 0x1000 * (ch) + 0x88)
+
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN BIT(0)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_MASK GENMASK(2, 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_MASK GENMASK(11, 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MASK GENMASK(31, 24)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_MODE_DEF (1 << 1)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_ARGB8888 (0 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_XRGB8888 (4 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_FBFMT_RGB888 (8 << 8)
+#define SUN8I_MIXER_CHAN_UI_LAYER_ATTR_ALPHA_DEF (0xff << 24)
+
+/*
+ * These sun-engines are still unknown now, the EN registers are here only to
+ * be used to disable these sub-engines.
+ */
+#define SUN8I_MIXER_VSU_EN 0x20000
+#define SUN8I_MIXER_GSU1_EN 0x30000
+#define SUN8I_MIXER_GSU2_EN 0x40000
+#define SUN8I_MIXER_GSU3_EN 0x50000
+#define SUN8I_MIXER_FCE_EN 0xa0000
+#define SUN8I_MIXER_BWS_EN 0xa2000
+#define SUN8I_MIXER_LTI_EN 0xa4000
+#define SUN8I_MIXER_PEAK_EN 0xa6000
+#define SUN8I_MIXER_ASE_EN 0xa8000
+#define SUN8I_MIXER_FCC_EN 0xaa000
+#define SUN8I_MIXER_DCSC_EN 0xb0000
+
+struct sun8i_mixer_cfg {
+ int vi_num;
+ int ui_num;
+};
+
+struct sun8i_mixer {
+ struct regmap *regs;
+
+ const struct sun8i_mixer_cfg *cfg;
+
+ struct reset_control *reset;
+
+ struct clk *bus_clk;
+ struct clk *mod_clk;
+};
+
+void sun8i_mixer_layer_enable(struct sun8i_mixer *mixer,
+ int layer, bool enable);
+int sun8i_mixer_update_layer_coord(struct sun8i_mixer *mixer,
+ int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_formats(struct sun8i_mixer *mixer,
+ int layer, struct drm_plane *plane);
+int sun8i_mixer_update_layer_buffer(struct sun8i_mixer *mixer,
+ int layer, struct drm_plane *plane);
+#endif /* _SUN8I_MIXER_H_ */
--
2.12.0
^ permalink raw reply related
* [PATCH v3 05/11] drm/sun4i: abstract a mixer type
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
As we are going to add support for the Allwinner DE2 mixer in sun4i-drm
driver, we will finally have two types of display mixers -- the DE1
backend and the DE2 mixer. They both do some display blending and feed
graphics data to TCON, so I choose to call them both "mixer" here.
Abstract the mixer type to void * and a ops struct, which contains
functions that should be called outside the mixer-specified code (in
TCON, CRTC or TV Encoder code).
A dedicated Kconfig option is also added to control whether
sun4i-backend-specified code (sun4i_backend.c and sun4i_layer.c) should
be built. As we removed the codes in CRTC code that directly call the
layer code, we can now extract the layer part and combine it with the
backend part into a new module, sun4i-backend.ko.
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Refactored patch in v3.
drivers/gpu/drm/sun4i/Kconfig | 10 ++++++++++
drivers/gpu/drm/sun4i/Makefile | 6 ++++--
drivers/gpu/drm/sun4i/sun4i_backend.c | 26 +++++++++++++++++++-------
drivers/gpu/drm/sun4i/sun4i_backend.h | 5 -----
drivers/gpu/drm/sun4i/sun4i_crtc.c | 14 +++++++-------
drivers/gpu/drm/sun4i/sun4i_crtc.h | 7 ++++---
drivers/gpu/drm/sun4i/sun4i_drv.h | 3 ++-
drivers/gpu/drm/sun4i/sun4i_layer.c | 7 +++----
drivers/gpu/drm/sun4i/sun4i_layer.h | 6 +++---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 2 +-
drivers/gpu/drm/sun4i/sun4i_tv.c | 8 +++-----
drivers/gpu/drm/sun4i/sunxi_mixer.h | 22 ++++++++++++++++++++++
12 files changed, 78 insertions(+), 38 deletions(-)
create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index a4b357db8856..5a8227f37cc4 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -12,3 +12,13 @@ config DRM_SUN4I
Choose this option if you have an Allwinner SoC with a
Display Engine. If M is selected the module will be called
sun4i-drm.
+
+config DRM_SUN4I_BACKEND
+ tristate "Support for Allwinner A10 Display Engine Backend"
+ depends on DRM_SUN4I
+ default DRM_SUN4I
+ help
+ Choose this option if you have an Allwinner SoC with the
+ original Allwinner Display Engine, which has a backend to
+ do some alpha blending and feed graphics to TCON. If M is
+ selected the module will be called sun4i-backend.
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index 59b757350a1f..1db1068b9be1 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -5,9 +5,11 @@ sun4i-tcon-y += sun4i_tcon.o
sun4i-tcon-y += sun4i_rgb.o
sun4i-tcon-y += sun4i_dotclock.o
sun4i-tcon-y += sun4i_crtc.o
-sun4i-tcon-y += sun4i_layer.o
+
+sun4i-backend-y += sun4i_layer.o
+sun4i-backend-y += sun4i_backend.o
obj-$(CONFIG_DRM_SUN4I) += sun4i-drm.o sun4i-tcon.o
-obj-$(CONFIG_DRM_SUN4I) += sun4i_backend.o
+obj-$(CONFIG_DRM_SUN4I_BACKEND) += sun4i-backend.o
obj-$(CONFIG_DRM_SUN4I) += sun6i_drc.o
obj-$(CONFIG_DRM_SUN4I) += sun4i_tv.o
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index d660741ba475..35ea51b686e6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -23,6 +23,8 @@
#include "sun4i_backend.h"
#include "sun4i_drv.h"
+#include "sun4i_layer.h"
+#include "sunxi_mixer.h"
static const u32 sunxi_rgb2yuv_coef[12] = {
0x00000107, 0x00000204, 0x00000064, 0x00000108,
@@ -30,9 +32,10 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
};
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_apply_color_correction(void *mixer)
{
int i;
+ struct sun4i_backend *backend = mixer;
DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
@@ -44,27 +47,28 @@ void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
sunxi_rgb2yuv_coef[i]);
}
-EXPORT_SYMBOL(sun4i_backend_apply_color_correction);
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend)
+static void sun4i_backend_disable_color_correction(void *mixer)
{
+ struct sun4i_backend *backend = mixer;
+
DRM_DEBUG_DRIVER("Disabling color correction\n");
/* Disable color correction */
regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
SUN4I_BACKEND_OCCTL_ENABLE, 0);
}
-EXPORT_SYMBOL(sun4i_backend_disable_color_correction);
-void sun4i_backend_commit(struct sun4i_backend *backend)
+static void sun4i_backend_commit(void *mixer)
{
+ struct sun4i_backend *backend = mixer;
+
DRM_DEBUG_DRIVER("Committing changes\n");
regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
}
-EXPORT_SYMBOL(sun4i_backend_commit);
void sun4i_backend_layer_enable(struct sun4i_backend *backend,
int layer, bool enable)
@@ -288,6 +292,13 @@ static int sun4i_backend_free_sat(struct device *dev) {
return 0;
}
+static const struct sunxi_mixer_ops sun4i_backend_mixer_ops = {
+ .apply_color_correction = sun4i_backend_apply_color_correction,
+ .disable_color_correction = sun4i_backend_disable_color_correction,
+ .commit = sun4i_backend_commit,
+ .layers_init = sun4i_layers_init,
+};
+
static struct regmap_config sun4i_backend_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
@@ -310,7 +321,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
if (!backend)
return -ENOMEM;
dev_set_drvdata(dev, backend);
- drv->backend = backend;
+ drv->mixer = backend;
+ drv->mixer_ops = &sun4i_backend_mixer_ops;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h
index 83e63cc702b4..65ef521de7d2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.h
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.h
@@ -151,11 +151,6 @@ struct sun4i_backend {
struct reset_control *sat_reset;
};
-void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
-void sun4i_backend_disable_color_correction(struct sun4i_backend *backend);
-
-void sun4i_backend_commit(struct sun4i_backend *backend);
-
void sun4i_backend_layer_enable(struct sun4i_backend *backend,
int layer, bool enable);
int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 33854ee7f636..938dfe7188ff 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -25,11 +25,10 @@
#include <video/videomode.h>
-#include "sun4i_backend.h"
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
-#include "sun4i_layer.h"
#include "sunxi_layer.h"
+#include "sunxi_mixer.h"
#include "sun4i_tcon.h"
static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -57,7 +56,7 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
DRM_DEBUG_DRIVER("Committing plane changes\n");
- sun4i_backend_commit(scrtc->backend);
+ scrtc->mixer_ops->commit(scrtc->mixer);
if (event) {
crtc->state->event = NULL;
@@ -135,8 +134,8 @@ static const struct drm_crtc_funcs sun4i_crtc_funcs = {
.disable_vblank = sun4i_crtc_disable_vblank,
};
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
- struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+ const struct sunxi_mixer_ops *mixer_ops,
struct sun4i_tcon *tcon)
{
struct sun4i_crtc *scrtc;
@@ -146,11 +145,12 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
if (!scrtc)
return ERR_PTR(-ENOMEM);
- scrtc->backend = backend;
+ scrtc->mixer = mixer;
+ scrtc->mixer_ops = mixer_ops;
scrtc->tcon = tcon;
/* Create our layers */
- scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
+ scrtc->layers = mixer_ops->layers_init(drm, scrtc);
if (IS_ERR(scrtc->layers)) {
dev_err(drm->dev, "Couldn't create the planes\n");
return NULL;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index a4036ee44cf8..808019046397 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -17,7 +17,8 @@ struct sun4i_crtc {
struct drm_crtc crtc;
struct drm_pending_vblank_event *event;
- struct sun4i_backend *backend;
+ void *mixer;
+ const struct sunxi_mixer_ops *mixer_ops;
struct sun4i_tcon *tcon;
void **layers;
const struct sunxi_layer_ops *layer_ops;
@@ -28,8 +29,8 @@ static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
return container_of(crtc, struct sun4i_crtc, crtc);
}
-struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
- struct sun4i_backend *backend,
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm, void *mixer,
+ const struct sunxi_mixer_ops *mixer_ops,
struct sun4i_tcon *tcon);
#endif /* _SUN4I_CRTC_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.h b/drivers/gpu/drm/sun4i/sun4i_drv.h
index 5df50126ff52..97666b3e6381 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.h
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.h
@@ -17,8 +17,9 @@
#include <linux/regmap.h>
struct sun4i_drv {
- struct sun4i_backend *backend;
+ void *mixer;
struct sun4i_tcon *tcon;
+ const struct sunxi_mixer_ops *mixer_ops;
struct drm_fbdev_cma *fbdev;
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index bc4a70d6968b..972e1eb0bb2a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -141,11 +141,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
return layer;
}
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
- struct sun4i_crtc *crtc)
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc)
{
struct sun4i_layer **layers;
- struct sun4i_backend *backend = crtc->backend;
+ struct sun4i_backend *backend = crtc->mixer;
int i;
layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -198,5 +197,5 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
/* Assign layer ops to the CRTC */
crtc->layer_ops = &layer_ops;
- return layers;
+ return (void **)layers;
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 425eea7b9e3b..e6a08216d038 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -13,6 +13,8 @@
#ifndef _SUN4I_LAYER_H_
#define _SUN4I_LAYER_H_
+struct sun4i_crtc;
+
struct sun4i_layer {
struct drm_plane plane;
struct sun4i_drv *drv;
@@ -26,7 +28,5 @@ plane_to_sun4i_layer(struct drm_plane *plane)
return container_of(plane, struct sun4i_layer, plane);
}
-struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
- struct sun4i_crtc *crtc);
-
+void **sun4i_layers_init(struct drm_device *drm, struct sun4i_crtc *crtc);
#endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3ced0b1cef6e..2f330e4e2ead 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -528,7 +528,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
goto err_free_dotclock;
}
- tcon->crtc = sun4i_crtc_init(drm, drv->backend, tcon);
+ tcon->crtc = sun4i_crtc_init(drm, drv->mixer, drv->mixer_ops, tcon);
if (IS_ERR(tcon->crtc)) {
dev_err(dev, "Couldn't create our CRTC\n");
ret = PTR_ERR(tcon->crtc);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 49c49431a053..5950736610aa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -22,10 +22,10 @@
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
-#include "sun4i_backend.h"
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
#include "sun4i_tcon.h"
+#include "sunxi_mixer.h"
#define SUN4I_TVE_EN_REG 0x000
#define SUN4I_TVE_EN_DAC_MAP_MASK GENMASK(19, 4)
@@ -353,7 +353,6 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
struct sun4i_tcon *tcon = crtc->tcon;
- struct sun4i_backend *backend = crtc->backend;
DRM_DEBUG_DRIVER("Disabling the TV Output\n");
@@ -362,7 +361,7 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
SUN4I_TVE_EN_ENABLE,
0);
- sun4i_backend_disable_color_correction(backend);
+ crtc->mixer_ops->disable_color_correction(crtc->mixer);
}
static void sun4i_tv_enable(struct drm_encoder *encoder)
@@ -370,11 +369,10 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
struct sun4i_tcon *tcon = crtc->tcon;
- struct sun4i_backend *backend = crtc->backend;
DRM_DEBUG_DRIVER("Enabling the TV Output\n");
- sun4i_backend_apply_color_correction(backend);
+ crtc->mixer_ops->apply_color_correction(crtc->mixer);
regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
SUN4I_TVE_EN_ENABLE,
diff --git a/drivers/gpu/drm/sun4i/sunxi_mixer.h b/drivers/gpu/drm/sun4i/sunxi_mixer.h
new file mode 100644
index 000000000000..11bdd20269ef
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_mixer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_MIXER_H_
+#define _SUNXI_MIXER_H_
+
+struct sun4i_crtc;
+
+struct sunxi_mixer_ops {
+ void **(*layers_init)(struct drm_device *drm, struct sun4i_crtc *crtc);
+ void (*apply_color_correction)(void *mixer);
+ void (*disable_color_correction)(void *mixer);
+ void (*commit)(void *mixer);
+};
+
+#endif /* _SUNXI_MIXER_H_ */
--
2.12.0
^ permalink raw reply related
* [PATCH v3 04/11] drm/sun4i: abstract the layer type
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
As we are going to add support for the Allwinner DE2 Mixer in sun4i-drm
driver, we will finally have two types of layer.
Abstract the layer type to void * and a ops struct, which contains the
only function used by crtc -- get the drm_plane struct of the layer.
Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
Refactored patch in v3.
drivers/gpu/drm/sun4i/sun4i_crtc.c | 19 +++++++++++--------
drivers/gpu/drm/sun4i/sun4i_crtc.h | 3 ++-
drivers/gpu/drm/sun4i/sun4i_layer.c | 19 ++++++++++++++++++-
drivers/gpu/drm/sun4i/sun4i_layer.h | 2 +-
drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +++++++++++++++++
5 files changed, 49 insertions(+), 11 deletions(-)
create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 3c876c3a356a..33854ee7f636 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -29,6 +29,7 @@
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
#include "sun4i_layer.h"
+#include "sunxi_layer.h"
#include "sun4i_tcon.h"
static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -149,7 +150,7 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
scrtc->tcon = tcon;
/* Create our layers */
- scrtc->layers = sun4i_layers_init(drm, scrtc->backend);
+ scrtc->layers = (void **)sun4i_layers_init(drm, scrtc);
if (IS_ERR(scrtc->layers)) {
dev_err(drm->dev, "Couldn't create the planes\n");
return NULL;
@@ -157,14 +158,15 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
/* find primary and cursor planes for drm_crtc_init_with_planes */
for (i = 0; scrtc->layers[i]; i++) {
- struct sun4i_layer *layer = scrtc->layers[i];
+ void *layer = scrtc->layers[i];
+ struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
- switch (layer->plane.type) {
+ switch (plane->type) {
case DRM_PLANE_TYPE_PRIMARY:
- primary = &layer->plane;
+ primary = plane;
break;
case DRM_PLANE_TYPE_CURSOR:
- cursor = &layer->plane;
+ cursor = plane;
break;
default:
break;
@@ -190,10 +192,11 @@ struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm,
/* Set possible_crtcs to this crtc for overlay planes */
for (i = 0; scrtc->layers[i]; i++) {
uint32_t possible_crtcs = BIT(drm_crtc_index(&scrtc->crtc));
- struct sun4i_layer *layer = scrtc->layers[i];
+ void *layer = scrtc->layers[i];
+ struct drm_plane *plane = scrtc->layer_ops->get_plane(layer);
- if (layer->plane.type == DRM_PLANE_TYPE_OVERLAY)
- layer->plane.possible_crtcs = possible_crtcs;
+ if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+ plane->possible_crtcs = possible_crtcs;
}
return scrtc;
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.h b/drivers/gpu/drm/sun4i/sun4i_crtc.h
index 230cb8f0d601..a4036ee44cf8 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.h
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.h
@@ -19,7 +19,8 @@ struct sun4i_crtc {
struct sun4i_backend *backend;
struct sun4i_tcon *tcon;
- struct sun4i_layer **layers;
+ void **layers;
+ const struct sunxi_layer_ops *layer_ops;
};
static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index f26bde5b9117..bc4a70d6968b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -16,7 +16,9 @@
#include <drm/drmP.h>
#include "sun4i_backend.h"
+#include "sun4i_crtc.h"
#include "sun4i_layer.h"
+#include "sunxi_layer.h"
struct sun4i_plane_desc {
enum drm_plane_type type;
@@ -100,6 +102,17 @@ static const struct sun4i_plane_desc sun4i_backend_planes[] = {
},
};
+static struct drm_plane *sun4i_layer_get_plane(void *layer)
+{
+ struct sun4i_layer *sun4i_layer = layer;
+
+ return &sun4i_layer->plane;
+}
+
+static const struct sunxi_layer_ops layer_ops = {
+ .get_plane = sun4i_layer_get_plane,
+};
+
static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
struct sun4i_backend *backend,
const struct sun4i_plane_desc *plane)
@@ -129,9 +142,10 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
}
struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
- struct sun4i_backend *backend)
+ struct sun4i_crtc *crtc)
{
struct sun4i_layer **layers;
+ struct sun4i_backend *backend = crtc->backend;
int i;
layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes) + 1,
@@ -181,5 +195,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
layers[i] = layer;
};
+ /* Assign layer ops to the CRTC */
+ crtc->layer_ops = &layer_ops;
+
return layers;
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4be1f0919df2..425eea7b9e3b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -27,6 +27,6 @@ plane_to_sun4i_layer(struct drm_plane *plane)
}
struct sun4i_layer **sun4i_layers_init(struct drm_device *drm,
- struct sun4i_backend *backend);
+ struct sun4i_crtc *crtc);
#endif /* _SUN4I_LAYER_H_ */
diff --git a/drivers/gpu/drm/sun4i/sunxi_layer.h b/drivers/gpu/drm/sun4i/sunxi_layer.h
new file mode 100644
index 000000000000..d8838ec39299
--- /dev/null
+++ b/drivers/gpu/drm/sun4i/sunxi_layer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUNXI_LAYER_H_
+#define _SUNXI_LAYER_H_
+
+struct sunxi_layer_ops {
+ struct drm_plane *(*get_plane)(void *layer);
+};
+
+#endif /* _SUNXI_LAYER_H_ */
--
2.12.0
^ permalink raw reply related
* [PATCH v3 03/11] dt-bindings: add bindings for DE2 on V3s SoC
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Allwinner V3s SoC have a display engine which have a different pipeline
with older SoCs.
Add document for it (new compatibles and the new "mixer" part).
The paragraph of TCON is also refactored, for furtherly add TCONs in
A83T/H3/A64/H5 that have only a channel 1 (used for HDMI or TV Encoder).
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v3:
- Remove the description of having a BE directly as allwinner,pipeline.
.../bindings/display/sunxi/sun4i-drm.txt | 37 +++++++++++++++++++---
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b82c00449468..38de5e96f359 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -31,11 +31,11 @@ Required properties:
* allwinner,sun6i-a31-tcon
* allwinner,sun6i-a31s-tcon
* allwinner,sun8i-a33-tcon
+ * allwinner,sun8i-v3s-tcon
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
- - clocks: phandles to the clocks feeding the TCON. Three are needed:
+ - clocks: phandles to the clocks feeding the TCON
- 'ahb': the interface clocks
- - 'tcon-ch0': The clock driving the TCON channel 0
- resets: phandles to the reset controllers driving the encoder
- "lcd": the reset line for the TCON channel 0
@@ -52,7 +52,12 @@ Required properties:
second the block connected to the TCON channel 1 (usually the TV
encoder)
-On SoCs other than the A33, there is one more clock required:
+On TCONs that have a channel 0 (currently all TCONs supported), there
+is one more clock required:
+ - 'tcon-ch0': The clock driving the TCON channel 0
+
+On TCONs that have a channel 1 (currently all TCONs except the ones in
+A33 and V3s), there is one more clock required:
- 'tcon-ch1': The clock driving the TCON channel 1
DRC
@@ -137,6 +142,26 @@ Required properties:
Documentation/devicetree/bindings/media/video-interfaces.txt. The
first port should be the input endpoints, the second one the outputs
+Display Engine 2.0 Mixer
+------------------------
+
+The DE2 mixer have many functionalities, currently only layer blending is
+supported.
+
+Required properties:
+ - compatible: value must be one of:
+ * allwinner,sun8i-v3s-de2-mixer
+ - reg: base address and size of the memory-mapped region.
+ - clocks: phandles to the clocks feeding the frontend and backend
+ * bus: the backend interface clock
+ * ram: the backend DRAM clock
+ - clock-names: the clock names mentioned above
+ - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+ Documentation/devicetree/bindings/media/video-interfaces.txt. The
+ first port should be the input endpoints, the second one the output
+
Display Engine Pipeline
-----------------------
@@ -151,9 +176,13 @@ Required properties:
* allwinner,sun6i-a31-display-engine
* allwinner,sun6i-a31s-display-engine
* allwinner,sun8i-a33-display-engine
+ * allwinner,sun8i-v3s-display-engine
- allwinner,pipelines: list of phandle to the display engine
- frontends available.
+ pipeline entry point. For SoCs with original DE (currently
+ all SoCs supported by display engine except V3s), this
+ phandle should be a display frontend; for SoCs with DE2,
+ this phandle should be a mixer.
Example:
--
2.12.0
^ permalink raw reply related
* [PATCH v3 02/11] clk: sunxi-ng: add support for DE2 CCU
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
The "Display Engine 2.0" in Allwinner newer SoCs contains a clock
management unit for its subunits, like the DE CCU in A80.
Add a sunxi-ng style driver for it.
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v2:
- Rename sunxi-de2-ccu to sun8i-de2-ccu.
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 204 ++++++++++++++++++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun8i-de2.h | 28 +++++
include/dt-bindings/clock/sun8i-de2.h | 54 +++++++++
include/dt-bindings/reset/sun8i-de2.h | 50 +++++++++
6 files changed, 342 insertions(+)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
create mode 100644 include/dt-bindings/clock/sun8i-de2.h
create mode 100644 include/dt-bindings/reset/sun8i-de2.h
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index 8af8f4be8e3b..778c141dd966 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -140,6 +140,11 @@ config SUN8I_V3S_CCU
default MACH_SUN8I
depends on MACH_SUN8I || COMPILE_TEST
+config SUN8I_DE2_CCU
+ bool "Support for the Allwinner SoCs DE2 CCU"
+ select SUNXI_CCU_DIV
+ select SUNXI_CCU_GATE
+
config SUN9I_A80_CCU
bool "Support for the Allwinner A80 CCU"
select SUNXI_CCU_DIV
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6feaac0c5600..8bf3afaefde4 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o
obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o
obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_DE2_CCU) += ccu-sun8i-de2.o
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o
obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
new file mode 100644
index 000000000000..43d7bd15e38b
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "ccu_common.h"
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_reset.h"
+
+#include "ccu-sun8i-de2.h"
+
+static SUNXI_CCU_GATE(bus_mixer0_clk, "bus-mixer0", "bus-de",
+ 0x04, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mixer1_clk, "bus-mixer1", "bus-de",
+ 0x04, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_wb_clk, "bus-wb", "bus-de",
+ 0x04, BIT(2), 0);
+
+static SUNXI_CCU_GATE(mixer0_clk, "mixer0", "mixer0-div",
+ 0x00, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_clk, "mixer1", "mixer1-div",
+ 0x00, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div",
+ 0x00, BIT(2), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
+ CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sunxi_de2_clks[] = {
+ &mixer0_clk.common,
+ &mixer1_clk.common,
+ &wb_clk.common,
+
+ &bus_mixer0_clk.common,
+ &bus_mixer1_clk.common,
+ &bus_wb_clk.common,
+
+ &mixer0_div_clk.common,
+ &mixer1_div_clk.common,
+ &wb_div_clk.common,
+};
+
+static struct clk_hw_onecell_data sunxi_de2_hw_clks = {
+ .hws = {
+ [CLK_MIXER0] = &mixer0_clk.common.hw,
+ [CLK_MIXER1] = &mixer1_clk.common.hw,
+ [CLK_WB] = &wb_clk.common.hw,
+
+ [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw,
+ [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw,
+ [CLK_BUS_WB] = &bus_wb_clk.common.hw,
+
+ [CLK_MIXER0_DIV] = &mixer1_div_clk.common.hw,
+ [CLK_MIXER1_DIV] = &mixer0_div_clk.common.hw,
+ [CLK_WB_DIV] = &wb_div_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_a83t_de2_resets[] = {
+ [RST_MIXER0] = { 0x08, BIT(0) },
+ /*
+ * For A83T, H3 and R40, mixer1 reset line is shared with wb, so
+ * only RST_WB is exported here.
+ */
+ [RST_WB] = { 0x08, BIT(2) },
+};
+
+static struct ccu_reset_map sun50i_a64_de2_resets[] = {
+ [RST_MIXER0] = { 0x08, BIT(0) },
+ [RST_MIXER1] = { 0x08, BIT(1) },
+ [RST_WB] = { 0x08, BIT(2) },
+};
+
+static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
+ .ccu_clks = sunxi_de2_clks,
+ .num_ccu_clks = ARRAY_SIZE(sunxi_de2_clks),
+
+ .hw_clks = &sunxi_de2_hw_clks,
+
+ .resets = sun8i_a83t_de2_resets,
+ .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
+ .ccu_clks = sunxi_de2_clks,
+ .num_ccu_clks = ARRAY_SIZE(sunxi_de2_clks),
+
+ .hw_clks = &sunxi_de2_hw_clks,
+
+ .resets = sun50i_a64_de2_resets,
+ .num_resets = ARRAY_SIZE(sun50i_a64_de2_resets),
+};
+
+static int sunxi_de2_clk_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct clk *bus_clk;
+ struct reset_control *rstc;
+ void __iomem *reg;
+ const struct sunxi_ccu_desc *ccu_desc;
+ int ret;
+
+ ccu_desc = of_device_get_match_data(&pdev->dev);
+ if (!ccu_desc)
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ bus_clk = devm_clk_get(&pdev->dev, "bus");
+ if (IS_ERR(bus_clk)) {
+ ret = PTR_ERR(bus_clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
+ return ret;
+ }
+
+ rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(rstc)) {
+ ret = PTR_ERR(bus_clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "Couldn't get reset control: %d\n", ret);
+ return ret;
+ }
+
+ /* The bus clock needs to be enabled for us to access the registers */
+ ret = clk_prepare_enable(bus_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
+ return ret;
+ }
+
+ /* The reset control needs to be asserted for the controls to work */
+ ret = reset_control_deassert(rstc);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Couldn't deassert reset control: %d\n", ret);
+ goto err_disable_clk;
+ }
+
+ ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
+ if (ret)
+ goto err_assert_reset;
+
+ return 0;
+
+err_assert_reset:
+ reset_control_assert(rstc);
+err_disable_clk:
+ clk_disable_unprepare(bus_clk);
+ return ret;
+}
+
+static const struct of_device_id sunxi_de2_clk_ids[] = {
+ {
+ .compatible = "allwinner,sun8i-a83t-de2-clk",
+ .data = &sun8i_a83t_de2_clk_desc,
+ },
+ {
+ .compatible = "allwinner,sun50i-h5-de2-clk",
+ .data = &sun50i_a64_de2_clk_desc,
+ },
+ /*
+ * The Allwinner A64 SoC needs some bit to be poke in syscon to make
+ * DE2 really working.
+ * So there's currently no A64 compatible here.
+ * H5 shares the same reset line with A64, so here H5 is using the
+ * clock description of A64.
+ */
+ { }
+};
+
+static struct platform_driver sunxi_de2_clk_driver = {
+ .probe = sunxi_de2_clk_probe,
+ .driver = {
+ .name = "sunxi-de2-clks",
+ .of_match_table = sunxi_de2_clk_ids,
+ },
+};
+builtin_platform_driver(sunxi_de2_clk_driver);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.h b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
new file mode 100644
index 000000000000..ab8bcd4ba3a5
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_DE2_H_
+#define _CCU_SUN8I_DE2_H_
+
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+
+/* Intermediary clock dividers are not exported */
+#define CLK_MIXER0_DIV 3
+#define CLK_MIXER1_DIV 4
+#define CLK_WB_DIV 5
+
+#define CLK_NUMBER (CLK_WB + 1)
+
+#endif /* _CCU_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/clock/sun8i-de2.h b/include/dt-bindings/clock/sun8i-de2.h
new file mode 100644
index 000000000000..5fbc954d78e8
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-de2.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+#define _DT_BINDINGS_CLOCK_SUN8I_DE2_H_
+
+#define CLK_BUS_MIXER0 0
+#define CLK_BUS_MIXER1 1
+#define CLK_BUS_WB 2
+
+#define CLK_MIXER0 6
+#define CLK_MIXER1 7
+#define CLK_WB 8
+
+#endif /* _DT_BINDINGS_CLOCK_SUN8I_DE2_H_ */
diff --git a/include/dt-bindings/reset/sun8i-de2.h b/include/dt-bindings/reset/sun8i-de2.h
new file mode 100644
index 000000000000..b45eba4e28c8
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-de2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8I_DE2_H_
+#define _DT_BINDINGS_RESET_SUN8I_DE2_H_
+
+#define RST_MIXER0 0
+#define RST_MIXER1 1
+#define RST_WB 2
+
+#endif /* _DT_BINDINGS_RESET_SUN8I_DE2_H_ */
--
2.12.0
^ permalink raw reply related
* [PATCH v3 01/11] dt-bindings: add binding for the Allwinner DE2 CCU
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170329194613.55548-1-icenowy-h8G6r0blFSE@public.gmane.org>
From: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
Allwinner "Display Engine 2.0" contains some clock controls in it.
In order to add them as clock drivers, we need a device tree binding.
Add the binding here.
Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>
---
Changes in v3:
- Fill the address space length of DE2 CCU to 0x100000, just reach the start of mixer0.
.../devicetree/bindings/clock/sun8i-de2.txt | 31 ++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
new file mode 100644
index 000000000000..34cf79c05f13
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sun8i-de2.txt
@@ -0,0 +1,31 @@
+Allwinner Display Engine 2.0 Clock Control Binding
+--------------------------------------------------
+
+Required properties :
+- compatible: must contain one of the following compatibles:
+ - "allwinner,sun8i-a83t-de2-clk"
+ - "allwinner,sun50i-a64-de2-clk"
+ - "allwinner,sun50i-h5-de2-clk"
+
+- reg: Must contain the registers base address and length
+- clocks: phandle to the clocks feeding the display engine subsystem.
+ Three are needed:
+ - "mod": the display engine module clock
+ - "bus": the bus clock for the whole display engine subsystem
+- clock-names: Must contain the clock names described just above
+- resets: phandle to the reset control for the display engine subsystem.
+- #clock-cells : must contain 1
+- #reset-cells : must contain 1
+
+Example:
+de2_clocks: clock@01000000 {
+ compatible = "allwinner,sun50i-a64-de2-clk";
+ reg = <0x01000000 0x100000>;
+ clocks = <&ccu CLK_DE>,
+ <&ccu CLK_BUS_DE>;
+ clock-names = "mod",
+ "bus";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+};
--
2.12.0
^ permalink raw reply related
* [PATCH v3 00/11] Initial Allwinner Display Engine 2.0 Support
From: Icenowy Zheng @ 2017-03-29 19:46 UTC (permalink / raw)
To: Rob Herring, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: linux-clk-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
This patchset is the initial patchset for Allwinner DE2 support.
It contains the support of clocks in DE2 and the mixers in DE2.
The SoC used to develop this patchset is V3s, as V3s is the simplest
one of the SoCs that have DE2.
(Allwinner V3s features only one mixer, although its clock control
unit contains support for second mixer's clock; and its only video
output is RGB LCD, which is already supported in our TCON driver)
The last patch is only a testing patch, it shouldn't be merged; and
for the patch to be really usable, the RFC fix of the TCON driver [1]
is needed.
No HDMI, TV encoder or other internal bridges' support is included
in this patchset, which makes it currently not usable on H3.
Thanks to Jean-Francois Moine and Jernej Skrabec for their efforts
to discover the internal of DE2!
[1] https://lists.freedesktop.org/archives/dri-devel/2016-December/126264.html
Icenowy Zheng (11):
dt-bindings: add binding for the Allwinner DE2 CCU
clk: sunxi-ng: add support for DE2 CCU
dt-bindings: add bindings for DE2 on V3s SoC
drm/sun4i: abstruct the layer type
drm/sun4i: abstract a mixer type
drm/sun4i: add support for Allwinner DE2 mixers
drm/sun4i: Add compatible string for V3s display engine
drm/sun4i: tcon: add support for V3s TCON
ARM: dts: sun8i: add DE2 nodes for V3s SoC
ARM: dts: sun8i: add pinmux for LCD pins of V3s SoC
[DO NOT MERGE] ARM: dts: sun8i: enable LCD panel of Lichee Pi Zero
.../devicetree/bindings/clock/sun8i-de2.txt | 31 ++
.../bindings/display/sunxi/sun4i-drm.txt | 37 +-
arch/arm/boot/dts/sun8i-v3s-licheepi-zero.dts | 36 ++
arch/arm/boot/dts/sun8i-v3s.dtsi | 96 +++++
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 204 +++++++++++
drivers/clk/sunxi-ng/ccu-sun8i-de2.h | 28 ++
drivers/gpu/drm/sun4i/Kconfig | 20 ++
drivers/gpu/drm/sun4i/Makefile | 10 +-
drivers/gpu/drm/sun4i/sun4i_backend.c | 26 +-
drivers/gpu/drm/sun4i/sun4i_backend.h | 5 -
drivers/gpu/drm/sun4i/sun4i_crtc.c | 31 +-
drivers/gpu/drm/sun4i/sun4i_crtc.h | 10 +-
drivers/gpu/drm/sun4i/sun4i_drv.c | 4 +-
drivers/gpu/drm/sun4i/sun4i_drv.h | 3 +-
drivers/gpu/drm/sun4i/sun4i_layer.c | 22 +-
drivers/gpu/drm/sun4i/sun4i_layer.h | 6 +-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 7 +-
drivers/gpu/drm/sun4i/sun4i_tv.c | 8 +-
drivers/gpu/drm/sun4i/sun8i_layer.c | 156 +++++++++
drivers/gpu/drm/sun4i/sun8i_layer.h | 35 ++
drivers/gpu/drm/sun4i/sun8i_mixer.c | 386 +++++++++++++++++++++
drivers/gpu/drm/sun4i/sun8i_mixer.h | 131 +++++++
drivers/gpu/drm/sun4i/sunxi_layer.h | 17 +
drivers/gpu/drm/sun4i/sunxi_mixer.h | 22 ++
include/dt-bindings/clock/sun8i-de2.h | 54 +++
include/dt-bindings/reset/sun8i-de2.h | 50 +++
28 files changed, 1391 insertions(+), 50 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-de2.h
create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.c
create mode 100644 drivers/gpu/drm/sun4i/sun8i_layer.h
create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.c
create mode 100644 drivers/gpu/drm/sun4i/sun8i_mixer.h
create mode 100644 drivers/gpu/drm/sun4i/sunxi_layer.h
create mode 100644 drivers/gpu/drm/sun4i/sunxi_mixer.h
create mode 100644 include/dt-bindings/clock/sun8i-de2.h
create mode 100644 include/dt-bindings/reset/sun8i-de2.h
--
2.12.0
^ permalink raw reply
* Re: [PATCH v4 2/3] mailbox: Add iProc mailbox controller driver
From: Jonathan Richardson @ 2017-03-29 19:28 UTC (permalink / raw)
To: Jassi Brar
Cc: Rob Herring, Mark Rutland, Ray Jui, Scott Branden, Jon Mason,
Russell King, Vikram Prakash, Devicetree List,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
BCM Kernel Feedback
In-Reply-To: <CABb+yY31oW09-fq_t4V6vatMe50Ed2Mi00kT4bOJv2=qFBT+QA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On 17-03-28 09:36 PM, Jassi Brar wrote:
> On Tue, Mar 28, 2017 at 11:00 PM, Jonathan Richardson
> <jonathan.richardson-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
>> On 17-03-15 10:30 AM, Jassi Brar wrote:
>>> The right way to do is have a 'server/owner' client that accepts
>>> requests from various clients and serially queue them to mailbox. That
>>> way you can keep the controller driver free from quirks (like max wait
>>> time of 30us) of your present platform.
>> Do you mean 1 mailbox client with one mailbox channel that all the mbox client drivers share?
>> I thought this would work when I suggested it previously but the client callbacks are necessary
>> in all txdone modes. Client drivers that send the messages need the callbacks
>>
> That's a legit requirement.
>
>> and this is only possible with multiple mbox clients.
>>
> That is incorrect.
> It is trivial to support callbacks to end clients from your common
> code... just ask for callback along with the message to be submitted
> to mailbox api.
Ok, if we can provide our own callbacks in the message instead of the client then that's perfectly fine.
>
>> And a channel can only have 1 mbox client. Clients in multiple drivers need the callbacks to either know when to start polling, or be notified when the transaction is complete. It would be nice if multiple clients could use the same channel.
>>
> We had to choose from shared vs exclusive access to channels... latter
> was chosen because there are ways to still support former.
This makes more sense now. Thanks for clarifying.
Jon
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/2] DT: leds: Add Qualcomm Light Pulse Generator binding
From: Bjorn Andersson @ 2017-03-29 19:26 UTC (permalink / raw)
To: Rob Herring
Cc: Richard Purdie, Jacek Anaszewski, Pavel Machek, Mark Rutland,
linux-leds-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-msm-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170329022649.wp5uvt2akufgihwh@rob-hp-laptop>
On Tue 28 Mar 19:26 PDT 2017, Rob Herring wrote:
> On Wed, Mar 22, 2017 at 10:54:35PM -0700, Bjorn Andersson wrote:
> > This adds the binding document describing the three hardware blocks
> > related to the Light Pulse Generator found in a wide range of Qualcomm
> > PMICs.
> >
> > Signed-off-by: Bjorn Andersson <bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > ---
> > .../devicetree/bindings/leds/leds-qcom-lpg.txt | 194 +++++++++++++++++++++
> > 1 file changed, 194 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/leds/leds-qcom-lpg.txt
> >
> > diff --git a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.txt b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.txt
> > new file mode 100644
> > index 000000000000..fb9edd89119d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.txt
> > @@ -0,0 +1,194 @@
> > +Binding for Qualcomm Light Pulse Generator
> > +
> > +The Qualcomm Light Pulse Generator consists of three different hardware blocks;
> > +a ramp generator with lookup table, the light pulse generator and a three
> > +channel current sink. These blocks are found in a wide range of Qualcomm PMICs.
> > +Each of these are described individually below.
> > +
> > += Lookup Table (LUT)
> > +
> > +- compatible:
> > + Usage: required
> > + Value type: <stringlist>
> > + Definition: must be "qcom,spmi-lpg-lut"
> > +
> > +- reg:
> > + Usage: required
> > + Value type: <prop-encoded-array>
> > + Definition: base address of the LUT block
> > +
> > +- qcom,lut-size:
> > + Usage: required
> > + Value type: <u32>
> > + Definition: number of elements available in the lookup table
> > +
> > += Light Pulse Generator (LPG)
> > +The Light Pulse Generator can operate either as a standard PWM controller or in
> > +a more advanced lookup-table based mode. These are described separately below.
> > +
> > +- compatible:
> > + Usage: required
> > + Value type: <stringlist>
> > + Definition: must be "qcom,spmi-lpg"
> > +
> > +- reg:
> > + Usage: required
> > + Value type: <prop-encoded-array>
> > + Definition: base address of the LPG block
> > +
> > +== PWM mode
> > +
> > +- #pwm-cells:
> > + Usage: required
> > + Value type: <u32>
> > + Definition: must be 1
> > +
> > +== Lookup-table mode
> > +
> > +- cell-index:
>
> This is a standard though not used property name. Perhaps "reg" or a
> vendor property instead.
>
The node already has a "reg", this is the "natural" id of the
LPG-channel, as used to reference a certain ramp-generator in the LUT.
I did model this as an argument of the qcom,lut property below, but felt
it's not a question of "which LUT" or any "configuration of the LUT" it
is a property of the LPG.
I can convert this to a qcom,lpg-id or something like that if you
prefer.
> > + Usage: required, when referencing a LUT
> > + Value type: <u32>
> > + Definition: id of the LPG, used to associate the LPG with a particular
> > + ramp generator in the LUT block
> > +
> > +- default-state:
> > + Usage: optional
> > + Value type: <string>
> > + Definition: default state, as defined in common.txt
> > +
> > +- label:
> > + Usage: optional
> > + Value type: <string>
> > + Definition: label of the LED, as defined in common.txt
> > +
> > +- linux,default-trigger:
> > + Usage: optional
> > + Value type: <string>
> > + Definition: default trigger, as defined in common.txt
> > +
> > +- qcom,tri-led:
> > + Usage: optional
> > + Value type: <prop-encoded-array>
> > + Definition: a phandle of a TRILED node and a single u32 denoting which
> > + output channel to control
> > +
> > +- qcom,lut:
> > + Usage: optional
> > + Value type: <prop-encoded-array>
> > + Definition: phandle of a LUT node
> > +
> > +- qcom,dtest:
> > + Usage: optional
> > + Value type: <prop-encoded-array>
> > + Definition: configures the output into an internal test line of the
> > + pmic. A first u32 defines which test line to use and the
> > + second cell configures how the value should be outputed
> > + (available lines and configuration differs between PMICs)
> > +
> > +- qcom,pattern:
> > + Usage: optional
> > + Value type: <u16-list>
> > + Definition: list of 16 bit duty cycle values to make up the pattern to
> > + be programmed into the LUT. Values should be in the range
> > + [0,512).
> > +
> > +- qcom,pattern-length-ms:
> > + Usage: optional
> > + Value type: <u32>
> > + Definition: duration, in milliseconds, of the ramp generator running
> > + one pass over the defined pattern
> > +
> > +- qcom,pattern-pause-lo-ms:
> > + Usage: optional
> > + Value type: <u32>
> > + Definition: duration, in milliseconds, for the ramp generator to pause
> > + before iterating over the pattern
> > +
> > +- qcom,pattern-pause-hi-ms:
> > + Usage: optional
> > + Value type: <u32>
> > + Definition: duration, in milliseconds, for the ramp generator to pause
> > + after iterating over the pattern
> > +
> > +- qcom,pattern-ping-pong:
> > + Usage: optional
> > + Value type: <boolean>
> > + Definition: denotes that the ramp generator should reverse direction
> > + when reaching the end of the pattern, instead of wrapping
> > + to the beginning
> > +
> > +- qcom,pattern-oneshot:
> > + Usage: optional
> > + Value type: <boolean>
> > + Definition: denotes that the ramp generator should stop after a single
> > + pass over the pattern
> > +
> > +- qcom,pattern-reverse:
> > + Usage: optional
> > + Value type: <boolean>
> > + Definition: denotes that the ramp generator should operate backwards
> > + over the pattern
>
> The pattern related properties should be common if we put them in DT
> which I think is debatable.
>
A few years back I saw one other chip that had a similar pattern style,
using these properties for the LP5xx - that is what's being requested -
would have to be implemented by something reading the pattern and
generating firmware to be run on the chip. This should be possible to
do, but there are a lot functionality in the LP55xx chips that you would
not be able to use with such an approach.
> > +
> > += LED Current Sink (TRILED)
> > +
> > +- compatible:
> > + Usage: required
> > + Value type: <stringlist>
> > + Definition: must be "qcom,spmi-tri-led"
> > +
> > +- reg:
> > + Usage: required
> > + Value type: <prop-encoded-array>
> > + Definition: base address of the TRILED block
> > +
> > +- qcom,power-source:
> > + Usage: required
> > + Value type: <u32>
> > + Definition: power-source used to drive the output, as defined in the
> > + datasheet
> > +
> > += EXAMPLE:
> > +The following example defines a single output of the PMI8994, sinking current
> > +into a LED in a natural pulsating pattern:
> > +
> > +&spmi_bus {
> > + pmic@3 {
> > + compatible = "qcom,pmi8994", "qcom,spmi-pmic";
>
> typo.
>
Sorry, I don't see the typo.
> > + reg = <0x3 SPMI_USID>;
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + pmi8994_lpg_lut: lpg-lut@b000 {
> > + compatible = "qcom,spmi-lpg-lut";
> > + reg = <0xb000>;
> > +
> > + qcom,lut-size = <24>;
> > + };
> > +
> > + lpg@b200 {
> > + compatible = "qcom,spmi-lpg";
> > + reg = <0xb200>;
> > +
> > + cell-index = <2>;
> > +
> > + label = "lpg:green:user0";
> > +
> > + qcom,tri-led = <&pmi8994_tri_led 1>;
> > + qcom,lut = <&pmi8994_lpg_lut>;
> > +
> > + qcom,pattern = /bits/ 16 <9 20 42 86 158 256 353
> > + 425 469 491 502 507>;
> > + qcom,pattern-length-ms = <1337>;
> > + qcom,pattern-ping-pong;
> > +
> > + default-state = "on";
> > + };
> > +
> > + pmi8994_tri_led: tri-led@d000 {
>
> It may make more sense to make the LED(s) and their properties a sub
> node of this. You could always use the PWM binding to link back to the
> LPG. The pattern/LUT is really just a queue of PWM settings. That's not
> all that different than a PWM based audio buzzer. There was a DMA based
> PWM binding the other day for audio.
>
The TRILED is a separate hardware block from the LPG and for 3
(predefined) LPG channel it serves as one of the options for routing the
signal out of the PMIC.
As an example, on DB820c I drive the fourth user-LED by routing one of
the LPG channels to a MPP configured as current-sink.
Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCHv3 2/2] leds: cpcap: new driver
From: Jacek Anaszewski @ 2017-03-29 19:12 UTC (permalink / raw)
To: Sebastian Reichel, Richard Purdie, Pavel Machek, Lee Jones
Cc: Tony Lindgren, Rob Herring, Mark Rutland,
linux-leds-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170324084732.31255-2-sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Hi Sebastian,
On 03/24/2017 09:47 AM, Sebastian Reichel wrote:
> Motorola CPCAP is a PMIC (power management integrated circuit) found
> in multiple smartphones. This driver adds support for the chip's LED
> controllers. This introduces support for all controllers used by the
> Droid 4. According to Motorola's driver (no datasheets available)
> there a couple of more LED controllers. I did not add support for
> them, since I cannot verify that they work with my modifications.
>
> Acked-by: Pavel Machek <pavel-+ZI9xUNit7I@public.gmane.org>
> Signed-off-by: Sebastian Reichel <sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
> Changes since PATCHv1:
> - binding: reference common led binding for label
> - drop DEBUG define (leftover)
> - s/led/LED/g in debug prints
> - order includes alphabetically
> - introduce mutex, since led API is not atomic
> - register led class after initial register setup
> - use GPLv2+ in header
> - drop unsupported leds from driver
>
> Changes since PATCHv2:
> - use standard defines instead CPCAP_LED_OFF and CPCAP_LED_ON
>
> Notes:
> - The "motorola" vendor-prefix is added via rtc-next
> ---
> .../devicetree/bindings/leds/cpcap-leds.txt | 29 +++
> drivers/leds/Kconfig | 9 +
> drivers/leds/Makefile | 1 +
> drivers/leds/leds-cpcap.c | 239 +++++++++++++++++++++
> 4 files changed, 278 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/leds/cpcap-leds.txt
> create mode 100644 drivers/leds/leds-cpcap.c
>
> diff --git a/Documentation/devicetree/bindings/leds/cpcap-leds.txt b/Documentation/devicetree/bindings/leds/cpcap-leds.txt
> new file mode 100644
> index 000000000000..ebf7cdc7f70c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/leds/cpcap-leds.txt
I've changed cpcap-leds.txt to leds-cpcap.txt to match the prevailing
pattern for LED DT bindings file names.
Please let me know if you have any objections.
--
Best regards,
Jacek Anaszewski
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 1/2] leds: Add driver for Qualcomm LPG
From: Bjorn Andersson @ 2017-03-29 19:07 UTC (permalink / raw)
To: Rob Herring
Cc: Pavel Machek, Richard Purdie, Jacek Anaszewski, linux-kernel,
linux-leds, linux-arm-msm, Mark Rutland, devicetree
In-Reply-To: <20170329021734.afhqmfpmbcjyv7bu@rob-hp-laptop>
On Tue 28 Mar 19:17 PDT 2017, Rob Herring wrote:
> On Thu, Mar 23, 2017 at 09:37:49PM +0100, Pavel Machek wrote:
> > Hi!
> >
> > > The Light Pulse Generator (LPG) is a PWM-block found in a wide range of
> > > PMICs from Qualcomm. It can operate on fixed parameters or based on a
> > > lookup-table, altering the duty cycle over time - which provides the
> > > means for e.g. hardware assisted transitions of LED brightness.
> >
> > Ok, this is not first hardware that supports something like this. We
> > have similar hardware that can do blinking on Nokia N900 -- please
> > take a look at leds-lp55*.c
>
> And perhaps some alignment on the bindings too if the N900 has bindings.
>
There is a binding for ti,lp55xx, but there's nothing I can reuse from
that binding...because it's completely different hardware.
> > And it would be really good to provide hardware abstraction. We really
> > don't want to have different userspace for LPG and for N900 and for
>
> I'm interested in what this looks like as several AOSP platforms do
> tri-color LEDs with custom sysfs extensions.
>
How to model RGB LEDs has been discussed many times before and I was
hoping for that discussion to come to some conclusion during the last 2
years, but now I couldn't wait more - we need this driver for db820c.
With this driver, as with many existing, you will have 3 LEDs that you
set independently.
I did implement blinking by using the PWM straight off, so you can't set
brightness or synchronize the multiple channels. Perhaps this should be
changed to use the ramp generator.
To synchronize patterns I suggest that we extend the LUT binding to
describe groups and when any LPG trigger a restart of the pattern-walker
we trigger all that are grouped.
These two changes combined allows you to set brightness and blink with a
RGB-LED.
But I will have to dig up some hardware that uses the LPG for driving a
RGB-LED to be able to test this (and I do prefer that to be done with
some incremental patches at some later time, if acceptable).
> Do any of the Dragonboards have tri-color LEDs?
>
No.
Regards,
Bjorn
^ permalink raw reply
* [PATCH] Input: silead - list all supported compatible strings in binding document
From: Javier Martinez Canillas @ 2017-03-29 18:25 UTC (permalink / raw)
To: linux-kernel
Cc: Javier Martinez Canillas, devicetree, Robert Dolca, Hans de Goede,
Rob Herring, Dmitry Torokhov, linux-input, Mark Rutland
The driver contains compatible strings for different models, but the DT
binding doc only lists one of them. Add the remaining to the document.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
---
.../devicetree/bindings/input/touchscreen/silead_gsl1680.txt | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt b/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
index ce85ee508238..6aa625e0cb8d 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
@@ -1,7 +1,12 @@
* GSL 1680 touchscreen controller
Required properties:
-- compatible : "silead,gsl1680"
+- compatible : Must be one of the following, depending on the model:
+ "silead,gsl1680"
+ "silead,gsl1688"
+ "silead,gsl3670"
+ "silead,gsl3675"
+ "silead,gsl3692"
- reg : I2C slave address of the chip (0x40)
- interrupt-parent : a phandle pointing to the interrupt controller
serving the interrupt for this chip
--
2.9.3
^ permalink raw reply related
* Re: [PATCH v2 7/8] bus: brcmstb_gisb: add notifier handling
From: Mark Rutland @ 2017-03-29 18:17 UTC (permalink / raw)
To: Doug Berger
Cc: robh+dt, catalin.marinas, will.deacon, computersforpeace,
gregory.0xf0, f.fainelli, bcm-kernel-feedback-list,
wangkefeng.wang, james.morse, mingo, sandeepa.s.prabhu,
shijie.huang, linus.walleij, treding, jonathanh, olof, mirza.krak,
suzuki.poulose, bgolaszewski, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <e6bb68fa-dd2f-7d18-6031-b709f8fd162e@gmail.com>
On Wed, Mar 29, 2017 at 10:39:11AM -0700, Doug Berger wrote:
> On 03/29/2017 03:13 AM, Mark Rutland wrote:
> >> +static int dump_gisb_error(struct notifier_block *self, unsigned long v,
> >> + void *p)
> >> + return 0;
> >
> > I think this should be NOTIFY_OK.
> >
> I used dump_mem_limit() as a template and didn't catch this (work to
> do...). Upon review I think I would prefer NOTIFY_DONE since this call
> is opportunistic (i.e. it is taking the opportunity to check whether
> additional diagnostic data is available to display) and has no interest
> in affecting the overall handling of the event.
That's fine by me.
Does the distinction matter here?
Most notifer users treat NOTIFY_OK and NOTIFY_DONE as equivalent, and
notifier_call_chain only terminates when it sees NOTIFY_STOP_MASK.
[...]
> >> + if (list_is_singular(&brcmstb_gisb_arb_device_list)) {
> >> + register_die_notifier(&gisb_error_notifier);
> >> + atomic_notifier_chain_register(&panic_notifier_list,
> >> + &gisb_error_notifier);
> >
> > I don't think this is quite right. A notifier_block can only be
> > registered to one notifier chain at a time, and this has the potential
> > to corrupt both chains.
> >
> A VERY good point thanks for pointing this out.
>
> > I also think you only need to register the panic notifier. An SError
> > should always result in a panic.
> >
> That was my initial thought as well. However, testing revealed that the
> bad mode Oops actually exits the user space process and doesn't reach
> the panic so there was no helpful diagnostic message. This may be in
> line with your comments about insufficient fatality of failures in PATCH
> v2 6/8, but it actually is more in line with our desired behavior for
> the aborted write. Setting the notify on die gave us the result we are
> looking for, but as noted above I should have created a separate notifier.
>
> I had hoped that the same approach (i.e. die notifier) would remove the
> need for PATCH v2 6/8 as well, but I found that the Unhandled fault
> error didn't actually die from user mode.
In my mind it's a bug that we don't treat those errors more fatally.
I'll try to dig into that.
Thanks,
Mark.
^ permalink raw reply
* [PATCH v4 14/23] drivers/fsi: Add sysfs files for FSI master & slave accesses
From: Christopher Bostic @ 2017-03-29 17:49 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
mingo-H+wXaHxf7aLQT0dZR+AlfA,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
This change adds a 'raw' file for reads & writes, and a 'term' file for
the TERM command, and a 'break' file for issuing a BREAK.
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-9v/Yh3O1LlxrKZClcjn33gC/G2K4zDHf@public.gmane.org>
---
drivers/fsi/fsi-core.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 4359e26..f0f0556 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -294,6 +294,95 @@ static int fsi_slave_scan(struct fsi_slave *slave)
return 0;
}
+static ssize_t fsi_slave_sysfs_raw_read(struct file *file,
+ struct kobject *kobj, struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
+ size_t total_len, read_len;
+ int rc;
+
+ if (off < 0)
+ return -EINVAL;
+
+ if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+ return -EINVAL;
+
+ for (total_len = 0; total_len < count; total_len += read_len) {
+ read_len = min_t(size_t, count, 4);
+ read_len -= off & 0x3;
+
+ rc = fsi_slave_read(slave, off, buf + total_len, read_len);
+ if (rc)
+ return rc;
+
+ off += read_len;
+ }
+
+ return count;
+}
+
+static ssize_t fsi_slave_sysfs_raw_write(struct file *file,
+ struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
+ size_t total_len, write_len;
+ int rc;
+
+ if (off < 0)
+ return -EINVAL;
+
+ if (off > 0xffffffff || count > 0xffffffff || off + count > 0xffffffff)
+ return -EINVAL;
+
+ for (total_len = 0; total_len < count; total_len += write_len) {
+ write_len = min_t(size_t, count, 4);
+ write_len -= off & 0x3;
+
+ rc = fsi_slave_write(slave, off, buf + total_len, write_len);
+ if (rc)
+ return rc;
+
+ off += write_len;
+ }
+
+ return count;
+}
+
+static struct bin_attribute fsi_slave_raw_attr = {
+ .attr = {
+ .name = "raw",
+ .mode = 0600,
+ },
+ .size = 0,
+ .read = fsi_slave_sysfs_raw_read,
+ .write = fsi_slave_sysfs_raw_write,
+};
+
+static ssize_t fsi_slave_sysfs_term_write(struct file *file,
+ struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct fsi_slave *slave = to_fsi_slave(kobj_to_dev(kobj));
+ struct fsi_master *master = slave->master;
+
+ if (!master->term)
+ return -ENODEV;
+
+ master->term(master, slave->link, slave->id);
+ return count;
+}
+
+static struct bin_attribute fsi_slave_term_attr = {
+ .attr = {
+ .name = "term",
+ .mode = 0200,
+ },
+ .size = 0,
+ .write = fsi_slave_sysfs_term_write,
+};
+
/* Encode slave local bus echo delay */
static inline uint32_t fsi_smode_echodly(int x)
{
@@ -409,6 +498,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
return rc;
}
+ rc = device_create_bin_file(&slave->dev, &fsi_slave_raw_attr);
+ if (rc)
+ dev_warn(&slave->dev, "failed to create raw attr: %d\n", rc);
+
+ rc = device_create_bin_file(&slave->dev, &fsi_slave_term_attr);
+ if (rc)
+ dev_warn(&slave->dev, "failed to create term attr: %d\n", rc);
+
fsi_slave_scan(slave);
return 0;
}
@@ -523,6 +620,18 @@ static ssize_t master_rescan_store(struct device *dev,
static DEVICE_ATTR(rescan, 0200, NULL, master_rescan_store);
+static ssize_t master_break_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fsi_master *master = to_fsi_master(dev);
+
+ fsi_master_break(master, 0);
+
+ return count;
+}
+
+static DEVICE_ATTR(break, 0200, NULL, master_break_store);
+
int fsi_master_register(struct fsi_master *master)
{
int rc;
@@ -546,6 +655,13 @@ int fsi_master_register(struct fsi_master *master)
return rc;
}
+ rc = device_create_file(&master->dev, &dev_attr_break);
+ if (rc) {
+ device_unregister(&master->dev);
+ ida_simple_remove(&master_ida, master->idx);
+ return rc;
+ }
+
fsi_master_scan(master);
return 0;
--
1.8.2.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v4 23/23] drivers/fsi: Use asynchronous slave mode
From: Christopher Bostic @ 2017-03-29 17:43 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, rostedt-nx8X9YLhiw1AfugRpC6u6w,
mingo-H+wXaHxf7aLQT0dZR+AlfA,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Jeremy Kerr, joel-U3u1mxZcP9KHXe+LvDLADg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, andrew-zrmu5oMJ5Fs,
alistair-Y4h6yKqj69EXC2x5gXVKYQ,
benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r, Chris Bostic
In-Reply-To: <20170329174340.89109-1-cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
From: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
For slaves that are behind a software-clocked master, we want FSI CFAMs
to run asynchronously to the FSI clock, so set up our slaves to be in
async mode.
Signed-off-by: Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>
Signed-off-by: Chris Bostic <cbostic-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
drivers/fsi/fsi-core.c | 22 +++++++++++++++++++++-
drivers/fsi/fsi-master-gpio.c | 1 +
drivers/fsi/fsi-master.h | 2 ++
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
index 747d0e3..a6ed34f 100644
--- a/drivers/fsi/fsi-core.c
+++ b/drivers/fsi/fsi-core.c
@@ -47,6 +47,7 @@
#define FSI_SMODE 0x0 /* R/W: Mode register */
#define FSI_SISC 0x8 /* R/W: Interrupt condition */
#define FSI_SSTAT 0x14 /* R : Slave status */
+#define FSI_LLMODE 0x100 /* R/W: Link layer mode register */
/*
* SMODE fields
@@ -62,6 +63,11 @@
#define FSI_SMODE_LBCRR_SHIFT 8 /* Clk ratio shift */
#define FSI_SMODE_LBCRR_MASK 0xf /* Clk ratio mask */
+/*
+ * LLMODE fields
+ */
+#define FSI_LLMODE_ASYNC 0x1
+
#define FSI_SLAVE_SIZE_23b 0x800000
static DEFINE_IDA(master_ida);
@@ -560,8 +566,8 @@ static void fsi_slave_release(struct device *dev)
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{
+ uint32_t chip_id, llmode;
struct fsi_slave *slave;
- uint32_t chip_id;
uint8_t crc;
int rc;
@@ -597,6 +603,20 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
return -ENODEV;
}
+ /* If we're behind a master that doesn't provide a self-running bus
+ * clock, put the slave into async mode
+ */
+ if (master->flags & FSI_MASTER_FLAG_SWCLOCK) {
+ llmode = cpu_to_be32(FSI_LLMODE_ASYNC);
+ rc = fsi_master_write(master, link, id,
+ FSI_SLAVE_BASE + FSI_LLMODE,
+ &llmode, sizeof(llmode));
+ if (rc)
+ dev_warn(&master->dev,
+ "can't set llmode on slave:%02x:%02x %d\n",
+ link, id, rc);
+ }
+
/* We can communicate with a slave; create the slave device and
* register.
*/
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index 84d5595..f3fcede 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -573,6 +573,7 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
master->gpio_mux = gpio;
master->master.n_links = 1;
+ master->master.flags = FSI_MASTER_FLAG_SWCLOCK;
master->master.read = fsi_master_gpio_read;
master->master.write = fsi_master_gpio_write;
master->master.term = fsi_master_gpio_term;
diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
index d6a4885..fd39924 100644
--- a/drivers/fsi/fsi-master.h
+++ b/drivers/fsi/fsi-master.h
@@ -19,6 +19,8 @@
#include <linux/device.h>
+#define FSI_MASTER_FLAG_SWCLOCK 0x1
+
struct fsi_master {
struct device dev;
int idx;
--
1.8.2.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox