[ sunxi-dev ] Moving to 4.19.y Tested: H3, H5 (unstable?!), H6(no hdmi), R40 (no hdmi), A83T, A64, ... some wireless drivers were left. They need to be adjusted for 4.19.y

This commit is contained in:
Igor Pecovnik 2018-11-13 11:50:40 +01:00
parent 08caff89c3
commit ced3bf0a40
32 changed files with 2354 additions and 6697 deletions

View file

@ -23,9 +23,8 @@ if test -e ${devtype} ${devnum} ${prefix}armbianEnv.txt; then
env import -t ${load_addr} ${filesize}
fi
# No display driver yet
if test "${console}" = "display" || test "${console}" = "both"; then setenv consoleargs "console=tty1"; fi
if test "${console}" = "serial" || test "${console}" = "both"; then setenv consoleargs "${consoleargs} console=ttyS0,115200"; fi
if test "${console}" = "display" || test "${console}" = "both"; then setenv consoleargs "console=ttyS0,115200 console=tty1"; fi
if test "${console}" = "serial"; then setenv consoleargs "console=ttyS0,115200"; fi
# get PARTUUID of first partition on SD/eMMC it was loaded from
# mmc 0 is always mapped to device u-boot (2016.09+) was loaded from

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,7 @@ case $BRANCH in
KERNELPATCHDIR='sunxi-dev-h6'
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
KERNELBRANCH='branch:linux-4.18.y'
KERNELBRANCH='branch:linux-4.19.y'
KERNELDIR=$MAINLINE_KERNEL_DIR
KERNEL_USE_GCC='> 7.0'
KERNELPATCHDIR='sunxi-dev'

View file

@ -46,7 +46,7 @@ case $BRANCH in
ATF_TARGET_MAP='PLAT=sun50iw1p1 DEBUG=1 bl31;;build/sun50iw1p1/debug/bl31.bin'
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
KERNELBRANCH='branch:linux-4.18.y'
KERNELBRANCH='branch:linux-4.19.y'
KERNELDIR=$MAINLINE_KERNEL_DIR
KERNEL_USE_GCC='> 7.0'
KERNELPATCHDIR='sunxi-dev'

View file

@ -37,7 +37,7 @@ case $BRANCH in
dev)
KERNELSOURCE=$MAINLINE_KERNEL_SOURCE
KERNELBRANCH='branch:linux-4.18.y'
KERNELBRANCH='branch:linux-4.19.y'
KERNELDIR=$MAINLINE_KERNEL_DIR
KERNEL_USE_GCC='> 7.0'

View file

@ -1,444 +0,0 @@
Add an extra argument to ahci_platform_get_resources(), that is
for the bitmap representing the resource to get in this function.
Currently there is no resources to be defined, so all the callers set
'0' to the argument.
Suggested-by: Hans de Goede <hdegoede@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Patrice Chotard <patrice.chotard@st.com>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
---
drivers/ata/ahci_brcm.c | 2 +-
drivers/ata/ahci_ceva.c | 2 +-
drivers/ata/ahci_da850.c | 2 +-
drivers/ata/ahci_dm816.c | 2 +-
drivers/ata/ahci_imx.c | 2 +-
drivers/ata/ahci_mtk.c | 2 +-
drivers/ata/ahci_mvebu.c | 2 +-
drivers/ata/ahci_platform.c | 2 +-
drivers/ata/ahci_qoriq.c | 2 +-
drivers/ata/ahci_seattle.c | 2 +-
drivers/ata/ahci_st.c | 2 +-
drivers/ata/ahci_sunxi.c | 2 +-
drivers/ata/ahci_tegra.c | 2 +-
drivers/ata/ahci_xgene.c | 2 +-
drivers/ata/libahci_platform.c | 4 +++-
include/linux/ahci_platform.h | 2 +-
16 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c
index ea43081..f3d5577 100644
--- a/drivers/ata/ahci_brcm.c
+++ b/drivers/ata/ahci_brcm.c
@@ -425,7 +425,7 @@ static int brcm_ahci_probe(struct platform_device *pdev)
brcm_sata_phys_enable(priv);
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
hpriv->plat_data = priv;
diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
index 5ecc9d4..dc78c98 100644
--- a/drivers/ata/ahci_ceva.c
+++ b/drivers/ata/ahci_ceva.c
@@ -213,7 +213,7 @@ static int ceva_ahci_probe(struct platform_device *pdev)
cevapriv->ahci_pdev = pdev;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c
index 9b34dff..ebaa657 100644
--- a/drivers/ata/ahci_da850.c
+++ b/drivers/ata/ahci_da850.c
@@ -171,7 +171,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
u32 mpy;
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_dm816.c b/drivers/ata/ahci_dm816.c
index fbd827c..89509c3 100644
--- a/drivers/ata/ahci_dm816.c
+++ b/drivers/ata/ahci_dm816.c
@@ -148,7 +148,7 @@ static int ahci_dm816_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 6822e2f..b00799d 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -1127,7 +1127,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
return ret;
}
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_mtk.c b/drivers/ata/ahci_mtk.c
index 0ae6971..8bc1a26 100644
--- a/drivers/ata/ahci_mtk.c
+++ b/drivers/ata/ahci_mtk.c
@@ -142,7 +142,7 @@ static int mtk_ahci_probe(struct platform_device *pdev)
if (!plat)
return -ENOMEM;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index 72d90b4..f9cb51b 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -158,7 +158,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
const struct mbus_dram_target_info *dram;
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 99f9a89..5709273 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -43,7 +43,7 @@ static int ahci_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index cfdef4d..ce59253 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -250,7 +250,7 @@ static int ahci_qoriq_probe(struct platform_device *pdev)
struct resource *res;
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_seattle.c b/drivers/ata/ahci_seattle.c
index 1d31c0c..e57b6f9 100644
--- a/drivers/ata/ahci_seattle.c
+++ b/drivers/ata/ahci_seattle.c
@@ -164,7 +164,7 @@ static int ahci_seattle_probe(struct platform_device *pdev)
int rc;
struct ahci_host_priv *hpriv;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c
index bc345f2..21c5c44 100644
--- a/drivers/ata/ahci_st.c
+++ b/drivers/ata/ahci_st.c
@@ -156,7 +156,7 @@ static int st_ahci_probe(struct platform_device *pdev)
if (!drv_data)
return -ENOMEM;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
hpriv->plat_data = drv_data;
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index b264374..631610b 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -181,7 +181,7 @@ static int ahci_sunxi_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_tegra.c b/drivers/ata/ahci_tegra.c
index 64d8484..004f260 100644
--- a/drivers/ata/ahci_tegra.c
+++ b/drivers/ata/ahci_tegra.c
@@ -494,7 +494,7 @@ static int tegra_ahci_probe(struct platform_device *pdev)
int ret;
unsigned int i;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c
index ad58da7..7e157e1 100644
--- a/drivers/ata/ahci_xgene.c
+++ b/drivers/ata/ahci_xgene.c
@@ -759,7 +759,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
&xgene_ahci_v2_port_info };
int rc;
- hpriv = ahci_platform_get_resources(pdev);
+ hpriv = ahci_platform_get_resources(pdev, 0);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 30cc8f1..6abc1cd 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -332,6 +332,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
/**
* ahci_platform_get_resources - Get platform resources
* @pdev: platform device to get resources for
+ * @flags: bitmap representing the resource to get
*
* This function allocates an ahci_host_priv struct, and gets the following
* resources, storing a reference to them inside the returned struct:
@@ -345,7 +346,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
* RETURNS:
* The allocated ahci_host_priv on success, otherwise an ERR_PTR value
*/
-struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
+ unsigned int flags)
{
struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv;
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 1b0a17b..6490be1 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -30,7 +30,7 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv);
int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
struct ahci_host_priv *ahci_platform_get_resources(
- struct platform_device *pdev);
+ struct platform_device *pdev, unsigned int flags);
int ahci_platform_init_host(struct platform_device *pdev,
struct ahci_host_priv *hpriv,
const struct ata_port_info *pi_template,
From patchwork Wed Aug 22 12:13:02 2018
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [v2,2/3] ata: libahci_platform: add reset control support
X-Patchwork-Submitter: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
X-Patchwork-Id: 960932
X-Patchwork-Delegate: davem@davemloft.net
Message-Id: <1534939983-16264-3-git-send-email-hayashi.kunihiko@socionext.com>
To: Tejun Heo <tj@kernel.org>, Hans de Goede <hdegoede@redhat.com>,
Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>, linux-ide@vger.kernel.org
Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
Kunihiko Hayashi <hayashi.kunihiko@socionext.com>,
Thierry Reding <thierry.reding@gmail.com>
Date: Wed, 22 Aug 2018 21:13:02 +0900
From: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
List-Id: <linux-ide.vger.kernel.org>
Add support to get and control a list of resets for the device
as optional and shared. These resets must be kept de-asserted until
the device is enabled.
This is specified as shared because some SoCs like UniPhier series
have common reset controls with all ahci controller instances.
However, according to Thierry's view,
https://www.spinics.net/lists/linux-ide/msg55357.html
some hardware-specific drivers already use their own resets,
and the common reset make a path to occur double controls of resets.
The ahci_platform_get_resources() can get and control the reset
only when the second argument includes AHCI_PLATFORM_GET_RESETS bit.
Suggested-by: Hans de Goede <hdegoede@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/ata/ahci-platform.txt | 1 +
drivers/ata/ahci.h | 1 +
drivers/ata/libahci_platform.c | 31 ++++++++++++++++++----
include/linux/ahci_platform.h | 2 ++
4 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index c760ecb..f4006d3 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -30,6 +30,7 @@ compatible:
Optional properties:
- dma-coherent : Present if dma operations are coherent
- clocks : a list of phandle + clock specifier pairs
+- resets : a list of phandle + reset specifier pairs
- target-supply : regulator for SATA target power
- phys : reference to the SATA PHY node
- phy-names : must be "sata-phy"
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 1609eba..6a1515f 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -350,6 +350,7 @@ struct ahci_host_priv {
u32 em_msg_type; /* EM message type */
bool got_runtime_pm; /* Did we do pm_runtime_get? */
struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
+ struct reset_control *rsts; /* Optional */
struct regulator **target_pwrs; /* Optional */
/*
* If platform uses PHYs. There is a 1:1 relation between the port number and
diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
index 6abc1cd..6817143 100644
--- a/drivers/ata/libahci_platform.c
+++ b/drivers/ata/libahci_platform.c
@@ -25,6 +25,7 @@
#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#include <linux/of_platform.h>
+#include <linux/reset.h>
#include "ahci.h"
static void ahci_host_stop(struct ata_host *host);
@@ -195,7 +196,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
* following order:
* 1) Regulator
* 2) Clocks (through ahci_platform_enable_clks)
- * 3) Phys
+ * 3) Resets
+ * 4) Phys
*
* If resource enabling fails at any point the previous enabled resources
* are disabled in reverse order.
@@ -215,12 +217,19 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
if (rc)
goto disable_regulator;
- rc = ahci_platform_enable_phys(hpriv);
+ rc = reset_control_deassert(hpriv->rsts);
if (rc)
goto disable_clks;
+ rc = ahci_platform_enable_phys(hpriv);
+ if (rc)
+ goto disable_resets;
+
return 0;
+disable_resets:
+ reset_control_assert(hpriv->rsts);
+
disable_clks:
ahci_platform_disable_clks(hpriv);
@@ -238,13 +247,16 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
* This function disables all ahci_platform managed resources in the
* following order:
* 1) Phys
- * 2) Clocks (through ahci_platform_disable_clks)
- * 3) Regulator
+ * 2) Resets
+ * 3) Clocks (through ahci_platform_disable_clks)
+ * 4) Regulator
*/
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
{
ahci_platform_disable_phys(hpriv);
+ reset_control_assert(hpriv->rsts);
+
ahci_platform_disable_clks(hpriv);
ahci_platform_disable_regulators(hpriv);
@@ -341,7 +353,8 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
* 2) regulator for controlling the targets power (optional)
* 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
* or for non devicetree enabled platforms a single clock
- * 4) phys (optional)
+ * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
+ * 5) phys (optional)
*
* RETURNS:
* The allocated ahci_host_priv on success, otherwise an ERR_PTR value
@@ -395,6 +408,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
hpriv->clks[i] = clk;
}
+ if (flags & AHCI_PLATFORM_GET_RESETS) {
+ hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
+ if (IS_ERR(hpriv->rsts)) {
+ rc = PTR_ERR(hpriv->rsts);
+ goto err_out;
+ }
+ }
+
hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
/*
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index 6490be1..eaedca5f 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -43,4 +43,6 @@ int ahci_platform_resume_host(struct device *dev);
int ahci_platform_suspend(struct device *dev);
int ahci_platform_resume(struct device *dev);
+#define AHCI_PLATFORM_GET_RESETS 0x01
+
#endif /* _AHCI_PLATFORM_H */
Unlike SoC-specific driver, generic ahci_platform driver doesn't
have any chances to control resets.
This adds AHCI_PLATFORM_GET_RESETS to ahci_platform_get_resources()
on the generic driver to enable reset control support.
Suggested-by: Hans de Goede <hdegoede@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
---
drivers/ata/ahci_platform.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 5709273..ddd9308 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -43,7 +43,8 @@ static int ahci_probe(struct platform_device *pdev)
struct ahci_host_priv *hpriv;
int rc;
- hpriv = ahci_platform_get_resources(pdev, 0);
+ hpriv = ahci_platform_get_resources(pdev,
+ AHCI_PLATFORM_GET_RESETS);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);

File diff suppressed because it is too large Load diff

View file

@ -1,867 +0,0 @@
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 5a9319ad8861..288b4cbc255e 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -399,6 +399,7 @@ Required properties:
* allwinner,sun8i-a33-display-engine
* allwinner,sun8i-a83t-display-engine
* allwinner,sun8i-h3-display-engine
+ * allwinner,sun8i-r40-display-engine
* allwinner,sun8i-v3s-display-engine
* allwinner,sun9i-a80-display-engine
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 6ddf4eaccb40..a15feb807393 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -417,6 +417,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun8i-a33-display-engine" },
{ .compatible = "allwinner,sun8i-a83t-display-engine" },
{ .compatible = "allwinner,sun8i-h3-display-engine" },
+ { .compatible = "allwinner,sun8i-r40-display-engine" },
{ .compatible = "allwinner,sun8i-v3s-display-engine" },
{ .compatible = "allwinner,sun9i-a80-display-engine" },
{ }
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index c95a59aac48f..2afb079a3776 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -102,8 +102,7 @@
};
de: display-engine {
- compatible = "allwinner,sun8i-r40-display-engine",
- "allwinner,sun8i-h3-display-engine";
+ compatible = "allwinner,sun8i-r40-display-engine";
allwinner,pipelines = <&mixer0>, <&mixer1>;
status = "disabled";
};
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index 8da0460e0028..9fb51940156f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -44,15 +44,20 @@ static int sun8i_tcon_top_get_connected_ep_id(struct device_node *node,
}
static struct clk_hw *sun8i_tcon_top_register_gate(struct device *dev,
- struct clk *parent,
+ const char *parent,
void __iomem *regs,
spinlock_t *lock,
u8 bit, int name_index)
{
const char *clk_name, *parent_name;
- int ret;
+ int ret, index;
+
+ index = of_property_match_string(dev->of_node, "clock-names", parent);
+ if (IS_ERR_VALUE(index))
+ return ERR_PTR(index);
+
+ parent_name = of_clk_get_parent_name(dev->of_node, index);
- parent_name = __clk_get_name(parent);
ret = of_property_read_string_index(dev->of_node,
"clock-output-names", name_index,
&clk_name);
@@ -69,7 +74,6 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
void *data)
{
struct platform_device *pdev = to_platform_device(dev);
- struct clk *dsi, *tcon_tv0, *tcon_tv1, *tve0, *tve1;
struct clk_hw_onecell_data *clk_data;
struct sun8i_tcon_top *tcon_top;
bool mixer0_unused = false;
@@ -103,36 +107,6 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
return PTR_ERR(tcon_top->bus);
}
- dsi = devm_clk_get(dev, "dsi");
- if (IS_ERR(dsi)) {
- dev_err(dev, "Couldn't get the dsi clock\n");
- return PTR_ERR(dsi);
- }
-
- tcon_tv0 = devm_clk_get(dev, "tcon-tv0");
- if (IS_ERR(tcon_tv0)) {
- dev_err(dev, "Couldn't get the tcon-tv0 clock\n");
- return PTR_ERR(tcon_tv0);
- }
-
- tcon_tv1 = devm_clk_get(dev, "tcon-tv1");
- if (IS_ERR(tcon_tv1)) {
- dev_err(dev, "Couldn't get the tcon-tv1 clock\n");
- return PTR_ERR(tcon_tv1);
- }
-
- tve0 = devm_clk_get(dev, "tve0");
- if (IS_ERR(tve0)) {
- dev_err(dev, "Couldn't get the tve0 clock\n");
- return PTR_ERR(tve0);
- }
-
- tve1 = devm_clk_get(dev, "tve1");
- if (IS_ERR(tve1)) {
- dev_err(dev, "Couldn't get the tve1 clock\n");
- return PTR_ERR(tve1);
- }
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
if (IS_ERR(regs))
@@ -203,17 +177,17 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
* to TVE clock parent.
*/
clk_data->hws[CLK_TCON_TOP_TV0] =
- sun8i_tcon_top_register_gate(dev, tcon_tv0, regs,
+ sun8i_tcon_top_register_gate(dev, "tcon-tv0", regs,
&tcon_top->reg_lock,
TCON_TOP_TCON_TV0_GATE, 0);
clk_data->hws[CLK_TCON_TOP_TV1] =
- sun8i_tcon_top_register_gate(dev, tcon_tv1, regs,
+ sun8i_tcon_top_register_gate(dev, "tcon-tv1", regs,
&tcon_top->reg_lock,
TCON_TOP_TCON_TV1_GATE, 1);
clk_data->hws[CLK_TCON_TOP_DSI] =
- sun8i_tcon_top_register_gate(dev, dsi, regs,
+ sun8i_tcon_top_register_gate(dev, "dsi", regs,
&tcon_top->reg_lock,
TCON_TOP_TCON_DSI_GATE, 2);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index aacc841d3dc6..3fb084f802e2 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -811,6 +811,7 @@ sun4i_tcon_find_engine_traverse(struct sun4i_drv *drv,
* remote output id. If this for some reason can't be done, 0
* is used as input port id.
*/
+ of_node_put(port);
port = of_graph_get_remote_port(ep);
if (!of_property_read_u32(port, "reg", &reg) && reg > 0)
reg -= 1;
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 288b4cbc255e..7e2451396a28 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -147,6 +147,7 @@ Required properties:
* allwinner,sun8i-a33-tcon
* allwinner,sun8i-a83t-tcon-lcd
* allwinner,sun8i-a83t-tcon-tv
+ * allwinner,sun8i-r40-tcon-tv
* allwinner,sun8i-v3s-tcon
* allwinner,sun9i-a80-tcon-lcd
* allwinner,sun9i-a80-tcon-tv
@@ -181,7 +182,7 @@ For TCONs with channel 0, there is one more clock required:
For TCONs with channel 1, there is one more clock required:
- 'tcon-ch1': The clock driving the TCON channel 1
-When TCON support LVDS (all TCONs except TV TCON on A83T and those found
+When TCON support LVDS (all TCONs except TV TCONs on A83T, R40 and those found
in A13, H3, H5 and V3s SoCs), you need one more reset line:
- 'lvds': The reset line driving the LVDS logic
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 3459b9ec56c9..21dc9ebad0b4 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -53,22 +53,14 @@ static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm,
struct device_node *port, *ep, *remote, *remote_port;
u32 crtcs = 0;
- port = of_graph_get_port_by_id(node, 0);
- if (!port)
- return 0;
-
- ep = of_get_next_available_child(port, NULL);
- if (!ep)
- return 0;
-
- remote = of_graph_get_remote_port_parent(ep);
+ remote = of_graph_get_remote_node(node, 0, -1);
if (!remote)
return 0;
if (sun8i_dw_hdmi_node_is_tcon_top(remote)) {
port = of_graph_get_port_by_id(remote, 4);
if (!port)
- return 0;
+ goto crtcs_exit;
for_each_child_of_node(port, ep) {
remote_port = of_graph_get_remote_port(ep);
@@ -81,6 +73,9 @@ static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm,
crtcs = drm_of_find_possible_crtcs(drm, node);
}
+crtcs_exit:
+ of_node_put(remote);
+
return crtcs;
}
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 2afb079a3776..1dd088d82773 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -576,9 +576,12 @@
#size-cells = <0>;
tcon_top_mixer0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0>;
- tcon_top_mixer0_in_mixer0: endpoint {
+ tcon_top_mixer0_in_mixer0: endpoint@0 {
+ reg = <0>;
remote-endpoint = <&mixer0_out_tcon_top>;
};
};
@@ -606,9 +609,12 @@
};
tcon_top_mixer1_in: port@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <2>;
- tcon_top_mixer1_in_mixer1: endpoint {
+ tcon_top_mixer1_in_mixer1: endpoint@1 {
+ reg = <1>;
remote-endpoint = <&mixer1_out_tcon_top>;
};
};
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index ee8febb25903..11221f96746d 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -23,6 +23,7 @@
#include <linux/dma-mapping.h>
#include <linux/reset.h>
#include <linux/of_device.h>
+#include <linux/of_graph.h>
#include "sun4i_drv.h"
#include "sun8i_mixer.h"
@@ -322,6 +323,37 @@ static struct regmap_config sun8i_mixer_regmap_config = {
.max_register = 0xbfffc, /* guessed */
};
+static int sun8i_mixer_of_get_id(struct device_node *node)
+{
+ struct device_node *port, *ep;
+ int ret = -EINVAL;
+
+ /* output is port 1 */
+ port = of_graph_get_port_by_id(node, 1);
+ if (!port)
+ return -EINVAL;
+
+ /* try finding an upstream endpoint */
+ for_each_available_child_of_node(port, ep) {
+ struct device_node *remote;
+ u32 reg;
+
+ remote = of_graph_get_remote_endpoint(ep);
+ if (!remote)
+ continue;
+
+ ret = of_property_read_u32(remote, "reg", &reg);
+ if (ret)
+ continue;
+
+ ret = reg;
+ }
+
+ of_node_put(port);
+
+ return ret;
+}
+
static int sun8i_mixer_bind(struct device *dev, struct device *master,
void *data)
{
@@ -353,8 +385,7 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
dev_set_drvdata(dev, mixer);
mixer->engine.ops = &sun8i_engine_ops;
mixer->engine.node = dev->of_node;
- /* The ID of the mixer currently doesn't matter */
- mixer->engine.id = -1;
+ mixer->engine.id = sun8i_mixer_of_get_id(dev->of_node);
mixer->cfg = of_device_get_match_data(dev);
if (!mixer->cfg)
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index 9fb51940156f..c09b15b64192 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -14,6 +14,79 @@
#include "sun8i_tcon_top.h"
+static bool sun8i_tcon_top_node_is_tcon_top(struct device_node *node)
+{
+ return !!of_match_node(sun8i_tcon_top_of_table, node);
+}
+
+int sun8i_tcon_top_set_hdmi_src(struct device *dev, int tcon)
+{
+ struct sun8i_tcon_top *tcon_top = dev_get_drvdata(dev);
+ unsigned long flags;
+ u32 val;
+
+ if (!sun8i_tcon_top_node_is_tcon_top(dev->of_node)) {
+ dev_err(dev, "Device is not TCON TOP!\n");
+ return -EINVAL;
+ }
+
+ if (tcon < 2 || tcon > 3) {
+ dev_err(dev, "TCON index must be 2 or 3!\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&tcon_top->reg_lock, flags);
+
+ val = readl(tcon_top->regs + TCON_TOP_GATE_SRC_REG);
+ val &= ~TCON_TOP_HDMI_SRC_MSK;
+ val |= FIELD_PREP(TCON_TOP_HDMI_SRC_MSK, tcon - 1);
+ writel(val, tcon_top->regs + TCON_TOP_GATE_SRC_REG);
+
+ spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(sun8i_tcon_top_set_hdmi_src);
+
+int sun8i_tcon_top_de_config(struct device *dev, int mixer, int tcon)
+{
+ struct sun8i_tcon_top *tcon_top = dev_get_drvdata(dev);
+ unsigned long flags;
+ u32 reg;
+
+ if (!sun8i_tcon_top_node_is_tcon_top(dev->of_node)) {
+ dev_err(dev, "Device is not TCON TOP!\n");
+ return -EINVAL;
+ }
+
+ if (mixer > 1) {
+ dev_err(dev, "Mixer index is too high!\n");
+ return -EINVAL;
+ }
+
+ if (tcon > 3) {
+ dev_err(dev, "TCON index is too high!\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&tcon_top->reg_lock, flags);
+
+ reg = readl(tcon_top->regs + TCON_TOP_PORT_SEL_REG);
+ if (mixer == 0) {
+ reg &= ~TCON_TOP_PORT_DE0_MSK;
+ reg |= FIELD_PREP(TCON_TOP_PORT_DE0_MSK, tcon);
+ } else {
+ reg &= ~TCON_TOP_PORT_DE1_MSK;
+ reg |= FIELD_PREP(TCON_TOP_PORT_DE1_MSK, tcon);
+ }
+ writel(reg, tcon_top->regs + TCON_TOP_PORT_SEL_REG);
+
+ spin_unlock_irqrestore(&tcon_top->reg_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(sun8i_tcon_top_de_config);
+
static int sun8i_tcon_top_get_connected_ep_id(struct device_node *node,
int port_id)
{
@@ -109,6 +182,7 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res);
+ tcon_top->regs = regs;
if (IS_ERR(regs))
return PTR_ERR(regs);
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.h b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
index 39838bbfeaee..0390584a330e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.h
@@ -26,6 +26,7 @@
struct sun8i_tcon_top {
struct clk *bus;
struct clk_hw_onecell_data *clk_data;
+ void __iomem *regs;
struct reset_control *rst;
/*
@@ -37,4 +38,7 @@ struct sun8i_tcon_top {
extern const struct of_device_id sun8i_tcon_top_of_table[];
+int sun8i_tcon_top_set_hdmi_src(struct device *dev, int tcon);
+int sun8i_tcon_top_de_config(struct device *dev, int mixer, int tcon);
+
#endif /* _SUN8I_TCON_TOP_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3fb084f802e2..44ec3a3d4d64 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -35,6 +35,7 @@
#include "sun4i_rgb.h"
#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"
+#include "sun8i_tcon_top.h"
#include "sunxi_engine.h"
static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder)
@@ -880,6 +881,36 @@ static struct sunxi_engine *sun4i_tcon_get_engine_by_id(struct sun4i_drv *drv,
return ERR_PTR(-EINVAL);
}
+static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
+{
+ struct device_node *remote;
+ bool ret = false;
+
+ remote = of_graph_get_remote_node(node, 0, -1);
+ if (remote) {
+ ret = !!of_match_node(sun8i_tcon_top_of_table, remote);
+ of_node_put(remote);
+ }
+
+ return ret;
+}
+
+static int sun4i_tcon_get_index(struct sun4i_drv *drv)
+{
+ struct list_head *pos;
+ int size = 0;
+
+ /*
+ * Because TCON is added to the list at the end of the probe
+ * (after this function is called), index of the current TCON
+ * will be same as current TCON list size.
+ */
+ list_for_each(pos, &drv->tcon_list)
+ ++size;
+
+ return size;
+}
+
/*
* On SoCs with the old display pipeline design (Display Engine 1.0),
* we assumed the TCON was always tied to just one backend. However
@@ -928,8 +959,24 @@ static struct sunxi_engine *sun4i_tcon_find_engine(struct sun4i_drv *drv,
* connections between the backend and TCON?
*/
if (of_get_child_count(port) > 1) {
- /* Get our ID directly from an upstream endpoint */
- int id = sun4i_tcon_of_get_id_from_port(port);
+ int id;
+
+ /*
+ * When pipeline has the same number of TCONs and engines which
+ * are represented by frontends/backends (DE1) or mixers (DE2),
+ * we match them by their respective IDs. However, if pipeline
+ * contains TCON TOP, chances are that there are either more
+ * TCONs than engines (R40) or TCONs with non-consecutive ids.
+ * (H6). In that case it's easier just use TCON index in list
+ * as an id. That means that on R40, any 2 TCONs can be enabled
+ * in DT out of 4 (there are 2 mixers). Due to the design of
+ * TCON TOP, remaining 2 TCONs can't be connected to anything
+ * anyway.
+ */
+ if (sun4i_tcon_connected_to_tcon_top(node))
+ id = sun4i_tcon_get_index(drv);
+ else
+ id = sun4i_tcon_of_get_id_from_port(port);
/* Get our engine by matching our ID */
engine = sun4i_tcon_get_engine_by_id(drv, id);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 44ec3a3d4d64..5676b7faaca0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1291,6 +1291,40 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
return 0;
}
+static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
+ const struct drm_encoder *encoder)
+{
+ struct device_node *port, *remote;
+ struct platform_device *pdev;
+ int id, ret;
+
+ /* find TCON TOP platform device and TCON id */
+
+ port = of_graph_get_port_by_id(tcon->dev->of_node, 0);
+ if (!port)
+ return -EINVAL;
+
+ id = sun4i_tcon_of_get_id_from_port(port);
+ of_node_put(port);
+
+ remote = of_graph_get_remote_node(tcon->dev->of_node, 0, -1);
+ if (!remote)
+ return -EINVAL;
+
+ pdev = of_find_device_by_node(remote);
+ of_node_put(remote);
+ if (!pdev)
+ return -EINVAL;
+
+ if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
+ ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
+ if (ret)
+ return ret;
+ }
+
+ return sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
+}
+
static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
.has_channel_0 = true,
.has_channel_1 = true,
@@ -1338,6 +1372,11 @@ static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
.has_channel_1 = true,
};
+static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
+ .has_channel_1 = true,
+ .set_mux = sun8i_r40_tcon_tv_set_mux,
+};
+
static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
.has_channel_0 = true,
};
@@ -1362,6 +1401,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
{ .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
{ .compatible = "allwinner,sun8i-a83t-tcon-tv", .data = &sun8i_a83t_tv_quirks },
+ { .compatible = "allwinner,sun8i-r40-tcon-tv", .data = &sun8i_r40_tv_quirks },
{ .compatible = "allwinner,sun8i-v3s-tcon", .data = &sun8i_v3s_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-lcd", .data = &sun9i_a80_tcon_lcd_quirks },
{ .compatible = "allwinner,sun9i-a80-tcon-tv", .data = &sun9i_a80_tcon_tv_quirks },
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 1dd088d82773..6b4fe8eeee99 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -666,8 +666,7 @@
};
tcon_tv0: lcd-controller@1c73000 {
- compatible = "allwinner,sun8i-r40-tcon-tv",
- "allwinner,sun8i-a83t-tcon-tv";
+ compatible = "allwinner,sun8i-r40-tcon-tv";
reg = <0x01c73000 0x1000>;
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON_TV0>, <&tcon_top 0>;
@@ -690,8 +689,7 @@
};
tcon_tv1: lcd-controller@1c74000 {
- compatible = "allwinner,sun8i-r40-tcon-tv",
- "allwinner,sun8i-a83t-tcon-tv";
+ compatible = "allwinner,sun8i-r40-tcon-tv";
reg = <0x01c74000 0x1000>;
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON_TV1>, <&tcon_top 1>;
diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index 4f3d583183dc..737cf01b1acd 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -251,26 +251,6 @@
regulator-name = "vcc-wifi";
};
-&tcon_top_hdmi_in_tcon_tv0 {
- remote-endpoint = <&tcon_tv0_out_tcon_top>;
-};
-
-&tcon_top_mixer0_out_tcon_tv0 {
- remote-endpoint = <&tcon_tv0_in_tcon_top>;
-};
-
-&tcon_tv0_in {
- tcon_tv0_in_tcon_top: endpoint {
- remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
- };
-};
-
-&tcon_tv0_out {
- tcon_tv0_out_tcon_top: endpoint {
- remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
- };
-};
-
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pb_pins>;
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 6b4fe8eeee99..e5c7e4804384 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -601,10 +601,12 @@
tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
};
tcon_top_mixer0_out_tcon_tv1: endpoint@3 {
reg = <3>;
+ remote-endpoint = <&tcon_tv1_in_tcon_top_mixer0>;
};
};
@@ -634,10 +636,12 @@
tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
};
tcon_top_mixer1_out_tcon_tv1: endpoint@3 {
reg = <3>;
+ remote-endpoint = <&tcon_tv1_in_tcon_top_mixer1>;
};
};
@@ -648,10 +652,12 @@
tcon_top_hdmi_in_tcon_tv0: endpoint@0 {
reg = <0>;
+ remote-endpoint = <&tcon_tv0_out_tcon_top>;
};
tcon_top_hdmi_in_tcon_tv1: endpoint@1 {
reg = <1>;
+ remote-endpoint = <&tcon_tv1_out_tcon_top>;
};
};
@@ -679,11 +685,30 @@
#size-cells = <0>;
tcon_tv0_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0>;
+
+ tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+ };
+
+ tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
+ };
};
tcon_tv0_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <1>;
+
+ tcon_tv0_out_tcon_top: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+ };
};
};
};
@@ -702,11 +727,30 @@
#size-cells = <0>;
tcon_tv1_in: port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <0>;
+
+ tcon_tv1_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv1>;
+ };
+
+ tcon_tv1_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv1>;
+ };
};
tcon_tv1_out: port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
reg = <1>;
+
+ tcon_tv1_out_tcon_top: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv1>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index 737cf01b1acd..c39b9169ea64 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -251,6 +251,10 @@
regulator-name = "vcc-wifi";
};
+&tcon_tv0 {
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pb_pins>;
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index e5c7e4804384..e2cbd4f645c5 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -679,6 +679,7 @@
clock-names = "ahb", "tcon-ch1";
resets = <&ccu RST_BUS_TCON_TV0>;
reset-names = "lcd";
+ status = "disabled";
ports {
#address-cells = <1>;
@@ -721,6 +722,7 @@
clock-names = "ahb", "tcon-ch1";
resets = <&ccu RST_BUS_TCON_TV1>;
reset-names = "lcd";
+ status = "disabled";
ports {
#address-cells = <1>;
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index c09b15b64192..78795d6cb174 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -87,34 +87,6 @@ int sun8i_tcon_top_de_config(struct device *dev, int mixer, int tcon)
}
EXPORT_SYMBOL(sun8i_tcon_top_de_config);
-static int sun8i_tcon_top_get_connected_ep_id(struct device_node *node,
- int port_id)
-{
- struct device_node *ep, *remote, *port;
- struct of_endpoint endpoint;
-
- port = of_graph_get_port_by_id(node, port_id);
- if (!port)
- return -ENOENT;
-
- for_each_available_child_of_node(port, ep) {
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote)
- continue;
-
- if (of_device_is_available(remote)) {
- of_graph_parse_endpoint(ep, &endpoint);
-
- of_node_put(remote);
-
- return endpoint.id;
- }
-
- of_node_put(remote);
- }
-
- return -ENOENT;
-}
static struct clk_hw *sun8i_tcon_top_register_gate(struct device *dev,
const char *parent,
@@ -149,11 +121,9 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
struct platform_device *pdev = to_platform_device(dev);
struct clk_hw_onecell_data *clk_data;
struct sun8i_tcon_top *tcon_top;
- bool mixer0_unused = false;
struct resource *res;
void __iomem *regs;
- int ret, i, id;
- u32 val;
+ int ret, i;
tcon_top = devm_kzalloc(dev, sizeof(*tcon_top), GFP_KERNEL);
if (!tcon_top)
@@ -198,49 +168,12 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
goto err_assert_reset;
}
- val = 0;
-
- /* check if HDMI mux output is connected */
- if (sun8i_tcon_top_get_connected_ep_id(dev->of_node, 5) >= 0) {
- /* find HDMI input endpoint id, if it is connected at all*/
- id = sun8i_tcon_top_get_connected_ep_id(dev->of_node, 4);
- if (id >= 0)
- val = FIELD_PREP(TCON_TOP_HDMI_SRC_MSK, id + 1);
- else
- DRM_DEBUG_DRIVER("TCON TOP HDMI input is not connected\n");
- } else {
- DRM_DEBUG_DRIVER("TCON TOP HDMI output is not connected\n");
- }
-
- writel(val, regs + TCON_TOP_GATE_SRC_REG);
-
- val = 0;
-
- /* process mixer0 mux output */
- id = sun8i_tcon_top_get_connected_ep_id(dev->of_node, 1);
- if (id >= 0) {
- val = FIELD_PREP(TCON_TOP_PORT_DE0_MSK, id);
- } else {
- DRM_DEBUG_DRIVER("TCON TOP mixer0 output is not connected\n");
- mixer0_unused = true;
- }
-
- /* process mixer1 mux output */
- id = sun8i_tcon_top_get_connected_ep_id(dev->of_node, 3);
- if (id >= 0) {
- val |= FIELD_PREP(TCON_TOP_PORT_DE1_MSK, id);
-
- /*
- * mixer0 mux has priority over mixer1 mux. We have to
- * make sure mixer0 doesn't overtake TCON from mixer1.
- */
- if (mixer0_unused && id == 0)
- val |= FIELD_PREP(TCON_TOP_PORT_DE0_MSK, 1);
- } else {
- DRM_DEBUG_DRIVER("TCON TOP mixer1 output is not connected\n");
- }
-
- writel(val, regs + TCON_TOP_PORT_SEL_REG);
+ /*
+ * Default register values might have some reserved bits set, which
+ * prevents TCON TOP from working properly. Set them to 0 here.
+ */
+ writel(0, regs + TCON_TOP_GATE_SRC_REG);
+ writel(0, regs + TCON_TOP_PORT_SEL_REG);
/*
* TCON TOP has two muxes, which select parent clock for each TCON TV
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 7e2451396a28..f8773ecb7525 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -101,9 +101,9 @@ DWC HDMI PHY
Required properties:
- compatible: value must be one of:
- * allwinner,sun50i-a64-hdmi-phy
* allwinner,sun8i-a83t-hdmi-phy
* allwinner,sun8i-h3-hdmi-phy
+ * allwinner,sun50i-a64-hdmi-phy
- reg: base address and size of memory-mapped region
- clocks: phandles to the clocks feeding the HDMI PHY
* bus: the HDMI PHY interface clock

View file

@ -1,280 +0,0 @@
diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index c0f444e..3c032fb 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-nanopi-a64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-olinuxino.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinebook.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
new file mode 100644
index 00000000..07fc30ba
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+ model = "Pinebook";
+ compatible = "pine64,pinebook", "allwinner,sun50i-a64";
+
+ aliases {
+ serial0 = &uart0;
+ ethernet0 = &rtl8723cs;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+
+ framebuffer-lcd {
+ panel-supply = <&reg_dc1sw>;
+ dvdd25-supply = <&reg_dldo2>;
+ dvdd12-supply = <&reg_fldo1>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ lid_switch {
+ label = "Lid Switch";
+ gpios = <&r_pio 0 12 GPIO_ACTIVE_LOW>; /* PL12 */
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ wifi_pwrseq: wifi_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+ };
+};
+
+&ehci0 {
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ vmmc-supply = <&reg_dcdc1>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+ disable-wp;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ vmmc-supply = <&reg_dldo4>;
+ vqmmc-supply = <&reg_eldo1>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ rtl8723cs: wifi@1 {
+ reg = <1>;
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ vmmc-supply = <&reg_dcdc1>;
+ vqmmc-supply = <&reg_eldo1>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
+&ohci0 {
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&r_rsb {
+ status = "okay";
+
+ axp803: pmic@3a3 {
+ compatible = "x-powers,axp803";
+ reg = <0x3a3>;
+ interrupt-parent = <&r_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+#include "axp803.dtsi"
+
+&reg_aldo1 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-name = "vcc-csi";
+};
+
+&reg_aldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-pl";
+};
+
+&reg_aldo3 {
+ regulator-always-on;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dc1sw {
+ regulator-name = "vcc-lcd";
+};
+
+&reg_dcdc1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-name = "vdd-cpux";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc5 {
+ regulator-always-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-hdmi";
+};
+
+&reg_dldo2 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-name = "vcc-edp";
+};
+
+&reg_dldo3 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "avdd-csi";
+};
+
+&reg_dldo4 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-wifi";
+};
+
+&reg_eldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "cpvdd";
+};
+
+&reg_eldo3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vdd-1v8-csi";
+};
+
+&reg_fldo1 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-name = "vcc-1v2-hsic";
+};
+
+&reg_fldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-cpus";
+};
+
+&reg_ldo_io0 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-usb";
+ status = "okay";
+};
+
+&reg_rtc_ldo {
+ regulator-name = "vcc-rtc";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "host";
+};
+
+&usbphy {
+ usb0_vbus-supply = <&reg_ldo_io0>;
+ usb1_vbus-supply = <&reg_ldo_io0>;
+ status = "okay";
+};
\ No newline at end of file

View file

@ -1,56 +0,0 @@
Subject: [PATCH 1/2] arm64: allwinner: a64: change TERES-I DLDO3's name to start with "vdd"
Originally the name of the DLDO3 regulator on TERES-I is "eDP12", which
is not consistent with other regulator names.
Change it to "vdd-edp", in order to make it more consistent.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
index d9baab3dc96b..02fecc42440c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
@@ -210,7 +210,7 @@
&reg_dldo3 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
- regulator-name = "eDP12";
+ regulator-name = "vdd-edp";
};
&reg_dldo4 {
Subject: [PATCH 2/2] arm64: allwinner: a64: allow laptops to wake up from lid
Currently all ARM kernels will have s2idle enabled if CONFIG_SUSPEND is
present. In this case if the lid is closed, systemd-logind will enter
s2idle mode by default; however there's no possible wakeup source
defined, so the system will enter a forever idle.
Add the lid itself as a wakeup source, thus the system can wakeup when
the lid is opened.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
This patch is not related with the first patch, and have no dependency.
arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts | 1 +
arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
index 02fecc42440c..33f78e745815 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-teres-i.dts
@@ -38,6 +38,7 @@
gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
linux,input-type = <EV_SW>;
linux,code = <SW_LID>;
+ wakeup-source;
};
};

View file

@ -0,0 +1,19 @@
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index fd6681ab9..89e0837d7 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -216,6 +216,14 @@
bias-pull-up;
};
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ function = "mmc1";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
mmc2_pins: mmc2-pins {
pins = "PC1", "PC4", "PC5", "PC6",
"PC7", "PC8", "PC9", "PC10",

View file

@ -71,9 +71,9 @@ index 7f3080437be6..ace8628478ab 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -95,3 +95,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/
obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
obj-y += meson/
obj-y += cros-ec-cec/
+
+obj-$(CONFIG_VIDEO_SUN6I_CSI) += sunxi/sun6i-csi/
diff --git a/drivers/media/platform/sunxi/sun6i-csi/Kconfig b/drivers/media/platform/sunxi/sun6i-csi/Kconfig

View file

@ -1,211 +0,0 @@
From 05a8864b512a6555c92e693a0cfaf4af177105f4 Mon Sep 17 00:00:00 2001
From: wuweidong <625769020@qq.com>
Date: Mon, 26 Mar 2018 18:57:58 +0800
Subject: [PATCH 45/60] media: ov5640: Support 5M(2542x1944) resolution
---
drivers/media/i2c/ov5640.c | 153 +++++++++++++++++++++++++++++++++++++
1 file changed, 153 insertions(+)
diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
index e2dd352224c7..aa204e50c045 100644
--- a/drivers/media/i2c/ov5640.c
+++ b/drivers/media/i2c/ov5640.c
@@ -105,6 +105,8 @@ enum ov5640_mode_id {
enum ov5640_frame_rate {
OV5640_15_FPS = 0,
OV5640_30_FPS,
+ OV5640_7P5_FPS,
+ OV5640_5_FPS,
OV5640_NUM_FRAMERATES,
};
@@ -132,6 +134,8 @@ MODULE_PARM_DESC(virtual_channel,
static const int ov5640_framerates[] = {
[OV5640_15_FPS] = 15,
[OV5640_30_FPS] = 30,
+ [OV5640_7P5_FPS] = 7,
+ [OV5640_5_FPS] = 5,
};
/* regulator supplies */
@@ -703,6 +707,42 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
{0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
};
+static const struct reg_value ov5640_setting_7p5_fps_1080P_1920_1080[] = {
+ {0x3008, 0x42, 0, 0},
+ {0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0}, {0x3814, 0x11, 0, 0},
+ {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
+ {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
+ {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
+ {0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
+ {0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
+ {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
+ {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
+ {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
+ {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
+ {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0}, {0x4713, 0x03, 0, 0},
+ {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0}, {0x3035, 0x41, 0, 0},
+ {0x3036, 0x54, 0, 1}, {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
+ {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
+ {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
+ {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
+ {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
+ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
+ {0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
+ {0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
+ {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
+ {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
+ {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
+ {0x3a15, 0x60, 0, 0}, {0x4713, 0x02, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
+ {0x4005, 0x1a, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3503, 0, 0, 0},
+};
+
static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
{0x3820, 0x40, 0, 0}, {0x3821, 0x06, 0, 0},
{0x3035, 0x21, 0, 0}, {0x3036, 0x54, 0, 0}, {0x3c07, 0x08, 0, 0},
@@ -725,6 +765,103 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
{0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 70},
};
+static const struct reg_value ov5640_setting_5_fps_QSXGA_2592_1944[] = {
+ // YUV 2592x1944 5fps
+ // Input Clock = 24Mhz, PCLK = 56MHz
+ {0x3035, 0x21, 0, 0},
+ // PLL
+ {0x3036, 0x46, 0, 0},
+ // PLL
+ {0x3c07, 0x07, 0, 0},
+ // lightm eter 1 threshold[7:0]
+ {0x3820, 0x40, 0, 0},
+ // flip
+ {0x3821, 0x06, 0, 0},
+ // mirror
+ {0x3814, 0x11, 0, 0},
+ // timing X inc
+ {0x3815, 0x11, 0, 0},
+ // timing Y inc
+ {0x3800, 0x00, 0, 0},
+ // HS
+ {0x3801, 0x00, 0, 0},
+ // HS
+ {0x3802, 0x00, 0, 0},
+ // VS
+ {0x3803, 0x00, 0, 0},
+ // VS
+ {0x3804, 0x0a, 0, 0},
+ // HW {HE)
+ {0x3805, 0x3f, 0, 0},
+ // HW {HE)
+ {0x3806, 0x07, 0, 0},
+ // VH {VE)
+ {0x3807, 0x9f, 0, 0},
+ // VH {VE)
+ {0x3808, 0x0a, 0, 0},
+ // DVPHO
+ {0x3809, 0x20, 0, 0},
+ // DVPHO
+ {0x380a, 0x07, 0, 0},
+ // DVPVO
+ {0x380b, 0x98, 0, 0},
+ // DVPVO
+ {0x380c, 0x0b, 0, 0},
+ // HTS
+ {0x380d, 0x1c, 0, 0},
+ // HTS
+ {0x380e, 0x07, 0, 0},
+ // VTS
+ {0x380f, 0xb0, 0, 0},
+ // VTS
+ {0x3813, 0x04, 0, 0},
+ // timing V offset
+ {0x3618, 0x04, 0, 0},
+ {0x3612, 0x2b, 0, 0},
+ {0x3709, 0x12, 0, 0},
+ {0x370c, 0x00, 0, 0},
+ // banding filters are calculated automatically in camera driver
+ //{0x3a02, 0x07, 0, 0},
+ // 60Hz max exposure
+ //{0x3a03, 0xae, 0, 0},
+ // 60Hz max exposure
+ //{0x3a08, 0x01, 0, 0},
+ // B50 step
+ //{0x3a09, 0x27, 0, 0},
+ // B50 step
+ //{0x3a0a, 0x00, 0, 0},
+ // B60 step
+ //{0x3a0b, 0xf6, 0, 0},
+ // B60 step
+ //{0x3a0e, 0x06, 0, 0},
+ // 50Hz max band
+ //{0x3a0d, 0x08, 0, 0},
+ // 60Hz max band
+ //{0x3a14, 0x07, 0, 0},
+ // 50Hz max exposure
+ //{0x3a15, 0xae, 0, 0},
+ // 50Hz max exposure
+ {0x4004, 0x06, 0, 0},
+ // BLC line number
+ {0x3002, 0x1c, 0, 0},
+ // reset JFIFO, SFIFO, JPG
+ {0x3006, 0xc3, 0, 0},
+ // disable clock of JPEG2x, JPEG
+ {0x4713, 0x02, 0, 0},
+ // JPEG mode 3
+ {0x4407, 0x0c, 0, 0},
+ // Quantization sacle
+ {0x460b, 0x37, 0, 0},
+ {0x460c, 0x20, 0, 0},
+ {0x4837, 0x2c, 0, 0},
+ // MIPI global timing
+ {0x3824, 0x01, 0, 0},
+ // PCLK manual divider
+ {0x5001, 0x83, 0, 0},
+ // SDE on, CMX on, AWB on
+ {0x3503, 0x03, 0, 0},
+};
+
/* power-on sensor init reg table */
static const struct ov5640_mode_info ov5640_mode_init_data = {
0, SUBSAMPLING, 640, 480, ov5640_init_setting_30fps_VGA,
@@ -909,6 +909,14 @@ ov5640_mode_data[OV5640_NUM_FRAMERATES][OV5640_NUM_MODES] = {
ov5640_setting_30fps_1080P_1920_1080,
ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
{OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, 0, 0, NULL, 0},
+ }, {
+ {OV5640_MODE_1080P_1920_1080, SCALING, 1920, 1080,
+ ov5640_setting_7p5_fps_1080P_1920_1080,
+ ARRAY_SIZE(ov5640_setting_7p5_fps_1080P_1920_1080)}
+ }, {
+ {OV5640_MODE_1080P_1920_1080, SCALING, 2592, 1944,
+ ov5640_setting_5_fps_QSXGA_2592_1944,
+ ARRAY_SIZE(ov5640_setting_5_fps_QSXGA_2592_1944)}
},
};
@@ -1376,6 +1521,14 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
const struct ov5640_mode_info *mode = NULL;
int i;
+ printk("%s fps=%d width=%d height=%d nearest=%d\n", __func__, fr, width, height, nearest);
+
+ if (width >= 2592 && height >= 1944)
+ fr = OV5640_5_FPS;
+ else if (width >= 1920 && height >= 1080)
+ fr = OV5640_7P5_FPS;
+ else
+ fr = OV5640_30_FPS;
for (i = OV5640_NUM_MODES - 1; i >= 0; i--) {
mode = &ov5640_mode_data[fr][i];
--
2.17.1

View file

@ -1,221 +0,0 @@
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 90c9a8a..3c79b90 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -29,6 +29,27 @@ create_package() {
# in case we are in a restrictive umask environment like 0077
chmod -R a+rX "$pdir"
+ # Create preinstall and post install script to remove dtb
+ if [[ "$1" == *dtb* ]]; then
+ echo "if [ -d /boot/dtb-$version ]; then mv /boot/dtb-$version /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/preinst
+ echo "if [ -d /boot/dtb.old ]; then rm -rf /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst
+ echo "if [ -d /boot/dtb ]; then mv /boot/dtb /boot/dtb.old; fi" >> $pdir/DEBIAN/preinst
+ echo "exit 0" >> $pdir/DEBIAN/preinst
+ chmod 775 $pdir/DEBIAN/preinst
+
+ echo "if [ -d /boot/dtb-$version.old ]; then rm -rf /boot/dtb-$version.old; fi" >> $pdir/DEBIAN/postinst
+ echo "ln -sf dtb-$version /boot/dtb > /dev/null 2>&1 || mv /boot/dtb-$version /boot/dtb" >> $pdir/DEBIAN/postinst
+ echo "exit 0" >> $pdir/DEBIAN/postinst
+ chmod 775 $pdir/DEBIAN/postinst
+ fi
+
+ # Create postinstall script for headers
+ if [[ "$1" == *headers* ]]; then
+ echo "cd /usr/src/linux-headers-$version; echo \"Compiling headers - please wait ...\"; find -type f -exec touch {} + ; make -s scripts >/dev/null 2>&1" >> $pdir/DEBIAN/postinst
+ echo "exit 0" >> $pdir/DEBIAN/postinst
+ chmod 775 $pdir/DEBIAN/postinst
+ fi
+
# Create the package
dpkg-gencontrol -p$pname -P"$pdir"
dpkg --build "$pdir" ..
@@ -39,9 +60,11 @@ tmpdir="$objtree/debian/tmp"
kernel_headers_dir="$objtree/debian/hdrtmp"
libc_headers_dir="$objtree/debian/headertmp"
dbg_dir="$objtree/debian/dbgtmp"
-packagename=linux-image-$version
-kernel_headers_packagename=linux-headers-$version
-libc_headers_packagename=linux-libc-dev
+dtb_dir="$objtree/debian/dtbtmp"
+packagename=linux-image-next"$LOCALVERSION"
+kernel_headers_packagename=linux-headers-next"$LOCALVERSION"
+dtb_packagename=linux-dtb-next"$LOCALVERSION"
+libc_headers_packagename=linux-libc-dev-next"$LOCALVERSION"
dbg_packagename=$packagename-dbg
if [ "$ARCH" = "um" ] ; then
@@ -52,6 +75,15 @@ fi
# XXX: have each arch Makefile export a variable of the canonical image install
# path instead
case $ARCH in
+aarch64|arm64)
+ image_name=Image
+ installed_image_path="boot/vmlinuz-$version"
+
+ ;;
+arm*)
+ image_name=zImage
+ installed_image_path="boot/vmlinuz-$version"
+ ;;
um)
installed_image_path="usr/bin/linux-$version"
;;
@@ -65,7 +97,9 @@ esac
BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
# Setup the directory structure
-rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
+rm -rf "$tmpdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" "$dtb_dir" $objtree/debian/files
+mkdir -m 755 -p "$dtb_dir/DEBIAN"
+mkdir -p "$dtb_dir/boot/dtb-$version" "$dtb_dir/usr/share/doc/$dtb_packagename"
mkdir -m 755 -p "$tmpdir/DEBIAN"
mkdir -p "$tmpdir/lib" "$tmpdir/boot"
mkdir -p "$kernel_headers_dir/lib/modules/$version/"
@@ -118,6 +152,11 @@ if grep -q '^CONFIG_MODULES=y' $KCONFIG_CONFIG ; then
fi
fi
+if grep -q '^CONFIG_OF=y' $KCONFIG_CONFIG ; then
+ #mkdir -p "$tmpdir/boot/dtb"
+ INSTALL_DTBS_PATH="$dtb_dir/boot/dtb-$version" $MAKE KBUILD_SRC= dtbs_install
+fi
+
if [ "$ARCH" != "um" ]; then
$MAKE headers_check KBUILD_SRC=
$MAKE headers_install KBUILD_SRC= INSTALL_HDR_PATH="$libc_headers_dir/usr"
@@ -137,7 +176,7 @@ fi
for script in postinst postrm preinst prerm ; do
mkdir -p "$tmpdir$debhookdir/$script.d"
cat <<EOF > "$tmpdir/DEBIAN/$script"
-#!/bin/sh
+#!/bin/bash
set -e
@@ -153,9 +192,60 @@ EOF
chmod 755 "$tmpdir/DEBIAN/$script"
done
+##
+## Create sym link to kernel image
+##
+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/postinst
+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/postinst
+cat >> $tmpdir/DEBIAN/postinst <<EOT
+if [ "\$(grep nand /proc/partitions)" != "" ] && [ "\$(grep mmc /proc/partitions)" = "" ]; then
+ mkimage -A arm -O linux -T kernel -C none -a "0x40008000" -e "0x40008000" -n "Linux kernel" -d /$installed_image_path /boot/uImage > /dev/null 2>&1
+ cp /boot/uImage /tmp/uImage
+ sync
+ mountpoint -q /boot || mount /boot
+ cp /tmp/uImage /boot/uImage
+ rm -f /$installed_image_path
+else
+ ln -sf $(basename $installed_image_path) /boot/$image_name || mv /$installed_image_path /boot/$image_name
+fi
+touch /boot/.next
+exit 0
+EOT
+
+##
+## FAT install workaround
+##
+sed -e "s/set -e//g" -i $tmpdir/DEBIAN/preinst
+sed -e "s/exit 0//g" -i $tmpdir/DEBIAN/preinst
+cat >> $tmpdir/DEBIAN/preinst <<EOT
+# exit if we are running chroot
+if [ "\$(stat -c %d:%i /)" != "\$(stat -c %d:%i /proc/1/root/.)" ]; then exit 0; fi
+
+check_and_unmount (){
+ boot_device=\$(mountpoint -d /boot)
+
+ for file in /dev/* ; do
+ CURRENT_DEVICE=\$(printf "%d:%d" \$(stat --printf="0x%t 0x%T" \$file))
+ if [[ "\$CURRENT_DEVICE" = "\$boot_device" ]]; then
+ boot_partition=\$file
+ break
+ fi
+ done
+
+ bootfstype=\$(blkid -s TYPE -o value \$boot_partition)
+ if [ "\$bootfstype" = "vfat" ]; then
+ umount /boot
+ rm -f /boot/System.map* /boot/config* /boot/vmlinuz* /boot/$image_name /boot/uImage
+ fi
+}
+mountpoint -q /boot && check_and_unmount
+EOT
+echo "exit 0" >> $tmpdir/DEBIAN/preinst
+
# Build kernel header package
(cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
(cd $srctree; find arch/*/include include scripts -type f -o -type l) >> "$objtree/debian/hdrsrcfiles"
+(cd $srctree; find security/*/include -type f) >> "$objtree/debian/hdrsrcfiles"
(cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
if grep -q '^CONFIG_STACK_VALIDATION=y' $KCONFIG_CONFIG ; then
@@ -167,15 +257,19 @@ if grep -q '^CONFIG_GCC_PLUGINS=y' $KCONFIG_CONFIG ; then
fi
destdir=$kernel_headers_dir/usr/src/linux-headers-$version
mkdir -p "$destdir"
+(cd $destdir; patch -p1 < /tmp/headers-debian-byteshift.patch)
(cd $srctree; tar -c -f - -T -) < "$objtree/debian/hdrsrcfiles" | (cd $destdir; tar -xf -)
(cd $objtree; tar -c -f - -T -) < "$objtree/debian/hdrobjfiles" | (cd $destdir; tar -xf -)
(cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
+(cd $destdir; make M=scripts clean)
+
if [ "$ARCH" != "um" ]; then
create_package "$kernel_headers_packagename" "$kernel_headers_dir"
- create_package "$libc_headers_packagename" "$libc_headers_dir"
+ # create_package "$libc_headers_packagename" "$libc_headers_dir"
+ create_package "$dtb_packagename" "$dtb_dir"
fi
create_package "$packagename" "$tmpdir"
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian
index 6adb3a1..00e12eb 100755
--- a/scripts/package/mkdebian
+++ b/scripts/package/mkdebian
@@ -61,10 +61,12 @@ else
packageversion=$version-$revision
fi
sourcename=$KDEB_SOURCENAME
-packagename=linux-image-$version
-kernel_headers_packagename=linux-headers-$version
+packagename=linux-image-next$LOCALVERSION
+kernel_headers_packagename=linux-headers-next$LOCALVERSION
+dtb_packagename=linux-dtb-next$LOCALVERSION
dbg_packagename=$packagename-dbg
debarch=
+image_name=
set_debarch
if [ "$ARCH" = "um" ] ; then
@@ -168,6 +170,11 @@ Architecture: $debarch
Description: Linux kernel debugging symbols for $version
This package will come in handy if you need to debug the kernel. It provides
all the necessary debug symbols for the kernel and its modules.
+
+Package: $dtb_packagename
+Architecture: $debarch
+Description: Linux DTB, version $version
+ This package contains device blobs from the Linux kernel, version $version
EOF
cat <<EOF > debian/rules
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index f839ecd9..cd276162 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -103,7 +103,7 @@ core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
# Default target when executing plain make
boot := arch/arm64/boot
-KBUILD_IMAGE := $(boot)/Image.gz
+KBUILD_IMAGE := $(boot)/Image
KBUILD_DTBS := dtbs
all: Image.gz $(KBUILD_DTBS)

View file

@ -1,7 +1,7 @@
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 77533f7..8b3b184 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -532,11 +532,7 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
{
struct nand_chip *chip = mtd_to_nand(mtd);

View file

@ -49,236 +49,6 @@ index b6f2d6b2ecae..2e97173c9204 100644
2.17.1
From cc6843c51ec07b6c2ec961b4baa1d5967e0bdb3b Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 13 Jul 2018 00:04:48 +0800
Subject: [PATCH 09/45] dt-bindings: mfd: axp20x: Add "self-working" mode for
AXP806
The AXP806 has three operation modes:
- master mode: The PMIC is the first or only AXP PMIC in the system,
but is not in charge of power management, i.e. only
provides regulator functions.
- slave mode: The PMIC is the second AXP PMIC in the system, chained
to the first, or master, one.
- self-working mode: The PMIC is the only AXP PMIC in the system, and
is in charge of power sequencing.
The functional differences between these modes can be found in the
"Control and Operation" chapter of the AXP806 (in Chinese) and AXP805
(in English) datasheets. These include how the PMIC responds to external
signals, whether it takes an external voltage reference or uses its own,
and whether the EN/PWRON pin functions as an enable switch or power button.
We already support both slave and master mode. This patch adds a property
for describing the self-working mode, and reworks the description for
the mode properties.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Icenowy Zheng <icenowy@aosc.io>
Tested-by: Icenowy Zheng <icenowy@aosc.io>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
Documentation/devicetree/bindings/mfd/axp20x.txt | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index d1762f3b30af..eaaf79c01e1e 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -45,8 +45,11 @@ Optional properties:
board is driving OTG VBus or not.
(axp221 / axp223 / axp803/ axp813 only)
-- x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is
- wired for master mode. The default is slave mode.
+- x-powers,self-working-mode and
+ x-powers,master-mode: Boolean (axp806 only). Set either of these when the
+ PMIC is wired for self-working mode or master mode.
+ If neither is set then slave mode is assumed.
+ This corresponds to how the MODESET pin is wired.
- <input>-supply: a phandle to the regulator supply node. May be omitted if
inputs are unregulated, such as using the IPSOUT output
--
2.17.1
From 1ff51a1fb79a61f822f1551c994274c0cfcdf131 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 13 Jul 2018 00:04:49 +0800
Subject: [PATCH 10/45] mfd: axp20x: Add self-working mode support for AXP806
The AXP806 can operate in a standalone "self-working" mode, in which it
is also responsible for power control of the overall system. This mode
is similar to the master mode, but the EN/PWRON pin functions as a power
button, instead of a level-triggered enable switch.
This patch adds code checking for the new "x-powers,self-working-mode"
property, and a separate mfd_cell list that includes the power button
(PEK) sub-device.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Reviewed-by: Icenowy Zheng <icenowy@aosc.io>
Tested-by: Icenowy Zheng <icenowy@aosc.io>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/axp20x.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 9a2ef3d9b8f8..0be511dd93d0 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -221,6 +221,11 @@ static const struct resource axp803_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
+static const struct resource axp806_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_RISE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_FALL, "PEK_DBF"),
+};
+
static const struct resource axp809_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -730,6 +735,15 @@ static const struct mfd_cell axp803_cells[] = {
{ .name = "axp20x-regulator" },
};
+static const struct mfd_cell axp806_self_working_cells[] = {
+ {
+ .name = "axp221-pek",
+ .num_resources = ARRAY_SIZE(axp806_pek_resources),
+ .resources = axp806_pek_resources,
+ },
+ { .name = "axp20x-regulator" },
+};
+
static const struct mfd_cell axp806_cells[] = {
{
.id = 2,
@@ -842,8 +856,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
break;
case AXP806_ID:
- axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
- axp20x->cells = axp806_cells;
+ if (of_property_read_bool(axp20x->dev->of_node,
+ "x-powers,self-working-mode")) {
+ axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
+ axp20x->cells = axp806_self_working_cells;
+ } else {
+ axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
+ axp20x->cells = axp806_cells;
+ }
axp20x->regmap_cfg = &axp806_regmap_config;
axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
break;
@@ -901,7 +921,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
*/
if (axp20x->variant == AXP806_ID) {
if (of_property_read_bool(axp20x->dev->of_node,
- "x-powers,master-mode"))
+ "x-powers,master-mode") ||
+ of_property_read_bool(axp20x->dev->of_node,
+ "x-powers,self-working-mode"))
regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
else
--
2.17.1
From 8a19d87150e9afb44194407be651669fa02344fe Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Fri, 13 Jul 2018 00:04:50 +0800
Subject: [PATCH 11/45] mfd: axp20x: Support AXP806 in I2C mode
The Pine64 H64 board uses an AXP806 PMIC in I2C and self-working mode.
The H64 SoC does not have the usual RSB controller.
This patch adds AXP806 to the list of devices supported in I2C mode.
In theory, all RSB-based PMICs can also be used in I2C mode.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Reviewed-by: Icenowy Zheng <icenowy@aosc.io>
Tested-by: Icenowy Zheng <icenowy@aosc.io>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/axp20x-i2c.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c
index d35a5fe6c950..a7b7c5423ea5 100644
--- a/drivers/mfd/axp20x-i2c.c
+++ b/drivers/mfd/axp20x-i2c.c
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
{ .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
{ .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
{ .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
+ { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
{ },
};
MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
@@ -74,6 +75,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
{ "axp202", 0 },
{ "axp209", 0 },
{ "axp221", 0 },
+ { "axp806", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
--
From bb10f5dd2933681507d316b8c84b183f678dcf31 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Thu, 26 Jul 2018 12:41:27 +0800
Subject: [PATCH 36/45] arm64: allwinner: dts: h6: fix Pine H64 MMC bus width
Currently the enabled MMC controllers on Pine H64 do not have bus-width
set, which make them fall back to 1-bit mode and become quite slow.
Fix this by add the corresponding bus-width properties.
Fixes: ecbd611882a1 ("arm64: allwinner: h6: enable MMC0/2 on Pine H64")
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index bf0a88294ae4..3c74cbed319b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -97,6 +97,7 @@
pinctrl-0 = <&mmc0_pins>;
vmmc-supply = <&reg_cldo1>;
cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ bus-width = <4>;
status = "okay";
};
@@ -107,6 +108,7 @@
vqmmc-supply = <&reg_bldo2>;
non-removable;
cap-mmc-hw-reset;
+ bus-width = <8>;
status = "okay";
};
--
2.17.1
From 6bfc6aab9a9cd82578a7e782c83d04f4cf7fe6c4 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Fri, 27 Jul 2018 16:22:01 +0800
@ -839,9 +609,9 @@ index 8e3c47c7c797..cf125ebd1c7b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -10,6 +10,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/sun50i-h6-ccu.h>
#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
#include <dt-bindings/reset/sun50i-h6-ccu.h>
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+#include <dt-bindings/thermal/thermal.h>
/ {

View file

@ -1,333 +0,0 @@
Initial implementation of DE2 planes only supported fixed zpos.
Expand implementation with configurable zpos property.
Implementation background:
Channel in DE2 driver represents one DRM plane, whereas pipe is just
mapped channel to known Z position. Pipe 0 will always be at the bottom,
pipe 1 just above pipe 0 and so on. If, for example, channel 1 is mapped
at pipe 0 and channel 0 at pipe 1, whatever is on channel 0 will appear
on top.
Before this commit, channel id was used for addressing channel related
registers (prefixed with SUN8I_MIXER_CHAN_UI_ or SUN8I_MIXER_CHAN_VI_)
and pipe registers (prefixed with SUN8I_MIXER_BLEND_). Additionally,
register SUN8I_MIXER_BLEND_ROUTE, which takes care for mapping channels
to pipes had fixed value. It mapped channel 0 to pipe 0, 1 to 1 and so
on. Consequence of all that was fixed Z order of planes.
With this commit, pipe registers are using zpos property as index and
channel related registers still use channel id as index. Pipe mapping
register is now set dynamically too and pipe enable register is rebuild
every time to make sure only active pipes are enabled.
Testing was done to confirm that there is no issues if bottom plane
contains pixels with alpha value < 0xff and if it doesn't whole screen.
Tested-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Patch is based on linux-next (next-20180706).
Changes from v1:
- added tested-by tag
- expand commit message with detailed explanation
drivers/gpu/drm/sun4i/sun8i_mixer.c | 15 +++++++--
drivers/gpu/drm/sun4i/sun8i_mixer.h | 4 +++
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 45 ++++++++++++++++----------
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 45 ++++++++++++++++----------
4 files changed, 72 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index ee8febb25903..0747a9a69654 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -260,6 +260,17 @@ const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
return NULL;
}
+static void sun8i_mixer_atomic_begin(struct sunxi_engine *engine,
+ struct drm_crtc_state *old_state)
+{
+ /*
+ * Disable all pipes at the beginning. They will be enabled
+ * again if needed in plane update callback.
+ */
+ regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_PIPE_CTL,
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
+}
+
static void sun8i_mixer_commit(struct sunxi_engine *engine)
{
DRM_DEBUG_DRIVER("Committing changes\n");
@@ -311,6 +322,7 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
}
static const struct sunxi_engine_ops sun8i_engine_ops = {
+ .atomic_begin = sun8i_mixer_atomic_begin,
.commit = sun8i_mixer_commit,
.layers_init = sun8i_layers_init,
};
@@ -432,9 +444,6 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(0),
SUN8I_MIXER_BLEND_COLOR_BLACK);
- /* Fixed zpos for now */
- regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ROUTE, 0x43210);
-
plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
for (i = 0; i < plane_cnt; i++)
regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(i),
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index f34e70c42adf..406c42e752d7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -44,6 +44,7 @@
#define SUN8I_MIXER_BLEND_CK_MIN(x) (0x10e0 + 0x04 * (x))
#define SUN8I_MIXER_BLEND_OUTCTL 0x10fc
+#define SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK GENMASK(12, 8)
#define SUN8I_MIXER_BLEND_PIPE_CTL_EN(pipe) BIT(8 + pipe)
#define SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(pipe) BIT(pipe)
/* colors are always in AARRGGBB format */
@@ -51,6 +52,9 @@
/* The following numbers are some still unknown magic numbers */
#define SUN8I_MIXER_BLEND_MODE_DEF 0x03010301
+#define SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(n) (0xf << ((n) << 2))
+#define SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(n) ((n) << 2)
+
#define SUN8I_MIXER_BLEND_OUTCTL_INTERLACED BIT(1)
#define SUN8I_MIXER_FBFMT_ARGB8888 0
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 9a540330cb79..518e1921f47e 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -27,7 +27,7 @@
#include "sun8i_ui_scaler.h"
static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable)
+ int overlay, bool enable, unsigned int zpos)
{
u32 val;
@@ -43,18 +43,24 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
- if (enable)
- val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
- else
- val = 0;
+ if (enable) {
+ val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL,
- SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
+
+ val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_ROUTE,
+ SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
+ val);
+ }
}
static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
- int overlay, struct drm_plane *plane)
+ int overlay, struct drm_plane *plane,
+ unsigned int zpos)
{
struct drm_plane_state *state = plane->state;
u32 src_w, src_h, dst_w, dst_h;
@@ -137,10 +143,10 @@ static int sun8i_ui_layer_update_coord(struct sun8i_mixer *mixer, int channel,
state->dst.x1, state->dst.y1);
DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
regmap_write(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+ SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
regmap_write(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+ SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
outsize);
return 0;
@@ -238,28 +244,30 @@ static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane,
struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
struct sun8i_mixer *mixer = layer->mixer;
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false);
+ sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0);
}
static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+ unsigned int zpos = plane->state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
if (!plane->state->visible) {
sun8i_ui_layer_enable(mixer, layer->channel,
- layer->overlay, false);
+ layer->overlay, false, 0);
return;
}
sun8i_ui_layer_update_coord(mixer, layer->channel,
- layer->overlay, plane);
+ layer->overlay, plane, zpos);
sun8i_ui_layer_update_formats(mixer, layer->channel,
layer->overlay, plane);
sun8i_ui_layer_update_buffer(mixer, layer->channel,
layer->overlay, plane);
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, true);
+ sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
+ true, zpos);
}
static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
@@ -307,6 +315,7 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
enum drm_plane_type type = DRM_PLANE_TYPE_OVERLAY;
int channel = mixer->cfg->vi_num + index;
struct sun8i_ui_layer *layer;
+ unsigned int plane_cnt;
int ret;
layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
@@ -327,8 +336,10 @@ struct sun8i_ui_layer *sun8i_ui_layer_init_one(struct drm_device *drm,
return ERR_PTR(ret);
}
- /* fixed zpos for now */
- ret = drm_plane_create_zpos_immutable_property(&layer->plane, channel);
+ plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
+
+ ret = drm_plane_create_zpos_property(&layer->plane, channel,
+ 0, plane_cnt - 1);
if (ret) {
dev_err(drm->dev, "Couldn't add zpos property\n");
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 5877f8ef5895..17e0d00cfd8a 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -21,7 +21,7 @@
#include "sun8i_vi_scaler.h"
static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable)
+ int overlay, bool enable, unsigned int zpos)
{
u32 val;
@@ -37,18 +37,24 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
- if (enable)
- val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel);
- else
- val = 0;
+ if (enable) {
+ val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
- regmap_update_bits(mixer->engine.regs,
- SUN8I_MIXER_BLEND_PIPE_CTL,
- SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val);
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_PIPE_CTL, val, val);
+
+ val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_ROUTE,
+ SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos),
+ val);
+ }
}
static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
- int overlay, struct drm_plane *plane)
+ int overlay, struct drm_plane *plane,
+ unsigned int zpos)
{
struct drm_plane_state *state = plane->state;
const struct drm_format_info *format = state->fb->format;
@@ -130,10 +136,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
state->dst.x1, state->dst.y1);
DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
regmap_write(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ATTR_COORD(channel),
+ SUN8I_MIXER_BLEND_ATTR_COORD(zpos),
SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
regmap_write(mixer->engine.regs,
- SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
+ SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),
outsize);
return 0;
@@ -266,28 +272,30 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
struct sun8i_mixer *mixer = layer->mixer;
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false);
+ sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0);
}
static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+ unsigned int zpos = plane->state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
if (!plane->state->visible) {
sun8i_vi_layer_enable(mixer, layer->channel,
- layer->overlay, false);
+ layer->overlay, false, 0);
return;
}
sun8i_vi_layer_update_coord(mixer, layer->channel,
- layer->overlay, plane);
+ layer->overlay, plane, zpos);
sun8i_vi_layer_update_formats(mixer, layer->channel,
layer->overlay, plane);
sun8i_vi_layer_update_buffer(mixer, layer->channel,
layer->overlay, plane);
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, true);
+ sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
+ true, zpos);
}
static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {
@@ -351,6 +359,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
int index)
{
struct sun8i_vi_layer *layer;
+ unsigned int plane_cnt;
int ret;
layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
@@ -368,8 +377,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
return ERR_PTR(ret);
}
- /* fixed zpos for now */
- ret = drm_plane_create_zpos_immutable_property(&layer->plane, index);
+ plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num;
+
+ ret = drm_plane_create_zpos_property(&layer->plane, index,
+ 0, plane_cnt - 1);
if (ret) {
dev_err(drm->dev, "Couldn't add zpos property\n");
return ERR_PTR(ret);

View file

@ -1,178 +0,0 @@
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index 8e81c24d736e..12cb7183ce51 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -260,17 +260,6 @@ const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
return NULL;
}
-static void sun8i_mixer_atomic_begin(struct sunxi_engine *engine,
- struct drm_crtc_state *old_state)
-{
- /*
- * Disable all pipes at the beginning. They will be enabled
- * again if needed in plane update callback.
- */
- regmap_update_bits(engine->regs, SUN8I_MIXER_BLEND_PIPE_CTL,
- SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
-}
-
static void sun8i_mixer_commit(struct sunxi_engine *engine)
{
DRM_DEBUG_DRIVER("Committing changes\n");
@@ -322,7 +311,6 @@ static struct drm_plane **sun8i_layers_init(struct drm_device *drm,
}
static const struct sunxi_engine_ops sun8i_engine_ops = {
- .atomic_begin = sun8i_mixer_atomic_begin,
.commit = sun8i_mixer_commit,
.layers_init = sun8i_layers_init,
};
@@ -449,6 +437,9 @@ static int sun8i_mixer_bind(struct device *dev, struct device *master,
regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_MODE(i),
SUN8I_MIXER_BLEND_MODE_DEF);
+ regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL,
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);
+
return 0;
err_disable_bus_clk:
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index 518e1921f47e..28c15c6ef1ef 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -27,7 +27,8 @@
#include "sun8i_ui_scaler.h"
static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable, unsigned int zpos)
+ int overlay, bool enable, unsigned int zpos,
+ unsigned int old_zpos)
{
u32 val;
@@ -43,6 +44,18 @@ static void sun8i_ui_layer_enable(struct sun8i_mixer *mixer, int channel,
SUN8I_MIXER_CHAN_UI_LAYER_ATTR(channel, overlay),
SUN8I_MIXER_CHAN_UI_LAYER_ATTR_EN, val);
+ if (!enable || zpos != old_zpos) {
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_PIPE_CTL,
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
+ 0);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_ROUTE,
+ SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
+ 0);
+ }
+
if (enable) {
val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
@@ -242,9 +255,11 @@ static void sun8i_ui_layer_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
+ unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
- sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0);
+ sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
+ old_zpos);
}
static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
@@ -252,11 +267,12 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
{
struct sun8i_ui_layer *layer = plane_to_sun8i_ui_layer(plane);
unsigned int zpos = plane->state->normalized_zpos;
+ unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
if (!plane->state->visible) {
sun8i_ui_layer_enable(mixer, layer->channel,
- layer->overlay, false, 0);
+ layer->overlay, false, 0, old_zpos);
return;
}
@@ -267,7 +283,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane,
sun8i_ui_layer_update_buffer(mixer, layer->channel,
layer->overlay, plane);
sun8i_ui_layer_enable(mixer, layer->channel, layer->overlay,
- true, zpos);
+ true, zpos, old_zpos);
}
static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 17e0d00cfd8a..f4fe97813f94 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -21,7 +21,8 @@
#include "sun8i_vi_scaler.h"
static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
- int overlay, bool enable, unsigned int zpos)
+ int overlay, bool enable, unsigned int zpos,
+ unsigned int old_zpos)
{
u32 val;
@@ -37,6 +38,18 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),
SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val);
+ if (!enable || zpos != old_zpos) {
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_PIPE_CTL,
+ SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos),
+ 0);
+
+ regmap_update_bits(mixer->engine.regs,
+ SUN8I_MIXER_BLEND_ROUTE,
+ SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos),
+ 0);
+ }
+
if (enable) {
val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos);
@@ -270,9 +283,11 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
+ unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
- sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0);
+ sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0,
+ old_zpos);
}
static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
@@ -280,11 +295,12 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
{
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
unsigned int zpos = plane->state->normalized_zpos;
+ unsigned int old_zpos = old_state->normalized_zpos;
struct sun8i_mixer *mixer = layer->mixer;
if (!plane->state->visible) {
sun8i_vi_layer_enable(mixer, layer->channel,
- layer->overlay, false, 0);
+ layer->overlay, false, 0, old_zpos);
return;
}
@@ -295,7 +311,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,
sun8i_vi_layer_update_buffer(mixer, layer->channel,
layer->overlay, plane);
sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay,
- true, zpos);
+ true, zpos, old_zpos);
}
static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = {

View file

@ -1,54 +0,0 @@
diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig
index 156a865c3e6d..c2c042287c19 100644
--- a/drivers/gpu/drm/sun4i/Kconfig
+++ b/drivers/gpu/drm/sun4i/Kconfig
@@ -68,4 +68,11 @@ config DRM_SUN8I_MIXER
graphics mixture and feed graphics to TCON, If M is
selected the module will be called sun8i-mixer.
+config DRM_SUN8I_TCON_TOP
+ tristate
+ default DRM_SUN4I if DRM_SUN8I_MIXER!=n
+ help
+ TCON TOP is responsible for configuring display pipeline for
+ HTMI, TVE and LCD.
+
endif
diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile
index cd27d02c94e2..0eb38ac8e86e 100644
--- a/drivers/gpu/drm/sun4i/Makefile
+++ b/drivers/gpu/drm/sun4i/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_DRM_SUN4I_HDMI) += sun4i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN6I_DSI) += sun6i-dsi.o
obj-$(CONFIG_DRM_SUN8I_DW_HDMI) += sun8i-drm-hdmi.o
obj-$(CONFIG_DRM_SUN8I_MIXER) += sun8i-mixer.o
+obj-$(CONFIG_DRM_SUN8I_TCON_TOP) += sun8i_tcon_top.o
\ No newline at end of file
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a15feb807393..03ffbcc98dd0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -216,7 +216,8 @@ static bool sun4i_drv_node_is_tcon_with_ch0(struct device_node *node)
static bool sun4i_drv_node_is_tcon_top(struct device_node *node)
{
- return !!of_match_node(sun8i_tcon_top_of_table, node);
+ return IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
+ !!of_match_node(sun8i_tcon_top_of_table, node);
}
static int compare_of(struct device *dev, void *data)
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 21dc9ebad0b4..e184cb17690b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -44,7 +44,8 @@ sun8i_dw_hdmi_mode_valid(struct drm_connector *connector,
static bool sun8i_dw_hdmi_node_is_tcon_top(struct device_node *node)
{
- return !!of_match_node(sun8i_tcon_top_of_table, node);
+ return IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
+ !!of_match_node(sun8i_tcon_top_of_table, node);
}
static u32 sun8i_dw_hdmi_find_possible_crtcs(struct drm_device *drm,

View file

@ -301875,7 +301875,7 @@ new file mode 100644
index 0000000000000..324b45bd223fd
--- /dev/null
+++ b/drivers/net/wireless/rtl8188eu/include/wifi.h
@@ -0,0 +1,1103 @@
@@ -0,0 +1,1105 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
@ -302608,7 +302608,9 @@ index 0000000000000..324b45bd223fd
+ * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2)
+ */
+#define IEEE80211_MIN_AMPDU_BUF 0x8
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,19,0))
+#define IEEE80211_MAX_AMPDU_BUF 0x40
+#endif
+
+/* Spatial Multiplexing Power Save Modes */
+#define WLAN_HT_CAP_SM_PS_STATIC 0
@ -311898,7 +311900,7 @@ new file mode 100644
index 0000000000000..fadf117a54b6a
--- /dev/null
+++ b/drivers/net/wireless/rtl8188eu/os_dep/os_intfs.c
@@ -0,0 +1,1273 @@
@@ -0,0 +1,1276 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
@ -312553,7 +312555,10 @@ index 0000000000000..fadf117a54b6a
+}
+
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
+ ,struct net_device *sb_dev
+ ,select_queue_fallback_t fallback
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+ ,void *unused
+ ,select_queue_fallback_t fallback
+#elif (LINUX_VERSION_CODE == KERNEL_VERSION(3, 13, 0))

View file

@ -1,40 +0,0 @@
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 4b290705e3e6..9b3a58e89dd1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -32,11 +32,30 @@
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
-#define BRCMF_STA_WME 0x00000002 /* WMM association */
-#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
-#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
-#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
-#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
+#define BRCMF_STA_BRCM 0x00000001 /* Running a Broadcom driver */
+#define BRCMF_STA_WME 0x00000002 /* WMM association */
+#define BRCMF_STA_NONERP 0x00000004 /* No ERP */
+#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
+#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
+#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
+#define BRCMF_STA_WDS 0x00000040 /* Wireless Distribution System */
+#define BRCMF_STA_WDS_LINKUP 0x00000080 /* WDS traffic/probes flowing properly */
+#define BRCMF_STA_PS 0x00000100 /* STA is in power save mode from AP's viewpoint */
+#define BRCMF_STA_APSD_BE 0x00000200 /* APSD delv/trigger for AC_BE is default enabled */
+#define BRCMF_STA_APSD_BK 0x00000400 /* APSD delv/trigger for AC_BK is default enabled */
+#define BRCMF_STA_APSD_VI 0x00000800 /* APSD delv/trigger for AC_VI is default enabled */
+#define BRCMF_STA_APSD_VO 0x00001000 /* APSD delv/trigger for AC_VO is default enabled */
+#define BRCMF_STA_N_CAP 0x00002000 /* STA 802.11n capable */
+#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
+#define BRCMF_STA_AMPDU_CAP 0x00008000 /* STA AMPDU capable */
+#define BRCMF_STA_AMSDU_CAP 0x00010000 /* STA AMSDU capable */
+#define BRCMF_STA_MIMO_PS 0x00020000 /* mimo ps mode is enabled */
+#define BRCMF_STA_MIMO_RTS 0x00040000 /* send rts in mimo ps mode */
+#define BRCMF_STA_RIFS_CAP 0x00080000 /* rifs enabled */
+#define BRCMF_STA_VHT_CAP 0x00100000 /* STA VHT(11ac) capable */
+#define BRCMF_STA_WPS 0x00200000 /* WPS state */
+#define BRCMF_STA_DWDS_CAP 0x01000000 /* DWDS CAP */
+#define BRCMF_STA_DWDS 0x02000000 /* DWDS active */
/* size of brcmf_scan_params not including variable length array */
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64

View file

@ -1,46 +0,0 @@
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index 9b3a58e89dd1..d5bb81e88762 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -174,6 +174,8 @@
#define BRCMF_MFP_CAPABLE 1
#define BRCMF_MFP_REQUIRED 2
+#define BRCMF_VHT_CAP_MCS_MAP_NSS_MAX 8
+
/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
* ioctl. It is relatively small because firmware has small maximum size input
* playload restriction for ioctls.
@@ -550,6 +552,8 @@ struct brcmf_sta_info_le {
/* w/hi bit set if basic */
__le32 in; /* seconds elapsed since associated */
__le32 listen_interval_inms; /* Min Listen interval in ms for STA */
+
+ /* Fields valid for ver >= 3 */
__le32 tx_pkts; /* # of packets transmitted */
__le32 tx_failures; /* # of packets failed */
__le32 rx_ucast_pkts; /* # of unicast packets received */
@@ -558,6 +562,8 @@ struct brcmf_sta_info_le {
__le32 rx_rate; /* Rate of last successful rx frame */
__le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
+
+ /* Fields valid for ver >= 4 */
__le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
__le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
__le32 tx_mcast_pkts; /* # of mcast pkts txed */
@@ -594,6 +600,14 @@ struct brcmf_sta_info_le {
*/
__le32 rx_pkts_retried; /* # rx with retry bit set */
__le32 tx_rate_fallback; /* lowest fallback TX rate */
+
+ /* Fields valid for ver >= 5 */
+ struct {
+ __le32 count; /* # rates in this set */
+ u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */
+ u8 mcs[BRCMF_MCSSET_LEN]; /* supported mcs index bit map */
+ __le16 vht_mcs[BRCMF_VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */
+ } rateset_adv;
};
struct brcmf_chanspec_list {

View file

@ -1,181 +0,0 @@
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index 800a423c7bc2..a78b9bae44e0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -48,6 +48,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
{ BRCMF_FEAT_MBSS, "mbss" },
{ BRCMF_FEAT_MCHAN, "mchan" },
{ BRCMF_FEAT_P2P, "p2p" },
+ { BRCMF_FEAT_MONITOR, "monitor" },
};
#ifdef DEBUG
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index d1193825e559..3415d5d4d6b5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -33,6 +33,7 @@
* MFP: 802.11w Management Frame Protection.
* GSCAN: enhanced scan offload feature.
* FWSUP: Firmware supplicant.
+ * MONITOR: firmware can pass monitor packets to host.
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@@ -48,7 +49,8 @@
BRCMF_FEAT_DEF(WOWL_ARP_ND) \
BRCMF_FEAT_DEF(MFP) \
BRCMF_FEAT_DEF(GSCAN) \
- BRCMF_FEAT_DEF(FWSUP)
+ BRCMF_FEAT_DEF(FWSUP) \
+ BRCMF_FEAT_DEF(MONITOR)
/*
* Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index a78b9bae44e0..4db4d444407a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -49,6 +49,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
{ BRCMF_FEAT_MCHAN, "mchan" },
{ BRCMF_FEAT_P2P, "p2p" },
{ BRCMF_FEAT_MONITOR, "monitor" },
+ { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
};
#ifdef DEBUG
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 3415d5d4d6b5..0b4974df353a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -34,6 +34,7 @@
* GSCAN: enhanced scan offload feature.
* FWSUP: Firmware supplicant.
* MONITOR: firmware can pass monitor packets to host.
+ * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@@ -50,7 +51,8 @@
BRCMF_FEAT_DEF(MFP) \
BRCMF_FEAT_DEF(GSCAN) \
BRCMF_FEAT_DEF(FWSUP) \
- BRCMF_FEAT_DEF(MONITOR)
+ BRCMF_FEAT_DEF(MONITOR) \
+ BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
/*
* Quirks:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 72954fd6df3b..b1f702faff4f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -21,6 +21,7 @@
#include <net/cfg80211.h>
#include <net/rtnetlink.h>
#include <net/addrconf.h>
+#include <net/ieee80211_radiotap.h>
#include <net/ipv6.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
@@ -404,6 +405,30 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
netif_rx_ni(skb);
}
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
+{
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
+ /* Do nothing */
+ } else {
+ struct ieee80211_radiotap_header *radiotap;
+
+ /* TODO: use RX status to fill some radiotap data */
+ radiotap = skb_push(skb, sizeof(*radiotap));
+ memset(radiotap, 0, sizeof(*radiotap));
+ radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
+
+ /* TODO: 4 bytes with receive status? */
+ skb->len -= 4;
+ }
+
+ skb->dev = ifp->ndev;
+ skb_reset_mac_header(skb);
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_802_2);
+
+ brcmf_netif_rx(ifp, skb);
+}
+
static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
struct brcmf_if **ifp)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 401f50458686..dcf6e27cc16f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -121,6 +121,7 @@ struct brcmf_pub {
struct brcmf_if *iflist[BRCMF_MAX_IFS];
s32 if2bss[BRCMF_MAX_IFS];
+ struct brcmf_if *mon_if;
struct mutex proto_block;
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
@@ -216,6 +217,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
int __init brcmf_core_init(void);
void __exit brcmf_core_exit(void);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index c40ba8855cd5..4e8397a0cbc8 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -69,6 +69,8 @@
#define BRCMF_MSGBUF_MAX_EVENTBUF_POST 8
#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3 0x01
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11 0x02
+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK 0x07
#define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT 5
#define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
@@ -1128,6 +1130,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
struct sk_buff *skb;
u16 data_offset;
u16 buflen;
+ u16 flags;
u32 idx;
struct brcmf_if *ifp;
@@ -1137,6 +1140,7 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
data_offset = le16_to_cpu(rx_complete->data_offset);
buflen = le16_to_cpu(rx_complete->data_len);
idx = le32_to_cpu(rx_complete->msg.request_id);
+ flags = le16_to_cpu(rx_complete->flags);
skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
msgbuf->rx_pktids, idx);
@@ -1150,6 +1154,20 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
skb_trim(skb, buflen);
+ if ((flags & BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK) ==
+ BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11) {
+ ifp = msgbuf->drvr->mon_if;
+
+ if (!ifp) {
+ brcmf_err("Received unexpected monitor pkt\n");
+ brcmu_pkt_buf_free_skb(skb);
+ return;
+ }
+
+ brcmf_netif_mon_rx(ifp, skb);
+ return;
+ }
+
ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
if (!ifp || !ifp->ndev) {
brcmf_err("Received pkt for invalid ifidx %d\n",