[PATCH] drm/panel: rm67191: Remove CLOCK_NON_CONTINUOUS flag

2020-08-29 Thread Robert Chiras (OSS)
From: Robert Chiras 

The flag MIPI_DSI_CLOCK_NON_CONTINUOUS was wrong used in the DSI driver,
so it was added to this panel, but not necessary.
So, remove this flag since it is not needed.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
index 23b6208..572547d 100644
--- a/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -552,8 +552,7 @@ static int rad_panel_probe(struct mipi_dsi_device *dsi)
panel->dsi = dsi;
 
dsi->format = MIPI_DSI_FMT_RGB888;
-   dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
-  MIPI_DSI_CLOCK_NON_CONTINUOUS;
+   dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO;
 
ret = of_property_read_u32(np, "video-mode", _mode);
if (!ret) {
-- 
2.7.4

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


[PATCH 1/5] drm/bridge: nwl-dsi: Add support for video_pll

2020-08-29 Thread Robert Chiras (OSS)
From: Robert Chiras 

This patch adds support for a new clock 'video_pll' in order to better
set the video_pll clock to a clock-rate that satisfies a mode's clock.
The video PLL, on i.MX8MQ, can drive both DC pixel-clock and DSI phy_ref
clock. When used with a bridge that can drive multiple modes, like a DSI
to HDMI bridge, the DSI can't be statically configured for a specific
mode in the DTS file.
So, this patch adds access to the video PLL inside the DSI driver, so
that modes can be filtered-out if the required combination of phy_ref
and pixel-clock can't be achieved using the video PLL.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/bridge/nwl-dsi.c | 318 ++-
 1 file changed, 313 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
index ce94f79..1228466 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -39,6 +39,20 @@
 
 #define NWL_DSI_MIPI_FIFO_TIMEOUT msecs_to_jiffies(500)
 
+/* Maximum Video PLL frequency: 1.2GHz */
+#define MAX_PLL_FREQ 12
+
+#define MBPS(x) ((x) * 100)
+#define MIN_PHY_RATE MBPS(24)
+#define MAX_PHY_RATE MBPS(30)
+
+/* Possible valid PHY reference clock rates*/
+static u32 phyref_rates[] = {
+   2700,
+   2500,
+   2400,
+};
+
 enum transfer_direction {
DSI_PACKET_SEND,
DSI_PACKET_RECEIVE,
@@ -67,6 +81,17 @@ struct nwl_dsi_transfer {
size_t rx_len; /* in bytes */
 };
 
+struct mode_config {
+   int clock;
+   int crtc_clock;
+   unsigned intlanes;
+   unsigned long   bitclock;
+   unsigned long   phy_rates[3];
+   unsigned long   pll_rates[3];
+   int phy_rate_idx;
+   struct list_headlist;
+};
+
 struct nwl_dsi {
struct drm_bridge bridge;
struct mipi_dsi_host dsi_host;
@@ -101,6 +126,7 @@ struct nwl_dsi {
struct clk *rx_esc_clk;
struct clk *tx_esc_clk;
struct clk *core_clk;
+   struct clk *pll_clk;
/*
 * hardware bug: the i.MX8MQ needs this clock on during reset
 * even when not using LCDIF.
@@ -115,6 +141,7 @@ struct nwl_dsi {
int error;
 
struct nwl_dsi_transfer *xfer;
+   struct list_head valid_modes;
 };
 
 static const struct regmap_config nwl_dsi_regmap_config = {
@@ -778,6 +805,207 @@ static void nwl_dsi_bridge_disable(struct drm_bridge 
*bridge)
pm_runtime_put(dsi->dev);
 }
 
+static unsigned long nwl_dsi_get_bit_clock(struct nwl_dsi *dsi,
+   unsigned long pixclock, u32 lanes)
+{
+   int bpp;
+
+   if (lanes < 1 || lanes > 4)
+   return 0;
+
+   bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+
+   return (pixclock * bpp) / lanes;
+}
+
+/*
+ * Utility function to calculate least commom multiple, using an improved
+ * version of the Euclidean algorithm for greatest common factor.
+ */
+static unsigned long nwl_dsi_get_lcm(unsigned long a, unsigned long b)
+{
+   u32 gcf = 0; /* greatest common factor */
+   unsigned long tmp_a = a;
+   unsigned long tmp_b = b;
+
+   if (!a || !b)
+   return 0;
+
+   while (tmp_a % tmp_b) {
+   gcf = tmp_a % tmp_b;
+   tmp_a = tmp_b;
+   tmp_b = gcf;
+   }
+
+   if (!gcf)
+   return a;
+
+   return ((unsigned long long)a * b) / gcf;
+}
+
+/*
+ * This function tries to adjust the crtc_clock for a DSI device in such a way
+ * that the video pll will be able to satisfy both Display Controller pixel
+ * clock (feeding out DPI interface) and our input phy_ref clock.
+ */
+static void nwl_dsi_setup_pll_config(struct mode_config *config)
+{
+   unsigned long pll_rate;
+   int div;
+   size_t i, num_rates = ARRAY_SIZE(config->phy_rates);
+
+   config->crtc_clock = 0;
+
+   for (i = 0; i < num_rates; i++) {
+   int crtc_clock;
+
+   if (!config->phy_rates[i])
+   break;
+   /*
+* First, we need to check if phy_ref can actually be obtained
+* from pixel clock. To do this, we check their lowest common
+* multiple, which has to be in PLL range.
+*/
+   pll_rate = nwl_dsi_get_lcm(config->clock, config->phy_rates[i]);
+   if (pll_rate > MAX_PLL_FREQ) {
+   /* Drop pll_rate to a realistic value */
+   while (pll_rate > MAX_PLL_FREQ)
+   pll_rate >>= 1;
+   /* Make sure pll_rate can provide phy_ref rate */
+   div = DIV_ROUND_UP(pll_rate, config->phy_rates[i]);
+   pll_rate = confi

[PATCH 4/5] dt-bindings: display/bridge: nwl-dsi: Document fsl, clock-drop-level property

2020-08-29 Thread Robert Chiras (OSS)
From: Robert Chiras 

Add documentation for a new property: 'fsl,clock-drop-level'.

Signed-off-by: Robert Chiras 
---
 Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml 
b/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml
index 8b5741b..b415f4e 100644
--- a/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml
@@ -143,6 +143,10 @@ properties:
 
 additionalProperties: false
 
+  clock-drop-level:
+description:
+  Specifies the level at wich the crtc_clock should be dropped
+
 patternProperties:
   "^panel@[0-9]+$":
 type: object
-- 
2.7.4

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


[PATCH 2/5] dt-bindings: display/bridge: nwl-dsi: Document video_pll clock

2020-08-29 Thread Robert Chiras (OSS)
From: Robert Chiras 

Add documentation for a new clock 'video_pll'.

Signed-off-by: Robert Chiras 
---
 Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml 
b/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml
index 04099f5..8b5741b 100644
--- a/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/nwl-dsi.yaml
@@ -37,6 +37,8 @@ properties:
   - description: TX_ESC clock (used in escape mode)
   - description: PHY_REF clock
   - description: LCDIF clock
+  - description: VIDEO_PLL clock (used to set the the PLL clock feeding 
both
+ phy_ref and DC pixel clock to a convenient rate)
 
   clock-names:
 items:
@@ -45,6 +47,7 @@ properties:
   - const: tx_esc
   - const: phy_ref
   - const: lcdif
+  - const: video_pll
 
   mux-controls:
 description:
-- 
2.7.4

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


[PATCH 0/5] Add new features to nwl-dsi driver

2020-08-29 Thread Robert Chiras (OSS)
From: Robert Chiras 

This patch-set adds the new following features to the nwl-dsi bridge driver:

1. Control Video PLL from nwl-dsi driver

Add support for the Video PLL into the nwl-dsi driver, in order
to better control it's rate, depending on the requested video mode.
Controlling the Video PLL from nwl-dsi is usefull, since it both drives the DC
pixel-clock and DPHY phy_ref clock.
On i.MX8MQ, the DC can be either DCSS or LCDIF.

2. Add new property to nwl-dsi: clock-drop-level

This new property is usefull in order to use DSI panels with the nwl-dsi
driver which require a higher overhead to the pixel-clock.
For example, the Raydium RM67191 DSI Panel works with 132M pixel-clock,
but it needs an overhead in order to work properly. So, the actual pixel-clock
fed into the DSI DPI interface needs to be lower than the one used ad DSI 
output.
This new property addresses this matter.

3. Add support to handle both inputs for nwl-dsi: DCSS and LCDIF

Laurentiu Palcu (1):
  drm/bridge: nwl-dsi: add support for DCSS

Robert Chiras (4):
  drm/bridge: nwl-dsi: Add support for video_pll
  dt-bindings: display/bridge: nwl-dsi: Document video_pll clock
  drm/bridge: nwl-dsi: Add support for clock-drop-level
  dt-bindings: display/bridge: nwl-dsi: Document fsl,clock-drop-level
property

 .../bindings/display/bridge/nwl-dsi.yaml   |   7 +
 drivers/gpu/drm/bridge/nwl-dsi.c   | 338 -
 2 files changed, 336 insertions(+), 9 deletions(-)

-- 
2.7.4

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


[PATCH 5/5] drm/bridge: nwl-dsi: add support for DCSS

2020-08-29 Thread Robert Chiras (OSS)
From: Laurentiu Palcu 

DCSS needs active low VSYNC and HSYNC. Also, move the input selection in
the probe function, as this will not change at runtime.

Signed-off-by: Laurentiu Palcu 
Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/bridge/nwl-dsi.c | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
index ac4aa0a..c30f7a8 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -143,6 +143,7 @@ struct nwl_dsi {
struct nwl_dsi_transfer *xfer;
struct list_head valid_modes;
u32 clk_drop_lvl;
+   bool use_dcss;
 };
 
 static const struct regmap_config nwl_dsi_regmap_config = {
@@ -1036,16 +1037,16 @@ static int nwl_dsi_get_dphy_params(struct nwl_dsi *dsi,
 
 static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
  const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
+ struct drm_display_mode *adjusted)
 {
struct nwl_dsi *dsi = bridge_to_dsi(bridge);
struct mode_config *config;
unsigned long pll_rate;
 
DRM_DEV_DEBUG_DRIVER(dsi->dev, "Fixup mode:\n");
-   drm_mode_debug_printmodeline(adjusted_mode);
+   drm_mode_debug_printmodeline(adjusted);
 
-   config = nwl_dsi_mode_probe(dsi, adjusted_mode);
+   config = nwl_dsi_mode_probe(dsi, adjusted);
if (!config)
return false;
 
@@ -1067,12 +1068,16 @@ static bool nwl_dsi_bridge_mode_fixup(struct drm_bridge 
*bridge,
}
/* Update the crtc_clock to be used by display controller */
if (config->crtc_clock)
-   adjusted_mode->crtc_clock = config->crtc_clock / 1000;
+   adjusted->crtc_clock = config->crtc_clock / 1000;
 
-
-   /* At least LCDIF + NWL needs active high sync */
-   adjusted_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
-   adjusted_mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
+   if (!dsi->use_dcss) {
+   /* At least LCDIF + NWL needs active high sync */
+   adjusted->flags |= (DRM_MODE_FLAG_PHSYNC | 
DRM_MODE_FLAG_PVSYNC);
+   adjusted->flags &= ~(DRM_MODE_FLAG_NHSYNC | 
DRM_MODE_FLAG_NVSYNC);
+   } else {
+   adjusted->flags &= ~(DRM_MODE_FLAG_PHSYNC | 
DRM_MODE_FLAG_PVSYNC);
+   adjusted->flags |= (DRM_MODE_FLAG_NHSYNC | 
DRM_MODE_FLAG_NVSYNC);
+   }
 
return true;
 }
@@ -1400,6 +1405,9 @@ static int nwl_dsi_select_input(struct nwl_dsi *dsi)
DRM_DEV_ERROR(dsi->dev, "Failed to select input: %d\n", ret);
 
of_node_put(remote);
+
+   dsi->use_dcss = use_dcss;
+
return ret;
 }
 
-- 
2.7.4

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


[PATCH 3/5] drm/bridge: nwl-dsi: Add support for clock-drop-level

2020-08-29 Thread Robert Chiras (OSS)
From: Robert Chiras 

The clock-drop-level is needed in order to add more blanking space needed
by DSI panels when sending DSI commands. One level is the equivalent of
phy_ref rate from the PLL rate. Since the PLL rate is targeted as highest
possible, each level should not get the crtc_clock too low, compared to
the actual clock.

Example for a clock of 132M, with "clock-drop-level = <1>" in dts file
will result in a crtc_clock of 129M, using the following logic:
- video_pll rate to provide both phy_ref rate of 24M and pixel-clock
  of 132M is 1056M (divisor /43 for phy_ref and /8 for pixel-clock)
- from this rate, we subtract the equivalent of phy_ref (24M) but
  keep the same divisor. This way, the video_pll rate will be 1056 - 24
= 1032M.
- new pixel-clock will be: 1032 / 8 = 129M

For a "clock-drop-level = <2>", new pixel-clock will be:
(1056 - (24 * 2)) / 8 = 1008 / 8 = 126M

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/bridge/nwl-dsi.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
index 1228466..ac4aa0a 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -142,6 +142,7 @@ struct nwl_dsi {
 
struct nwl_dsi_transfer *xfer;
struct list_head valid_modes;
+   u32 clk_drop_lvl;
 };
 
 static const struct regmap_config nwl_dsi_regmap_config = {
@@ -842,13 +843,14 @@ static unsigned long nwl_dsi_get_lcm(unsigned long a, 
unsigned long b)
 
return ((unsigned long long)a * b) / gcf;
 }
-
 /*
  * This function tries to adjust the crtc_clock for a DSI device in such a way
  * that the video pll will be able to satisfy both Display Controller pixel
  * clock (feeding out DPI interface) and our input phy_ref clock.
+ * Also, the DC pixel clock must be lower than the actual clock in order to
+ * have enough blanking space to send DSI commands, if the device is a panel.
  */
-static void nwl_dsi_setup_pll_config(struct mode_config *config)
+static void nwl_dsi_setup_pll_config(struct mode_config *config, u32 lvl)
 {
unsigned long pll_rate;
int div;
@@ -908,7 +910,6 @@ static void nwl_dsi_setup_pll_config(struct mode_config 
*config)
}
 }
 
-
 /*
  * This function will try the required phy speed for current mode
  * If the phy speed can be achieved, the phy will save the speed
@@ -1103,7 +1104,7 @@ nwl_dsi_bridge_mode_valid(struct drm_bridge *bridge,
 
pll_rate = config->pll_rates[config->phy_rate_idx];
if (dsi->pll_clk && !pll_rate)
-   nwl_dsi_setup_pll_config(config);
+   nwl_dsi_setup_pll_config(config, dsi->clk_drop_lvl);
 
return MODE_OK;
 }
@@ -1248,6 +1249,7 @@ static const struct drm_bridge_funcs nwl_dsi_bridge_funcs 
= {
 static int nwl_dsi_parse_dt(struct nwl_dsi *dsi)
 {
struct platform_device *pdev = to_platform_device(dsi->dev);
+   struct device_node *np = dsi->dev->of_node;
struct clk *clk;
void __iomem *base;
int ret;
@@ -1364,6 +1366,8 @@ static int nwl_dsi_parse_dt(struct nwl_dsi *dsi)
return PTR_ERR(dsi->rst_dpi);
}
 
+   of_property_read_u32(np, "fsl,clock-drop-level", >clk_drop_lvl);
+
INIT_LIST_HEAD(>valid_modes);
 
return 0;
-- 
2.7.4

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


Re: [EXT] [PATCH v8 2/2] drm/bridge: Add NWL MIPI DSI host controller support

2019-12-04 Thread Robert Chiras
On Mi, 2019-12-04 at 13:06 +0100, Guido Günther wrote:
> Hi Robert,
> On Tue, Dec 03, 2019 at 09:50:03AM +, Robert Chiras wrote:
> > 
> > Hi Guido,
> > 
> > Since your last revision sent, I've done more tests here and found
> > a
> > few more improvements that could be added to this driver.
> > See inline.
> > 
> > On Lu, 2019-12-02 at 20:35 +0100, Guido Günther wrote:
> > > 
> > > Caution: EXT Email
> > > 
> > > This adds initial support for the NWL MIPI DSI Host controller
> > > found
> > > on
> > > i.MX8 SoCs.
> > > 
> > > It adds support for the i.MX8MQ but the same IP can be found on
> > > e.g. the i.MX8QXP.
> > > 
> > > It has been tested on the Librem 5 devkit using mxsfb.
> > > 
> > > Signed-off-by: Guido Günther 
> > > Co-developed-by: Robert Chiras 
> > > Signed-off-by: Robert Chiras 
> > > Tested-by: Robert Chiras 
> > > ---
> > >  drivers/gpu/drm/bridge/Kconfig   |   16 +
> > >  drivers/gpu/drm/bridge/Makefile  |3 +
> > >  drivers/gpu/drm/bridge/nwl-dsi.c | 1230
> > > ++
> > >  drivers/gpu/drm/bridge/nwl-dsi.h |  144 
> > >  4 files changed, 1393 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi.c
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi.h
> > > 
> > > diff --git a/drivers/gpu/drm/bridge/Kconfig
> > > b/drivers/gpu/drm/bridge/Kconfig
> > > index 34362976cd6f..6fb534f55d22 100644
> > > --- a/drivers/gpu/drm/bridge/Kconfig
> > > +++ b/drivers/gpu/drm/bridge/Kconfig
> > > @@ -65,6 +65,22 @@ config DRM_MEGACHIPS_STDP_GE_B850V3_FW
> > >    to DP++. This is used with the i.MX6 imx-ldb
> > >    driver. You are likely to say N here.
> > > 
> > > +config DRM_NWL_MIPI_DSI
> > > +   tristate "Northwest Logic MIPI DSI Host controller"
> > > +   depends on DRM
> > > +   depends on COMMON_CLK
> > > +   depends on OF && HAS_IOMEM
> > > +   select DRM_KMS_HELPER
> > > +   select DRM_MIPI_DSI
> > > +   select DRM_PANEL_BRIDGE
> > > +   select GENERIC_PHY_MIPI_DPHY
> > > +   select MFD_SYSCON
> > > +   select MULTIPLEXER
> > > +   select REGMAP_MMIO
> > > +   help
> > > + This enables the Northwest Logic MIPI DSI Host
> > > controller
> > > as
> > > + for example found on NXP's i.MX8 Processors.
> > > +
> > >  config DRM_NXP_PTN3460
> > > tristate "NXP PTN3460 DP/LVDS bridge"
> > > depends on OF
> > > diff --git a/drivers/gpu/drm/bridge/Makefile
> > > b/drivers/gpu/drm/bridge/Makefile
> > > index 4934fcf5a6f8..c3f3a43e9b8f 100644
> > > --- a/drivers/gpu/drm/bridge/Makefile
> > > +++ b/drivers/gpu/drm/bridge/Makefile
> > > @@ -16,4 +16,7 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
> > >  obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
> > >  obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
> > >  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> > > +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o
> > >  obj-y += synopsys/
> > > +
> > > +header-test-y += nwl-dsi.h
> > > diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c
> > > b/drivers/gpu/drm/bridge/nwl-dsi.c
> > > new file mode 100644
> > > index ..023191894fe4
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/bridge/nwl-dsi.c
> > > @@ -0,0 +1,1230 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/*
> > > + * i.MX8 NWL MIPI DSI host driver
> > > + *
> > > + * Copyright (C) 2017 NXP
> > > + * Copyright (C) 2019 Purism SPC
> > > + */
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +#include 
> > > +#include 
> > > +
> > > +#include "nwl-dsi.h"
> > > +
> 

Re: [EXT] [PATCH v8 2/2] drm/bridge: Add NWL MIPI DSI host controller support

2019-12-03 Thread Robert Chiras
Hi Guido,

Since your last revision sent, I've done more tests here and found a
few more improvements that could be added to this driver.
See inline.

On Lu, 2019-12-02 at 20:35 +0100, Guido Günther wrote:
> Caution: EXT Email
> 
> This adds initial support for the NWL MIPI DSI Host controller found
> on
> i.MX8 SoCs.
> 
> It adds support for the i.MX8MQ but the same IP can be found on
> e.g. the i.MX8QXP.
> 
> It has been tested on the Librem 5 devkit using mxsfb.
> 
> Signed-off-by: Guido Günther 
> Co-developed-by: Robert Chiras 
> Signed-off-by: Robert Chiras 
> Tested-by: Robert Chiras 
> ---
>  drivers/gpu/drm/bridge/Kconfig   |   16 +
>  drivers/gpu/drm/bridge/Makefile  |3 +
>  drivers/gpu/drm/bridge/nwl-dsi.c | 1230
> ++
>  drivers/gpu/drm/bridge/nwl-dsi.h |  144 
>  4 files changed, 1393 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi.c
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi.h
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig
> b/drivers/gpu/drm/bridge/Kconfig
> index 34362976cd6f..6fb534f55d22 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -65,6 +65,22 @@ config DRM_MEGACHIPS_STDP_GE_B850V3_FW
>    to DP++. This is used with the i.MX6 imx-ldb
>    driver. You are likely to say N here.
> 
> +config DRM_NWL_MIPI_DSI
> +   tristate "Northwest Logic MIPI DSI Host controller"
> +   depends on DRM
> +   depends on COMMON_CLK
> +   depends on OF && HAS_IOMEM
> +   select DRM_KMS_HELPER
> +   select DRM_MIPI_DSI
> +   select DRM_PANEL_BRIDGE
> +   select GENERIC_PHY_MIPI_DPHY
> +   select MFD_SYSCON
> +   select MULTIPLEXER
> +   select REGMAP_MMIO
> +   help
> + This enables the Northwest Logic MIPI DSI Host controller
> as
> + for example found on NXP's i.MX8 Processors.
> +
>  config DRM_NXP_PTN3460
> tristate "NXP PTN3460 DP/LVDS bridge"
> depends on OF
> diff --git a/drivers/gpu/drm/bridge/Makefile
> b/drivers/gpu/drm/bridge/Makefile
> index 4934fcf5a6f8..c3f3a43e9b8f 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -16,4 +16,7 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
>  obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
>  obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
>  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi.o
>  obj-y += synopsys/
> +
> +header-test-y += nwl-dsi.h
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c
> b/drivers/gpu/drm/bridge/nwl-dsi.c
> new file mode 100644
> index ..023191894fe4
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi.c
> @@ -0,0 +1,1230 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * i.MX8 NWL MIPI DSI host driver
> + *
> + * Copyright (C) 2017 NXP
> + * Copyright (C) 2019 Purism SPC
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#include "nwl-dsi.h"
> +
> +#define DRV_NAME "nwl-dsi"
> +
> +/* i.MX8 NWL quirks */
> +/* i.MX8MQ errata E11418 */
> +#define E11418_HS_MODE_QUIRK   BIT(0)
> +
> +#define NWL_DSI_MIPI_FIFO_TIMEOUT msecs_to_jiffies(500)
> +
> +enum transfer_direction {
> +   DSI_PACKET_SEND,
> +   DSI_PACKET_RECEIVE,
> +};
> +
> +/* Possible platform specific clocks */
> +#define NWL_DSI_CLK_CORE   "core"
> +#define NWL_DSI_MAX_PLATFORM_CLOCKS 1
> +
> +#define NWL_DSI_ENDPOINT_LCDIF 0
> +#define NWL_DSI_ENDPOINT_DCSS 1
> +
> +struct nwl_dsi_plat_clk_config {
> +   const char *id;
> +   struct clk *clk;
> +   bool present;
> +};
> +
> +struct nwl_dsi_transfer {
> +   const struct mipi_dsi_msg *msg;
> +   struct mipi_dsi_packet packet;
> +   struct completion completed;
> +
> +   int status; /* status of transmission */
> +   enum transfer_direction direction;
> +   bool need_bta;
> +   u8 cmd;
> +   u16 rx_word_count;
> +   size_t tx_len; /* in bytes */
> +   size_t rx_len; /* in bytes */
> +};
> +
> +struct nwl_dsi {
> +   struct drm_bridge bridge;
> +   struct mipi_dsi_host dsi_host;
> +   struct drm_bridge *panel_bridge;
> +   struct device *dev;
> +   stru

[PATCH v4 11/14] drm/mxsfb: Improve the axi clock usage

2019-08-30 Thread Robert Chiras
Currently, the enable of the axi clock return status is ignored, causing
issues when the enable fails then we try to disable it. Therefore, it is
better to check the return status and disable it only when enable
succeeded.
Also, remove the helper functions around clk_axi, since we can directly
use the clk API function for enable/disable the clock. Those functions
are already checking for NULL clk and returning 0 if that's the case.

Signed-off-by: Robert Chiras 
Acked-by: Leonard Crestez 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c |  8 
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 32 +---
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  3 ---
 3 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index a4ba368..e727f5e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -408,7 +408,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 {
dma_addr_t paddr;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
@@ -425,7 +425,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
 {
mxsfb_disable_controller(mxsfb);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
@@ -451,8 +451,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
 
paddr = mxsfb_get_fb_paddr(mxsfb);
if (paddr) {
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
}
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index d8686c7..888b520 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -94,18 +94,6 @@ drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe 
*pipe)
return container_of(pipe, struct mxsfb_drm_private, pipe);
 }
 
-void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_prepare_enable(mxsfb->clk_axi);
-}
-
-void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_disable_unprepare(mxsfb->clk_axi);
-}
-
 /**
  * mxsfb_atomic_helper_check - validate state object
  * @dev: DRM device
@@ -265,25 +253,31 @@ static void mxsfb_pipe_update(struct 
drm_simple_display_pipe *pipe,
 static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+   int ret = 0;
+
+   ret = clk_prepare_enable(mxsfb->clk_axi);
+   if (ret)
+   return ret;
 
/* Clear and enable VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
-   return 0;
+   return ret;
 }
 
 static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
 
+   if (clk_prepare_enable(mxsfb->clk_axi))
+   return;
+
/* Disable and clear VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
@@ -444,7 +438,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
struct mxsfb_drm_private *mxsfb = drm->dev_private;
u32 reg;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
 
reg = readl(mxsfb->base + LCDC_CTRL1);
 
@@ -453,7 +447,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
return IRQ_HANDLED;
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index a178173..54c0644 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -39,9 +39,6 @@ struct mxsfb_drm_private {
 int mxsfb_setup_crtc(struct 

[PATCH v4 14/14] drm/mxsfb: Add support for live pixel format change

2019-08-30 Thread Robert Chiras
This IP requires full stop and re-start when changing display timings,
but we can change the pixel format while running.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 317575e..5607fc0 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -494,6 +494,7 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
struct drm_crtc *crtc = >crtc;
struct drm_plane_state *new_state = pipe->plane.state;
struct drm_framebuffer *fb = pipe->plane.state->fb;
+   struct drm_framebuffer *old_fb = state->fb;
struct drm_pending_vblank_event *event;
u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
@@ -510,7 +511,7 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   if (!fb)
+   if (!fb || !old_fb)
return;
 
fb_addr = mxsfb_get_fb_paddr(mxsfb);
@@ -533,4 +534,17 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
src_w = new_state->src_w >> 16;
mxsfb_set_fb_hcrop(mxsfb, src_w, stride);
}
+
+   if (old_fb->format->format != fb->format->format) {
+   struct drm_format_name_buf old_fmt_buf;
+   struct drm_format_name_buf new_fmt_buf;
+
+   DRM_DEV_DEBUG_DRIVER(crtc->dev->dev,
+   "Switching pixel format: %s -> %s\n",
+   drm_get_format_name(old_fb->format->format,
+   _fmt_buf),
+   drm_get_format_name(fb->format->format,
+   _fmt_buf));
+   mxsfb_set_pixel_fmt(mxsfb, true);
+   }
 }
-- 
2.7.4

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

[PATCH v4 12/14] drm/mxsfb: Clear OUTSTANDING_REQS bits

2019-08-30 Thread Robert Chiras
Bit 21 can alter the CTRL2_OUTSTANDING_REQS value right after the eLCDIF
is enabled, since it comes up with default value of 1 (this behaviour
has been seen on some imx8 platforms).
In order to fix this, clear CTRL2_OUTSTANDING_REQS bits before setting
its value.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index e727f5e..a12f53d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -225,6 +225,13 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk);
 
if (mxsfb->devdata->ipversion >= 4) {
+   /*
+* On some platforms, bit 21 is defaulted to 1, which may alter
+* the below setting. So, to make sure we have the right setting
+* clear all the bits for CTRL2_OUTSTANDING_REQS.
+*/
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
/* Assert LCD Reset bit */
-- 
2.7.4

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

[PATCH v4 00/14] Improvements and fixes for mxsfb DRM driver

2019-08-30 Thread Robert Chiras
This patch-set improves the use of eLCDIF block on iMX 8 SoCs (like 8MQ, 8MM
and 8QXP). Following, are the new features added and fixes from this
patch-set:

1. Add support for drm_bridge
On 8MQ and 8MM, the LCDIF block is not directly connected to a parallel
display connector, where an LCD panel can be attached, but instead it is
connected to DSI controller. Since this DSI stands between the display
controller (eLCDIF) and the physical connector, the DSI can be implemented
as a DRM bridge. So, in order to be able to connect the mxsfb driver to
the DSI driver, the support for a drm_bridge was needed in mxsfb DRM
driver (the actual driver for the eLCDIF block).

2. Add support for additional pixel formats
Some of the pixel formats needed by Android were not implemented in this
driver, but they were actually supported. So, add support for them.

3. Add support for horizontal stride
Having support for horizontal stride allows the use of eLCDIF with a GPU
(for example) that can only output resolution sizes multiple of a power of
8. For example, 1080 is not a power of 16, so in order to support 1920x1080
output from GPUs that can produce linear buffers only in sizes multiple to 16,
this feature is needed.

3. Few minor features and bug-fixing
The addition of max-memory-bandwidth DT property was actually needed in order
to limit the bandwidth usage of the eLCDIF block. This is need on systems where
multiple display controllers are presend and the memory bandwidth is not
enough to handle all of them at maximum capacity (like it is the case on
8MQ, where there are two display controllers: DCSS and eLCDIF).
The rest of the patches are bug-fixes.

v4:
- Removed the "Fix vblank events" patch (will cover this issue later, on a
  separate thread)
- Colleted "Tested-by" from Guido
- Collected "Reviewed-by" from Rob Herring

v3:
- Removed the max-res property patches and added support for
  max-memory-bandwidth property, as it is also implemented in other drivers
- Removed unnecessary drm_vblank_off in probe

v2:
- Collected Tested-by from Guido
- Split the first patch, which added more than one feature into relevant
  patches, explaining each feature added
- Also split the second patch into more patches, to differentiate between
  the feature itself (additional pixel formats support) and the cleanup
  of the register definitions for a better representation (guido)
- Included a patch submitted by Guido, while he was testing my patch-set

Guido Günther (1):
  drm/mxsfb: Read bus flags from bridge if present

Mirela Rabulea (1):
  drm/mxsfb: Signal mode changed when bpp changed

Robert Chiras (12):
  drm/mxsfb: Update mxsfb to support a bridge
  drm/mxsfb: Add defines for the rest of registers
  drm/mxsfb: Reset vital registers for a proper initialization
  drm/mxsfb: Update register definitions using bit manipulation defines
  drm/mxsfb: Update mxsfb with additional pixel formats
  drm/mxsfb: Add max-memory-bandwidth property for MXSFB
  dt-bindings: display: Add max-memory-bandwidth property for mxsfb
  drm/mxsfb: Update mxsfb to support LCD reset
  drm/mxsfb: Improve the axi clock usage
  drm/mxsfb: Clear OUTSTANDING_REQS bits
  drm/mxsfb: Add support for horizontal stride
  drm/mxsfb: Add support for live pixel format change

 .../devicetree/bindings/display/mxsfb.txt  |   5 +
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 287 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 194 --
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  12 +-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  |  26 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 193 +-
 6 files changed, 581 insertions(+), 136 deletions(-)

-- 
2.7.4

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

[PATCH v4 10/14] drm/mxsfb: Update mxsfb to support LCD reset

2019-08-30 Thread Robert Chiras
The eLCDIF controller has control pin for the external LCD reset pin.
Add support for it and assert this pin in enable and de-assert it in
disable.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 14 ++
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  2 ++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1be29f5..a4ba368 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -224,9 +224,12 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
-   if (mxsfb->devdata->ipversion >= 4)
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   }
 
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -244,11 +247,14 @@ static void mxsfb_disable_controller(struct 
mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
-   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(0x7),
   mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
-
-   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+   /* De-assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+   }
 
/*
 * Even if we disable the controller here, it will still continue
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index dc4daa0..0f63ba1 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -108,6 +108,8 @@
 #define CTRL2_LINE_PATTERN_BGR 5
 #define CTRL2_LINE_PATTERN_CLR 7
 
+#define CTRL2_LCD_RESETBIT(0)
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   REG_PUT((x), 31, 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   REG_GET((x), 31, 16)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   REG_PUT((x), 15, 0)
-- 
2.7.4

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

[PATCH v4 04/14] drm/mxsfb: Reset vital registers for a proper initialization

2019-08-29 Thread Robert Chiras
Some of the registers, like LCDC_CTRL, CTRL2_OUTSTANDING_REQS and
CTRL1_RECOVERY_ON_UNDERFLOW needs to be properly cleared/initialized
for a better start and stop routine.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index b69ace8..5e44f57 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -127,6 +127,10 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_OUTSTANDING_REQS(REQ_16),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
 
@@ -136,12 +140,19 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
writel(reg, mxsfb->base + LCDC_VDCTRL4);
 
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+   writel(CTRL1_RECOVERY_ON_UNDERFLOW, mxsfb->base + LCDC_CTRL1 + REG_SET);
 }
 
 static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
/*
 * Even if we disable the controller here, it will still continue
 * until its FIFOs are running out of data
@@ -295,6 +306,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
dma_addr_t paddr;
 
mxsfb_enable_axi_clk(mxsfb);
+   writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
/* Write cur_buf as well to avoid an initial corrupt frame */
-- 
2.7.4



[PATCH v4 05/14] drm/mxsfb: Update register definitions using bit manipulation defines

2019-08-29 Thread Robert Chiras
Use BIT(x) and GEN_MASK(h, l) for better representation the inside of
various registers.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 151 ++---
 1 file changed, 89 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 71426aa..9fcb1db 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -40,66 +40,93 @@
 #define LCDC_AS_BUF0x220
 #define LCDC_AS_NEXT_BUF   0x230
 
-#define CTRL_SFTRST(1 << 31)
-#define CTRL_CLKGATE   (1 << 30)
-#define CTRL_BYPASS_COUNT  (1 << 19)
-#define CTRL_VSYNC_MODE(1 << 18)
-#define CTRL_DOTCLK_MODE   (1 << 17)
-#define CTRL_DATA_SELECT   (1 << 16)
-#define CTRL_SET_BUS_WIDTH(x)  (((x) & 0x3) << 10)
-#define CTRL_GET_BUS_WIDTH(x)  (((x) >> 10) & 0x3)
-#define CTRL_BUS_WIDTH_MASK(0x3 << 10)
-#define CTRL_SET_WORD_LENGTH(x)(((x) & 0x3) << 8)
-#define CTRL_GET_WORD_LENGTH(x)(((x) >> 8) & 0x3)
-#define CTRL_MASTER(1 << 5)
-#define CTRL_DF16  (1 << 3)
-#define CTRL_DF18  (1 << 2)
-#define CTRL_DF24  (1 << 1)
-#define CTRL_RUN   (1 << 0)
-
-#define CTRL1_RECOVERY_ON_UNDERFLOW(1 << 24)
-#define CTRL1_FIFO_CLEAR   (1 << 21)
-#define CTRL1_SET_BYTE_PACKAGING(x)(((x) & 0xf) << 16)
-#define CTRL1_GET_BYTE_PACKAGING(x)(((x) >> 16) & 0xf)
-#define CTRL1_CUR_FRAME_DONE_IRQ_EN(1 << 13)
-#define CTRL1_CUR_FRAME_DONE_IRQ   (1 << 9)
-
-#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
-
-#define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
-#define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
-#define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0x)
-#define TRANSFER_COUNT_GET_HCOUNT(x)   ((x) & 0x)
-
-#define VDCTRL0_ENABLE_PRESENT (1 << 28)
-#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
-#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
-#define VDCTRL0_ENABLE_ACT_HIGH(1 << 24)
-#define VDCTRL0_VSYNC_PERIOD_UNIT  (1 << 21)
-#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
-#define VDCTRL0_HALF_LINE  (1 << 19)
-#define VDCTRL0_HALF_LINE_MODE (1 << 18)
-#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3)
-#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3)
-
-#define VDCTRL2_SET_HSYNC_PERIOD(x)((x) & 0x3)
-#define VDCTRL2_GET_HSYNC_PERIOD(x)((x) & 0x3)
-
-#define VDCTRL3_MUX_SYNC_SIGNALS   (1 << 29)
-#define VDCTRL3_VSYNC_ONLY (1 << 28)
-#define SET_HOR_WAIT_CNT(x)(((x) & 0xfff) << 16)
-#define GET_HOR_WAIT_CNT(x)(((x) >> 16) & 0xfff)
-#define SET_VERT_WAIT_CNT(x)   ((x) & 0x)
-#define GET_VERT_WAIT_CNT(x)   ((x) & 0x)
-
-#define VDCTRL4_SET_DOTCLK_DLY(x)  (((x) & 0x7) << 29) /* v4 only */
-#define VDCTRL4_GET_DOTCLK_DLY(x)  (((x) >> 29) & 0x7) /* v4 only */
-#define VDCTRL4_SYNC_SIGNALS_ON(1 << 18)
-#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3)
-
-#define DEBUG0_HSYNC   (1 < 26)
-#define DEBUG0_VSYNC   (1 < 25)
+/* reg bit manipulation */
+#define REG_PUT(x, h, l) (((x) << (l)) & GENMASK(h, l))
+#define REG_GET(x, h, l) (((x) & GENMASK(h, l)) >> (l))
+
+#define CTRL_SFTRSTBIT(31)
+#define CTRL_CLKGATE   BIT(30)
+#define CTRL_SHIFT_DIR(x)  REG_PUT((x), 26, 26)
+#define CTRL_SHIFT_NUM(x)  REG_PUT((x), 25, 21)
+#define CTRL_BYPASS_COUNT  BIT(19)
+#define CTRL_VSYNC_MODEBIT(18)
+#define CTRL_DOTCLK_MODE   BIT(17)
+#define CTRL_DATA_SELECT   BIT(16)
+#define CTRL_INPUT_SWIZZLE(x)  REG_PUT((x), 15, 14)
+#define CTRL_CSC_SWIZZLE(x)REG_PUT((x), 13, 12)
+#define CTRL_SET_BUS_WIDTH(x)  REG_PUT((x), 11, 10)
+#define CTRL_GET_BUS_WIDTH(x)  REG_GET((x), 11, 10)
+#define CTRL_BUS_WIDTH_MASKREG_PUT((0x3), 11, 10)
+#define CTRL_SET_WORD_LENGTH(x)REG_PUT((x), 9, 8)
+#define CTRL_GET_WORD_LENGTH(x)REG_GET((x), 9, 8)
+#define CTRL_MASTERBIT(5)
+#define CTRL_DF16  BIT(3)
+#define CTRL_DF18  BIT(2)
+#define CTRL_DF24 

[PATCH v4 03/14] drm/mxsfb: Add defines for the rest of registers

2019-08-29 Thread Robert Chiras
Some of the existing registers in this controller are not defined, but
also not used. Add them to the register definitions, so that they can be
easily used in future improvements or fixes.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 932d7ea..71426aa 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -14,19 +14,31 @@
 
 #define LCDC_CTRL  0x00
 #define LCDC_CTRL1 0x10
+#define LCDC_V4_CTRL2  0x20
 #define LCDC_V3_TRANSFER_COUNT 0x20
 #define LCDC_V4_TRANSFER_COUNT 0x30
 #define LCDC_V4_CUR_BUF0x40
 #define LCDC_V4_NEXT_BUF   0x50
 #define LCDC_V3_CUR_BUF0x30
 #define LCDC_V3_NEXT_BUF   0x40
+#define LCDC_TIMING0x60
 #define LCDC_VDCTRL0   0x70
 #define LCDC_VDCTRL1   0x80
 #define LCDC_VDCTRL2   0x90
 #define LCDC_VDCTRL3   0xa0
 #define LCDC_VDCTRL4   0xb0
+#define LCDC_DVICTRL0  0xc0
+#define LCDC_DVICTRL1  0xd0
+#define LCDC_DVICTRL2  0xe0
+#define LCDC_DVICTRL3  0xf0
+#define LCDC_DVICTRL4  0x100
+#define LCDC_V4_DATA   0x180
+#define LCDC_V3_DATA   0x1b0
 #define LCDC_V4_DEBUG0 0x1d0
 #define LCDC_V3_DEBUG0 0x1f0
+#define LCDC_AS_CTRL   0x210
+#define LCDC_AS_BUF0x220
+#define LCDC_AS_NEXT_BUF   0x230
 
 #define CTRL_SFTRST(1 << 31)
 #define CTRL_CLKGATE   (1 << 30)
@@ -45,12 +57,15 @@
 #define CTRL_DF24  (1 << 1)
 #define CTRL_RUN   (1 << 0)
 
+#define CTRL1_RECOVERY_ON_UNDERFLOW(1 << 24)
 #define CTRL1_FIFO_CLEAR   (1 << 21)
 #define CTRL1_SET_BYTE_PACKAGING(x)(((x) & 0xf) << 16)
 #define CTRL1_GET_BYTE_PACKAGING(x)(((x) >> 16) & 0xf)
 #define CTRL1_CUR_FRAME_DONE_IRQ_EN(1 << 13)
 #define CTRL1_CUR_FRAME_DONE_IRQ   (1 << 9)
 
+#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0x)
-- 
2.7.4



[PATCH v4 09/14] dt-bindings: display: Add max-memory-bandwidth property for mxsfb

2019-08-29 Thread Robert Chiras
Add new optional property 'max-memory-bandwidth', to limit the maximum
bandwidth used by the MXSFB_DRM driver.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/display/mxsfb.txt | 5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt 
b/Documentation/devicetree/bindings/display/mxsfb.txt
index 472e1ea..c8dca50 100644
--- a/Documentation/devicetree/bindings/display/mxsfb.txt
+++ b/Documentation/devicetree/bindings/display/mxsfb.txt
@@ -14,6 +14,11 @@ Required properties:
 - "pix" for the LCDIF block clock
 - (MX6SX-only) "axi", "disp_axi" for the bus interface clock
 
+Optional properties:
+- max-memory-bandwidth: maximum bandwidth in bytes per second that the
+   controller can handle; if not present, the memory
+   interface is fast enough to handle all possible video modes
+
 Required sub-nodes:
   - port: The connection to an encoder chip.
 
-- 
2.7.4



[PATCH v4 06/14] drm/mxsfb: Update mxsfb with additional pixel formats

2019-08-29 Thread Robert Chiras
Since version 4 of eLCDIF, there are some registers that can do
transformations on the input data, like re-arranging the pixel
components. By doing that, we can support more pixel formats.
This patch adds support for X/ABGR and RGBX/A. Although, the local alpha
is not supported by eLCDIF, the alpha pixel formats were added to the
supported pixel formats but it will be ignored. This was necessary since
there are systems (like Android) that requires such pixel formats.

Also, add support for the following pixel formats:
16 bpp: RG16 ,BG16, XR15, XB15, AR15, AB15

Set the bus format based on input from the user and panel
capabilities.
Save the bus format in crtc->mode.private_flags, so the bridge can
use it.

Signed-off-by: Robert Chiras 
Signed-off-by: Mirela Rabulea 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 147 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  30 ++--
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |   3 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  15 
 4 files changed, 163 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 5e44f57..1be29f5 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -43,14 +43,17 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private 
*mxsfb, u32 val)
 }
 
 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
-static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb, bool update)
 {
struct drm_crtc *crtc = >pipe.crtc;
struct drm_device *drm = crtc->dev;
const u32 format = crtc->primary->state->fb->format->format;
-   u32 ctrl, ctrl1;
+   u32 ctrl = 0, ctrl1 = 0;
+   bool bgr_format = true;
+   struct drm_format_name_buf format_name_buf;
 
-   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
+   if (!update)
+   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 
/*
 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
@@ -59,64 +62,158 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private 
*mxsfb)
 * to arbitrary value. This limitation should not pose an issue.
 */
 
-   /* CTRL1 contains IRQ config and status bits, preserve those. */
-   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
-   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   if (!update) {
+   /* CTRL1 contains IRQ config and status bits, preserve those. */
+   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
+   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   }
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Setting up %s mode\n",
+drm_get_format_name(format, _name_buf));
+
+   /* Do some clean-up that we might have from a previous mode */
+   ctrl &= ~CTRL_SHIFT_DIR(1);
+   ctrl &= ~CTRL_SHIFT_NUM(0x3f);
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR) |
+  CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
 
switch (format) {
-   case DRM_FORMAT_RGB565:
-   dev_dbg(drm->dev, "Setting up RGB565 mode\n");
+   case DRM_FORMAT_BGR565: /* BG16 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR) |
+   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_RGB565: /* RG16 */
+   ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl &= ~CTRL_DF16;
+   ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
+   break;
+   case DRM_FORMAT_XBGR1555: /* XB15 */
+   case DRM_FORMAT_ABGR1555: /* AB15 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR) |
+   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_XRGB1555: /* XR15 */
+   case DRM_FORMAT_ARGB1555: /* AR15 */
ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl |= CTRL_DF16;
ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
break;
-   case DRM_FORMAT_XRGB:
-   dev_dbg(drm->dev, "Setting up XRGB mode\n");
+   case DRM_FORMAT_RGBX: /* RX24 */
+   case DRM_FORMAT_RGBA: /* RA

[PATCH v4 13/14] drm/mxsfb: Add support for horizontal stride

2019-08-29 Thread Robert Chiras
Besides the eLCDIF block, there is another IP block, used in the past
for EPDC panels. Since the iMX.8mq doesn't have an EPDC connector, this
block is not documented, but we can use it to do additional operations
on the frame buffer.
In this case, we can use the pigeon registers from this IP block in
order to do horizontal crop on the frame buffer processed by the eLCDIF
block.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 79 --
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  1 +
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 16 
 3 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index a12f53d..317575e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -15,6 +15,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -435,13 +436,66 @@ void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+void mxsfb_set_fb_hcrop(struct mxsfb_drm_private *mxsfb, u32 src_w, u32 fb_w)
+{
+   u32 mask_cnt, htotal, hcount;
+   u32 vdctrl2, vdctrl3, vdctrl4, transfer_count;
+   u32 pigeon_12_0, pigeon_12_1, pigeon_12_2;
+
+   if (src_w == fb_w) {
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   return;
+   }
+
+   transfer_count = readl(mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+   hcount = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+
+   transfer_count &= ~TRANSFER_COUNT_SET_HCOUNT(0x);
+   transfer_count |= TRANSFER_COUNT_SET_HCOUNT(fb_w);
+   writel(transfer_count, mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+
+   vdctrl2 = readl(mxsfb->base + LCDC_VDCTRL2);
+   htotal  = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2);
+   htotal  += fb_w - hcount;
+   vdctrl2 &= ~VDCTRL2_SET_HSYNC_PERIOD(0x3);
+   vdctrl2 |= VDCTRL2_SET_HSYNC_PERIOD(htotal);
+   writel(vdctrl2, mxsfb->base + LCDC_VDCTRL2);
+
+   vdctrl4 = readl(mxsfb->base + LCDC_VDCTRL4);
+   vdctrl4 &= ~SET_DOTCLK_H_VALID_DATA_CNT(0x3);
+   vdctrl4 |= SET_DOTCLK_H_VALID_DATA_CNT(fb_w);
+   writel(vdctrl4, mxsfb->base + LCDC_VDCTRL4);
+
+   /* configure related pigeon registers */
+   vdctrl3  = readl(mxsfb->base + LCDC_VDCTRL3);
+   mask_cnt = GET_HOR_WAIT_CNT(vdctrl3) - 5;
+
+   pigeon_12_0 = PIGEON_12_0_SET_STATE_MASK(0x24)  |
+ PIGEON_12_0_SET_MASK_CNT(mask_cnt)|
+ PIGEON_12_0_SET_MASK_CNT_SEL(0x6) |
+ PIGEON_12_0_POL_ACTIVE_LOW|
+ PIGEON_12_0_EN;
+   writel(pigeon_12_0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+
+   pigeon_12_1 = PIGEON_12_1_SET_CLR_CNT(src_w) |
+ PIGEON_12_1_SET_SET_CNT(0x0);
+   writel(pigeon_12_1, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   pigeon_12_2 = 0x0;
+   writel(pigeon_12_2, mxsfb->base + HW_EPDC_PIGEON_12_2);
+}
+
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
   struct drm_plane_state *state)
 {
struct drm_simple_display_pipe *pipe = >pipe;
struct drm_crtc *crtc = >crtc;
+   struct drm_plane_state *new_state = pipe->plane.state;
+   struct drm_framebuffer *fb = pipe->plane.state->fb;
struct drm_pending_vblank_event *event;
-   dma_addr_t paddr;
+   u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
spin_lock_irq(>dev->event_lock);
event = crtc->state->event;
@@ -456,10 +510,27 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   paddr = mxsfb_get_fb_paddr(mxsfb);
-   if (paddr) {
+   if (!fb)
+   return;
+
+   fb_addr = mxsfb_get_fb_paddr(mxsfb);
+   if (mxsfb->devdata->ipversion >= 4) {
+   cpp = fb->format->cpp[0];
+   src_off = (new_state->src_y >> 16) * fb->pitches[0] +
+ (new_state->src_x >> 16) * cpp;
+   fb_addr += fb->offsets[0] + src_off;
+   }
+
+   if (fb_addr) {
clk_prepare_enable(mxsfb->clk_axi);
-   writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
+   writel(fb_addr, mxsfb->base + mxsfb->devdata->next_buf);
clk_disable_unprepare(mxsfb->clk_axi);
}
+
+   if (mxsfb->devdata->ipversion >= 4 &&
+   unlikely(drm_atomic_crtc_needs_modeset(new_state->crtc->state))) {
+   stride = DIV_ROUND_UP(fb->pitches[0], cpp);
+   src_w = new_state->src_w >> 16;
+   mxsfb_set_fb_h

[PATCH v4 07/14] drm/mxsfb: Signal mode changed when bpp changed

2019-08-29 Thread Robert Chiras
From: Mirela Rabulea 

Add mxsfb_atomic_helper_check to signal mode changed when bpp changed.
This will trigger the execution of disable/enable on
a modeset with different bpp than the current one.

Signed-off-by: Mirela Rabulea 
Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 45 ++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 23027a9..f95ba63 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -105,9 +106,51 @@ void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+/**
+ * mxsfb_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * On top of the drm imlementation drm_atomic_helper_check,
+ * check if the bpp is changed, if so, signal mode_changed,
+ * this will trigger disable/enable
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+static int mxsfb_atomic_helper_check(struct drm_device *dev,
+struct drm_atomic_state *state)
+{
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_state;
+   int i, ret;
+
+   ret = drm_atomic_helper_check(dev, state);
+   if (ret)
+   return ret;
+
+   for_each_new_crtc_in_state(state, crtc, new_state, i) {
+   struct drm_plane_state *primary_state;
+   int old_bpp = 0;
+   int new_bpp = 0;
+
+   if (!crtc->primary || !crtc->primary->old_fb)
+   continue;
+   primary_state =
+   drm_atomic_get_plane_state(state, crtc->primary);
+   if (!primary_state || !primary_state->fb)
+   continue;
+   old_bpp = crtc->primary->old_fb->format->depth;
+   new_bpp = primary_state->fb->format->depth;
+   if (old_bpp != new_bpp)
+   new_state->mode_changed = true;
+   }
+   return ret;
+}
+
 static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
.fb_create  = drm_gem_fb_create,
-   .atomic_check   = drm_atomic_helper_check,
+   .atomic_check   = mxsfb_atomic_helper_check,
.atomic_commit  = drm_atomic_helper_commit,
 };
 
-- 
2.7.4



[PATCH v4 02/14] drm/mxsfb: Read bus flags from bridge if present

2019-08-29 Thread Robert Chiras
From: Guido Günther 

The bridge might have special requirmentes on the input bus. This
is e.g. used by the imx-nwl bridge.

Signed-off-by: Guido Günther 
Reviewed-by: Stefan Agner 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index de09b93..b69ace8 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -209,7 +209,7 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 {
struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
+   u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -233,6 +233,9 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   if (mxsfb->bridge && mxsfb->bridge->timings)
+   bus_flags = mxsfb->bridge->timings->input_bus_flags;
+
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(mxsfb->clk) / 1000));
-- 
2.7.4



[PATCH v4 08/14] drm/mxsfb: Add max-memory-bandwidth property for MXSFB

2019-08-29 Thread Robert Chiras
Because of stability issues, we may want to limit the maximum bandwidth
required by the MXSFB (eLCDIF) driver.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 48 +++
 drivers/gpu/drm/mxsfb/mxsfb_drv.h |  2 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index f95ba63..d8686c7 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -158,6 +158,49 @@ static const struct drm_mode_config_helper_funcs 
mxsfb_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+enum drm_mode_status mxsfb_pipe_mode_valid(struct drm_crtc *crtc,
+  const struct drm_display_mode *mode)
+{
+   struct drm_simple_display_pipe *pipe =
+   container_of(crtc, struct drm_simple_display_pipe, crtc);
+   struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+   u32 bpp;
+   u64 bw;
+
+   if (!pipe->plane.state->fb)
+   bpp = 32;
+   else
+   bpp = pipe->plane.state->fb->format->depth;
+
+   bw = mode->crtc_clock * 1000;
+   bw = bw * mode->hdisplay * mode->vdisplay * (bpp / 8);
+   bw = div_u64(bw, mode->htotal * mode->vtotal);
+
+   if (mxsfb->max_bw && (bw > mxsfb->max_bw))
+   return MODE_BAD;
+
+   return MODE_OK;
+}
+
+static int mxsfb_pipe_check(struct drm_simple_display_pipe *pipe,
+   struct drm_plane_state *plane_state,
+   struct drm_crtc_state *crtc_state)
+{
+   struct drm_framebuffer *fb = plane_state->fb;
+   struct drm_framebuffer *old_fb = pipe->plane.state->fb;
+
+   /* force 'mode_changed' when fb pitches changed, since
+* the pitch related registers configuration of LCDIF
+* can not be done when LCDIF is running.
+*/
+   if (old_fb && likely(!crtc_state->mode_changed)) {
+   if (old_fb->pitches[0] != fb->pitches[0])
+   crtc_state->mode_changed = true;
+   }
+
+   return 0;
+}
+
 static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
  struct drm_crtc_state *crtc_state,
  struct drm_plane_state *plane_state)
@@ -244,6 +287,8 @@ static void mxsfb_pipe_disable_vblank(struct 
drm_simple_display_pipe *pipe)
 }
 
 static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
+   .mode_valid = mxsfb_pipe_mode_valid,
+   .check  = mxsfb_pipe_check,
.enable = mxsfb_pipe_enable,
.disable= mxsfb_pipe_disable,
.update = mxsfb_pipe_update,
@@ -283,6 +328,9 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
if (IS_ERR(mxsfb->clk_disp_axi))
mxsfb->clk_disp_axi = NULL;
 
+   of_property_read_u32(drm->dev->of_node, "max-memory-bandwidth",
+>max_bw);
+
ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 8fb65d3..a178173 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -32,6 +32,8 @@ struct mxsfb_drm_private {
struct drm_connector*connector;
struct drm_panel*panel;
struct drm_bridge   *bridge;
+
+   u32 max_bw;
 };
 
 int mxsfb_setup_crtc(struct drm_device *dev);
-- 
2.7.4



[PATCH v4 01/14] drm/mxsfb: Update mxsfb to support a bridge

2019-08-29 Thread Robert Chiras
Currently, the MXSFB DRM driver only supports a panel. But, its output
display signal can also be redirected to another encoder, like a DSI
controller. In this case, that DSI controller may act like a drm_bridge.
In order support this use-case too, this patch adds support for drm_bridge
in mxsfb.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 17 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 46 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  4 +++-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  | 26 +++--
 4 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1242156..de09b93 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -95,8 +95,11 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private 
*mxsfb)
 
reg = readl(mxsfb->base + LCDC_CTRL);
 
-   if (mxsfb->connector.display_info.num_bus_formats)
-   bus_format = mxsfb->connector.display_info.bus_formats[0];
+   if (mxsfb->connector->display_info.num_bus_formats)
+   bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
+bus_format);
 
reg &= ~CTRL_BUS_WIDTH_MASK;
switch (bus_format) {
@@ -204,8 +207,9 @@ static dma_addr_t mxsfb_get_fb_paddr(struct 
mxsfb_drm_private *mxsfb)
 
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
+   struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -229,6 +233,13 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
+m->crtc_clock,
+(int)(clk_get_rate(mxsfb->clk) / 1000));
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
+bus_flags);
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
+
writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
   TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
   mxsfb->base + mxsfb->devdata->transfer_count);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index e850633..497cf44 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -101,9 +101,25 @@ static void mxsfb_pipe_enable(struct 
drm_simple_display_pipe *pipe,
  struct drm_crtc_state *crtc_state,
  struct drm_plane_state *plane_state)
 {
+   struct drm_connector *connector;
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
struct drm_device *drm = pipe->plane.dev;
 
+   if (!mxsfb->connector) {
+   list_for_each_entry(connector,
+   >mode_config.connector_list,
+   head)
+   if (connector->encoder == >pipe.encoder) {
+   mxsfb->connector = connector;
+   break;
+   }
+   }
+
+   if (!mxsfb->connector) {
+   dev_warn(drm->dev, "No connector attached, using default\n");
+   mxsfb->connector = >panel_connector;
+   }
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -129,6 +145,9 @@ static void mxsfb_pipe_disable(struct 
drm_simple_display_pipe *pipe)
drm_crtc_send_vblank_event(crtc, event);
}
spin_unlock_irq(>event_lock);
+
+   if (mxsfb->connector != >panel_connector)
+   mxsfb->connector = NULL;
 }
 
 static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -226,16 +245,33 @@ static int mxsfb_load(struct drm_device *drm, unsigned 
long flags)
 
ret = drm_simple_display_pipe_init(drm, >pipe, _funcs,
mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
-   >connector);
+   mxsfb->connector);
if (ret < 0) {
dev_err(drm->dev, "Cannot setup simple display pipe\n");
goto err_vblank;
}
 
-   ret = drm_

Re: [EXT] [PATCH v3 2/2] drm/bridge: Add NWL MIPI DSI host controller support

2019-08-29 Thread Robert Chiras
Hi Guido,

One more thing for you to add in v4, see inline.

On Jo, 2019-08-22 at 12:44 +0200, Guido Günther wrote:
> This adds initial support for the NWL MIPI DSI Host controller found
> on
> i.MX8 SoCs.
> 
> It adds support for the i.MX8MQ but the same IP can be found on
> e.g. the i.MX8QXP.
> 
> It has been tested on the Librem 5 devkit using mxsfb.
> 
> Signed-off-by: Guido Günther 
> Co-developed-by: Robert Chiras 
> ---
>  drivers/gpu/drm/bridge/Kconfig   |   2 +
>  drivers/gpu/drm/bridge/Makefile  |   1 +
>  drivers/gpu/drm/bridge/nwl-dsi/Kconfig   |  16 +
>  drivers/gpu/drm/bridge/nwl-dsi/Makefile  |   4 +
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c | 501 
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.h |  65 +++
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.c | 700
> +++
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.h | 112 
>  8 files changed, 1401 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/Kconfig
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/Makefile
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.h
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.c
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.h
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig
> b/drivers/gpu/drm/bridge/Kconfig
> index 1cc9f502c1f2..7980b5c2156f 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -154,6 +154,8 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
> 
>  source "drivers/gpu/drm/bridge/adv7511/Kconfig"
> 
> +source "drivers/gpu/drm/bridge/nwl-dsi/Kconfig"
> +
>  source "drivers/gpu/drm/bridge/synopsys/Kconfig"
> 
>  endmenu
> diff --git a/drivers/gpu/drm/bridge/Makefile
> b/drivers/gpu/drm/bridge/Makefile
> index 4934fcf5a6f8..d9f6c0f77592 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -16,4 +16,5 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
>  obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
>  obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
>  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi/
>  obj-y += synopsys/
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> b/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> new file mode 100644
> index ..3b157a9f2229
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> @@ -0,0 +1,16 @@
> +config DRM_NWL_MIPI_DSI
> +   tristate "Support for Northwest Logic MIPI DSI Host
> controller"
> +   depends on DRM
> +   depends on COMMON_CLK
> +   depends on OF && HAS_IOMEM
> +   select DRM_KMS_HELPER
> +   select DRM_MIPI_DSI
> +   select DRM_PANEL_BRIDGE
> +   select GENERIC_PHY_MIPI_DPHY
> +   select MFD_SYSCON
> +   select MULTIPLEXER
> +   select REGMAP_MMIO
> +   help
> + This enables the Northwest Logic MIPI DSI Host controller
> as
> + for example found on NXP's i.MX8 Processors.
> +
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> b/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> new file mode 100644
> index ..804baf2f1916
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0
> +nwl-mipi-dsi-y := nwl-drv.o nwl-dsi.o
> +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-mipi-dsi.o
> +header-test-y += nwl-drv.h nwl-dsi.h
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> b/drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> new file mode 100644
> index ..e457438738c0
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> @@ -0,0 +1,501 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * i.MX8 NWL MIPI DSI host driver
> + *
> + * Copyright (C) 2017 NXP
> + * Copyright (C) 2019 Purism SPC
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "nwl-drv.h"
> +#include "nwl-dsi.h"
> +
> +#define DRV_NAME "nwl-dsi"
> +
> +/* Possible platform specific clocks */
> +#define NWL_DSI_CLK_CORE   "core"
> +
> +static const struct regmap_config nwl_dsi_regmap_config = {
> +   .reg_bits = 16,
> +   .val_bits = 32,
> +   .reg_stride = 4,
> +   .max_register = NWL_DSI_IRQ_MASK2,
> +   .name = DRV_NAME,
> +};
> +
> +struct nwl_d

Re: [EXT] [PATCH v3 0/2] drm: bridge: Add NWL MIPI DSI host controller support

2019-08-28 Thread Robert Chiras
Hi Guido,

I tested this on my setup and it works. My DSI panel is a little bit
different and it doesn't work with this as-is, but I added some
improvements on top of this, in order to be able to setup the clocks.
The changes I made can arrive on top of this as improvements, of
course, since it will allow this driver to dinamically set the
video_pll clock for any kind of mode.

So, for the whole patch-set, you can add:
Tested-by: Robert Chiras 
Signed-off-by: Robert Chiras 

Best regards,
Robert

On Jo, 2019-08-22 at 12:44 +0200, Guido Günther wrote:
> This adds initial support for the NWL MIPI DSI Host controller found
> on i.MX8
> SoCs.
> 
> It adds support for the i.MX8MQ but the same IP core can also be
> found on e.g.
> i.MX8QXP. I added the necessary hooks to support other imx8 variants
> but since
> I only have imx8mq boards to test I omitted the platform data for
> other SoCs.
> 
> The code is based on NXPs BSP so I added Robert Chiras as
> Co-authored-by. Robert, if this looks sane could you add your
> Signed-off-by:?
> 
> The most notable changes over the BSP driver are
>  - Calculate HS mode timing from phy_configure_opts_mipi_dphy
>  - Perform all clock setup via DT
>  - Merge nwl-imx and nwl drivers
>  - Add B0 silion revision quirk
>  - become a bridge driver to hook into mxsfb (from what I read[0]
> DCSS, which
>    also can drive the nwl on the imx8mq will likely not become part
> of
>    imx-display-subsystem so it makes sense to make it drive a bridge
> for dsi as
>    well).
>  - Use panel_bridge to attach the panel
>  - Use multiplex framework instead of accessing syscon directly
> 
> This has been tested on a Librem 5 devkit using mxsfb with Robert's
> patches[1]
> and the rocktech-jh057n00900 panel driver on next-20190821. The DCSS
> can later
> on also act as input source too.
> 
> Changes from v2:
> - Per review comments by Rob Herring
>   https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fl
> ists.freedesktop.org%2Farchives%2Fdri-devel%2F2019-
> August%2F230448.htmldata=02%7C01%7Crobert.chiras%40nxp.com%7C757
> 201f9aaa54653580e08d726edb290%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%
> 7C0%7C637020674654566414sdata=JdvAdCPGq2CTsW%2BgXgnAVltWMIfdCDQn
> dXSLYpnjEH8%3Dreserved=0
>   - bindings:
> - Simplify by restricting to fsl,imx8mq-nwl-dsi
> - document reset lines
> - add port@{0,1}
> - use a real compatible string for the panel
> - resets are required
> - Per review comments by Arnd Bergmann
>   https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fl
> ists.freedesktop.org%2Farchives%2Fdri-devel%2F2019-
> August%2F230868.htmldata=02%7C01%7Crobert.chiras%40nxp.com%7C757
> 201f9aaa54653580e08d726edb290%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%
> 7C0%7C637020674654566414sdata=LyJpZjQjMCe5zUdvK8CD8ETucLPxx621gW
> xtpAr8DM4%3Dreserved=0
>   - Don't access iomuxc_gpr regs directly. This allows us to drop the
> first patch in the series with the iomuxc_gpr field defines.
> - Per review comments by Laurent Pinchart
> - Fix wording in bindings
> - Add mux-controls to bindings
> - Don't print error message on dphy probe deferal
> 
> Changes from v1:
> - Per review comments by Sam Ravnborg
>   https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fl
> ists.freedesktop.org%2Farchives%2Fdri-devel%2F2019-
> July%2F228130.htmldata=02%7C01%7Crobert.chiras%40nxp.com%7C75720
> 1f9aaa54653580e08d726edb290%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C
> 0%7C637020674654566414sdata=AU2gzIwrbCdIBZenPWWYYX%2BgdX53zc2%2B
> SQhZbuN%2FWpU%3Dreserved=0
>   - Change binding docs to YAML
>   - build: Don't always visit imx-nwl/
>   - build: Add header-test-y
>   - Sort headers according to DRM convention
>   - Use drm_display_mode instead of videmode
> - Per review comments by Fabio Estevam
>   https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fl
> ists.freedesktop.org%2Farchives%2Fdri-devel%2F2019-
> July%2F228299.htmldata=02%7C01%7Crobert.chiras%40nxp.com%7C75720
> 1f9aaa54653580e08d726edb290%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C
> 0%7C637020674654566414sdata=6kpIZ6iNAQ13fMXU6sqENLwy%2FdIWL6ef8j
> gyas7I0CQ%3Dreserved=0
>   - Don't restrict build to ARCH_MXC
>   - Drop unused includes
>   - Drop unreachable code in imx_nwl_dsi_bridge_mode_fixup()
>   - Drop remaining calls of dev_err() and use DRM_DEV_ERR()
> consistently.
>   - Use devm_platform_ioremap_resource()
>   - Drop devm_free_irq() in probe() error path
>   - Use single line comments where sufficient
>   - Use  instead of defining USEC_PER_SEC
>   - Make input source select imx8 specific
>   - Drop  inclusion (after removal of
> get_unaligned_le32)
>   - Drop all EXPORT_SYMBOL_GPL(

Re: [PATCH v3 00/15] Improvements and fixes for mxsfb DRM driver

2019-08-28 Thread Robert Chiras
Hi Leonard,

On Lu, 2019-08-26 at 19:19 +, Leonard Crestez wrote:
> On 26.08.2019 17:35, Stefan Agner wrote:
> > 
> > On 2019-08-26 14:05, Guido Günther wrote:
> > > 
> > > Hi,
> > > On Wed, Aug 21, 2019 at 01:15:40PM +0300, Robert Chiras wrote:
> > > > 
> > > > This patch-set improves the use of eLCDIF block on iMX 8 SoCs
> > > > (like 8MQ, 8MM
> > > > and 8QXP). Following, are the new features added and fixes from
> > > > this
> > > > patch-set:
> > > I've applied this whole series on top of my NWL work and it looks
> > > good
> > > with a DSI panel. Applying the whole series also fixes an issue
> > > where
> > > after unblank the output was sometimes shifted about half a
> > > screen width
> > > to the right (which didn't happen with DCSS). So at least from
> > > the parts
> > > I could test:
> > > 
> > >    Tested-by: Guido Günther 
> > > 
> > > for the whole thing.
> > Thanks for testing! What SoC did you use? I think it would be good
> > to
> > also give this a try on i.MX 7 or i.MX 6ULL before merging.
> I did a quick test on imx6sx-sdb and it seems that [PATCH 07/15] 
> "drm/mxsfb: Fix the vblank events" causes a hang on boot, even
> without a 
> panel.
> 
> If I revert that particular patch it seems to be fine: the new pixel 
> formats seem to work in modetest (checked with sii,43wvf1g panel).
Thanks for feedback. I tested this and, indeed there are issues on 6SX
with this particular patch. It seems that there is a race-condition
caused by the vblank_on call in enable and IRQ routine. Since this is
not happening on any of i.MX8 SoC, I suspect the axi clock usage.
I think I will just remove this patch from the patch-set and handle
this case separately.
> 
> --
> Regards,
> Leonard

Regards,
Robert

Re: [EXT] [PATCH v3 2/2] drm/bridge: Add NWL MIPI DSI host controller support

2019-08-25 Thread Robert Chiras
Hi Guido,

On Jo, 2019-08-22 at 19:03 +0200, Guido Günther wrote:
> Hi Robert,
> thanks for your comments! Most of this make sense, i have some
> comments
> inline below (mostly since I only have access to the imx8mq reference
> manual but not to the any NWL IP docs):
> 
> On Thu, Aug 22, 2019 at 01:18:21PM +, Robert Chiras wrote:
> > 
> > Hi Guido,
> > 
> > I added my signed-off, plus some comments inline.
> > 
> > On Jo, 2019-08-22 at 12:44 +0200, Guido Günther wrote:
> > > 
> > > This adds initial support for the NWL MIPI DSI Host controller
> > > found
> > > on
> > > i.MX8 SoCs.
> > > 
> > > It adds support for the i.MX8MQ but the same IP can be found on
> > > e.g. the i.MX8QXP.
> > > 
> > > It has been tested on the Librem 5 devkit using mxsfb.
> > > 
> > > Signed-off-by: Guido Günther 
> > Signed-off-by: Robert Chiras 
> Thanks!
> 
> > 
> > > 
> > > Co-developed-by: Robert Chiras 
> > > ---
> > >  drivers/gpu/drm/bridge/Kconfig   |   2 +
> > >  drivers/gpu/drm/bridge/Makefile  |   1 +
> > >  drivers/gpu/drm/bridge/nwl-dsi/Kconfig   |  16 +
> > >  drivers/gpu/drm/bridge/nwl-dsi/Makefile  |   4 +
> > >  drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c | 501 
> > >  drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.h |  65 +++
> > >  drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.c | 700
> > > +++
> > >  drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.h | 112 
> > >  8 files changed, 1401 insertions(+)
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/Makefile
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.h
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.c
> > >  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.h
> > > 
> > > diff --git a/drivers/gpu/drm/bridge/Kconfig
> > > b/drivers/gpu/drm/bridge/Kconfig
> > > index 1cc9f502c1f2..7980b5c2156f 100644
> > > --- a/drivers/gpu/drm/bridge/Kconfig
> > > +++ b/drivers/gpu/drm/bridge/Kconfig
> > > @@ -154,6 +154,8 @@ source
> > > "drivers/gpu/drm/bridge/analogix/Kconfig"
> > > 
> > >  source "drivers/gpu/drm/bridge/adv7511/Kconfig"
> > > 
> > > +source "drivers/gpu/drm/bridge/nwl-dsi/Kconfig"
> > > +
> > >  source "drivers/gpu/drm/bridge/synopsys/Kconfig"
> > > 
> > >  endmenu
> > > diff --git a/drivers/gpu/drm/bridge/Makefile
> > > b/drivers/gpu/drm/bridge/Makefile
> > > index 4934fcf5a6f8..d9f6c0f77592 100644
> > > --- a/drivers/gpu/drm/bridge/Makefile
> > > +++ b/drivers/gpu/drm/bridge/Makefile
> > > @@ -16,4 +16,5 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
> > >  obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
> > >  obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
> > >  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> > > +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi/
> > >  obj-y += synopsys/
> > > diff --git a/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> > > b/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> > > new file mode 100644
> > > index ..3b157a9f2229
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> > > @@ -0,0 +1,16 @@
> > > +config DRM_NWL_MIPI_DSI
> > > +   tristate "Support for Northwest Logic MIPI DSI Host
> > > controller"
> > > +   depends on DRM
> > > +   depends on COMMON_CLK
> > > +   depends on OF && HAS_IOMEM
> > > +   select DRM_KMS_HELPER
> > > +   select DRM_MIPI_DSI
> > > +   select DRM_PANEL_BRIDGE
> > > +   select GENERIC_PHY_MIPI_DPHY
> > > +   select MFD_SYSCON
> > > +   select MULTIPLEXER
> > > +   select REGMAP_MMIO
> > > +   help
> > > + This enables the Northwest Logic MIPI DSI Host
> > > controller
> > > as
> > > + for example found on NXP's i.MX8 Processors.
> > > +
> > > diff --git a/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> > > b/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> > > new file mode 100644
> > > index ..804baf2f1916
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/bridge/nwl-dsi/Makef

Re: [EXT] [PATCH v3 2/2] drm/bridge: Add NWL MIPI DSI host controller support

2019-08-22 Thread Robert Chiras
Hi Guido,

I added my signed-off, plus some comments inline.

On Jo, 2019-08-22 at 12:44 +0200, Guido Günther wrote:
> This adds initial support for the NWL MIPI DSI Host controller found
> on
> i.MX8 SoCs.
> 
> It adds support for the i.MX8MQ but the same IP can be found on
> e.g. the i.MX8QXP.
> 
> It has been tested on the Librem 5 devkit using mxsfb.
> 
> Signed-off-by: Guido Günther 
Signed-off-by: Robert Chiras 
> Co-developed-by: Robert Chiras 
> ---
>  drivers/gpu/drm/bridge/Kconfig   |   2 +
>  drivers/gpu/drm/bridge/Makefile  |   1 +
>  drivers/gpu/drm/bridge/nwl-dsi/Kconfig   |  16 +
>  drivers/gpu/drm/bridge/nwl-dsi/Makefile  |   4 +
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c | 501 
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.h |  65 +++
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.c | 700
> +++
>  drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.h | 112 
>  8 files changed, 1401 insertions(+)
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/Kconfig
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/Makefile
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.h
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.c
>  create mode 100644 drivers/gpu/drm/bridge/nwl-dsi/nwl-dsi.h
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig
> b/drivers/gpu/drm/bridge/Kconfig
> index 1cc9f502c1f2..7980b5c2156f 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -154,6 +154,8 @@ source "drivers/gpu/drm/bridge/analogix/Kconfig"
> 
>  source "drivers/gpu/drm/bridge/adv7511/Kconfig"
> 
> +source "drivers/gpu/drm/bridge/nwl-dsi/Kconfig"
> +
>  source "drivers/gpu/drm/bridge/synopsys/Kconfig"
> 
>  endmenu
> diff --git a/drivers/gpu/drm/bridge/Makefile
> b/drivers/gpu/drm/bridge/Makefile
> index 4934fcf5a6f8..d9f6c0f77592 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -16,4 +16,5 @@ obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
>  obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
>  obj-$(CONFIG_DRM_TI_SN65DSI86) += ti-sn65dsi86.o
>  obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
> +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-dsi/
>  obj-y += synopsys/
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> b/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> new file mode 100644
> index ..3b157a9f2229
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi/Kconfig
> @@ -0,0 +1,16 @@
> +config DRM_NWL_MIPI_DSI
> +   tristate "Support for Northwest Logic MIPI DSI Host
> controller"
> +   depends on DRM
> +   depends on COMMON_CLK
> +   depends on OF && HAS_IOMEM
> +   select DRM_KMS_HELPER
> +   select DRM_MIPI_DSI
> +   select DRM_PANEL_BRIDGE
> +   select GENERIC_PHY_MIPI_DPHY
> +   select MFD_SYSCON
> +   select MULTIPLEXER
> +   select REGMAP_MMIO
> +   help
> + This enables the Northwest Logic MIPI DSI Host controller
> as
> + for example found on NXP's i.MX8 Processors.
> +
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> b/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> new file mode 100644
> index ..804baf2f1916
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0
> +nwl-mipi-dsi-y := nwl-drv.o nwl-dsi.o
> +obj-$(CONFIG_DRM_NWL_MIPI_DSI) += nwl-mipi-dsi.o
> +header-test-y += nwl-drv.h nwl-dsi.h
> diff --git a/drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> b/drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> new file mode 100644
> index ..e457438738c0
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/nwl-dsi/nwl-drv.c
> @@ -0,0 +1,501 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * i.MX8 NWL MIPI DSI host driver
> + *
> + * Copyright (C) 2017 NXP
> + * Copyright (C) 2019 Purism SPC
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "nwl-drv.h"
> +#include "nwl-dsi.h"
> +
> +#define DRV_NAME "nwl-dsi"
> +
> +/* Possible platform specific clocks */
> +#define NWL_DSI_CLK_CORE   "core"
> +
> +static const struct regmap_config nwl_dsi_regmap_config = {
> +   .reg_bits = 16,
> +   .val_bits = 32,
> +   .reg_stride = 4,
> +   .max_register = NWL_DSI_IRQ_MASK2,
> +   .name = DRV_NAME,

[PATCH v3 06/15] drm/mxsfb: Update mxsfb with additional pixel formats

2019-08-22 Thread Robert Chiras
Since version 4 of eLCDIF, there are some registers that can do
transformations on the input data, like re-arranging the pixel
components. By doing that, we can support more pixel formats.
This patch adds support for X/ABGR and RGBX/A. Although, the local alpha
is not supported by eLCDIF, the alpha pixel formats were added to the
supported pixel formats but it will be ignored. This was necessary since
there are systems (like Android) that requires such pixel formats.

Also, add support for the following pixel formats:
16 bpp: RG16 ,BG16, XR15, XB15, AR15, AB15

Set the bus format based on input from the user and panel
capabilities.
Save the bus format in crtc->mode.private_flags, so the bridge can
use it.

Signed-off-by: Robert Chiras 
Signed-off-by: Mirela Rabulea 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 147 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  30 ++--
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |   3 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  15 
 4 files changed, 163 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 5e44f57..1be29f5 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -43,14 +43,17 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private 
*mxsfb, u32 val)
 }
 
 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
-static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb, bool update)
 {
struct drm_crtc *crtc = >pipe.crtc;
struct drm_device *drm = crtc->dev;
const u32 format = crtc->primary->state->fb->format->format;
-   u32 ctrl, ctrl1;
+   u32 ctrl = 0, ctrl1 = 0;
+   bool bgr_format = true;
+   struct drm_format_name_buf format_name_buf;
 
-   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
+   if (!update)
+   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 
/*
 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
@@ -59,64 +62,158 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private 
*mxsfb)
 * to arbitrary value. This limitation should not pose an issue.
 */
 
-   /* CTRL1 contains IRQ config and status bits, preserve those. */
-   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
-   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   if (!update) {
+   /* CTRL1 contains IRQ config and status bits, preserve those. */
+   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
+   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   }
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Setting up %s mode\n",
+drm_get_format_name(format, _name_buf));
+
+   /* Do some clean-up that we might have from a previous mode */
+   ctrl &= ~CTRL_SHIFT_DIR(1);
+   ctrl &= ~CTRL_SHIFT_NUM(0x3f);
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR) |
+  CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
 
switch (format) {
-   case DRM_FORMAT_RGB565:
-   dev_dbg(drm->dev, "Setting up RGB565 mode\n");
+   case DRM_FORMAT_BGR565: /* BG16 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR) |
+   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_RGB565: /* RG16 */
+   ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl &= ~CTRL_DF16;
+   ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
+   break;
+   case DRM_FORMAT_XBGR1555: /* XB15 */
+   case DRM_FORMAT_ABGR1555: /* AB15 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR) |
+   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_XRGB1555: /* XR15 */
+   case DRM_FORMAT_ARGB1555: /* AR15 */
ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl |= CTRL_DF16;
ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
break;
-   case DRM_FORMAT_XRGB:
-   dev_dbg(drm->dev, "Setting up XRGB mode\n");
+   case DRM_FORMAT_RGBX: /* RX24 */
+   case DRM_FORMAT_RGBA: /* RA24 */
+   /* RGBX - > 

[PATCH v3 00/15] Improvements and fixes for mxsfb DRM driver

2019-08-21 Thread Robert Chiras
This patch-set improves the use of eLCDIF block on iMX 8 SoCs (like 8MQ, 8MM
and 8QXP). Following, are the new features added and fixes from this
patch-set:

1. Add support for drm_bridge
On 8MQ and 8MM, the LCDIF block is not directly connected to a parallel
display connector, where an LCD panel can be attached, but instead it is
connected to DSI controller. Since this DSI stands between the display
controller (eLCDIF) and the physical connector, the DSI can be implemented
as a DRM bridge. So, in order to be able to connect the mxsfb driver to
the DSI driver, the support for a drm_bridge was needed in mxsfb DRM
driver (the actual driver for the eLCDIF block).

2. Add support for additional pixel formats
Some of the pixel formats needed by Android were not implemented in this
driver, but they were actually supported. So, add support for them.

3. Add support for horizontal stride
Having support for horizontal stride allows the use of eLCDIF with a GPU
(for example) that can only output resolution sizes multiple of a power of
8. For example, 1080 is not a power of 16, so in order to support 1920x1080
output from GPUs that can produce linear buffers only in sizes multiple to 16,
this feature is needed.

3. Few minor features and bug-fixing
The addition of max-res DT property was actually needed in order to limit
the bandwidth usage of the eLCDIF block. This is need on systems where
multiple display controllers are presend and the memory bandwidth is not
enough to handle all of them at maximum capacity (like it is the case on
8MQ, where there are two display controllers: DCSS and eLCDIF).
The rest of the patches are bug-fixes.

v3:
- Removed the max-res property patches and added support for
  max-memory-bandwidth property, as it is also implemented in other drivers
- Removed unnecessary drm_vblank_off in probe

v2:
- Collected Tested-by from Guido
- Split the first patch, which added more than one feature into relevant
  patches, explaining each feature added
- Also split the second patch into more patches, to differentiate between
  the feature itself (additional pixel formats support) and the cleanup
  of the register definitions for a better representation (guido)
- Included a patch submitted by Guido, while he was testing my patch-set

Guido Günther (1):
  drm/mxsfb: Read bus flags from bridge if present

Mirela Rabulea (1):
  drm/mxsfb: Signal mode changed when bpp changed

Robert Chiras (13):
  drm/mxsfb: Update mxsfb to support a bridge
  drm/mxsfb: Add defines for the rest of registers
  drm/mxsfb: Reset vital registers for a proper initialization
  drm/mxsfb: Update register definitions using bit manipulation defines
  drm/mxsfb: Update mxsfb with additional pixel formats
  drm/mxsfb: Fix the vblank events
  drm/mxsfb: Add max-memory-bandwidth property for MXSFB
  dt-bindings: display: Add max-memory-bandwidth property for mxsfb
  drm/mxsfb: Update mxsfb to support LCD reset
  drm/mxsfb: Improve the axi clock usage
  drm/mxsfb: Clear OUTSTANDING_REQS bits
  drm/mxsfb: Add support for horizontal stride
  drm/mxsfb: Add support for live pixel format change

 .../devicetree/bindings/display/mxsfb.txt  |   5 +
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 287 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 203 +--
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  12 +-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  |  26 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 193 +-
 6 files changed, 589 insertions(+), 137 deletions(-)

-- 
2.7.4



[PATCH v3 04/15] drm/mxsfb: Reset vital registers for a proper initialization

2019-08-21 Thread Robert Chiras
Some of the registers, like LCDC_CTRL, CTRL2_OUTSTANDING_REQS and
CTRL1_RECOVERY_ON_UNDERFLOW needs to be properly cleared/initialized
for a better start and stop routine.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index b69ace8..5e44f57 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -127,6 +127,10 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_OUTSTANDING_REQS(REQ_16),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
 
@@ -136,12 +140,19 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
writel(reg, mxsfb->base + LCDC_VDCTRL4);
 
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+   writel(CTRL1_RECOVERY_ON_UNDERFLOW, mxsfb->base + LCDC_CTRL1 + REG_SET);
 }
 
 static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
/*
 * Even if we disable the controller here, it will still continue
 * until its FIFOs are running out of data
@@ -295,6 +306,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
dma_addr_t paddr;
 
mxsfb_enable_axi_clk(mxsfb);
+   writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
/* Write cur_buf as well to avoid an initial corrupt frame */
-- 
2.7.4



[PATCH v3 15/15] drm/mxsfb: Add support for live pixel format change

2019-08-21 Thread Robert Chiras
This IP requires full stop and re-start when changing display timings,
but we can change the pixel format while running.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 317575e..5607fc0 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -494,6 +494,7 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
struct drm_crtc *crtc = >crtc;
struct drm_plane_state *new_state = pipe->plane.state;
struct drm_framebuffer *fb = pipe->plane.state->fb;
+   struct drm_framebuffer *old_fb = state->fb;
struct drm_pending_vblank_event *event;
u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
@@ -510,7 +511,7 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   if (!fb)
+   if (!fb || !old_fb)
return;
 
fb_addr = mxsfb_get_fb_paddr(mxsfb);
@@ -533,4 +534,17 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
src_w = new_state->src_w >> 16;
mxsfb_set_fb_hcrop(mxsfb, src_w, stride);
}
+
+   if (old_fb->format->format != fb->format->format) {
+   struct drm_format_name_buf old_fmt_buf;
+   struct drm_format_name_buf new_fmt_buf;
+
+   DRM_DEV_DEBUG_DRIVER(crtc->dev->dev,
+   "Switching pixel format: %s -> %s\n",
+   drm_get_format_name(old_fb->format->format,
+   _fmt_buf),
+   drm_get_format_name(fb->format->format,
+   _fmt_buf));
+   mxsfb_set_pixel_fmt(mxsfb, true);
+   }
 }
-- 
2.7.4



[PATCH v3 05/15] drm/mxsfb: Update register definitions using bit manipulation defines

2019-08-21 Thread Robert Chiras
Use BIT(x) and GEN_MASK(h, l) for better representation the inside of
various registers.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 151 ++---
 1 file changed, 89 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 71426aa..9fcb1db 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -40,66 +40,93 @@
 #define LCDC_AS_BUF0x220
 #define LCDC_AS_NEXT_BUF   0x230
 
-#define CTRL_SFTRST(1 << 31)
-#define CTRL_CLKGATE   (1 << 30)
-#define CTRL_BYPASS_COUNT  (1 << 19)
-#define CTRL_VSYNC_MODE(1 << 18)
-#define CTRL_DOTCLK_MODE   (1 << 17)
-#define CTRL_DATA_SELECT   (1 << 16)
-#define CTRL_SET_BUS_WIDTH(x)  (((x) & 0x3) << 10)
-#define CTRL_GET_BUS_WIDTH(x)  (((x) >> 10) & 0x3)
-#define CTRL_BUS_WIDTH_MASK(0x3 << 10)
-#define CTRL_SET_WORD_LENGTH(x)(((x) & 0x3) << 8)
-#define CTRL_GET_WORD_LENGTH(x)(((x) >> 8) & 0x3)
-#define CTRL_MASTER(1 << 5)
-#define CTRL_DF16  (1 << 3)
-#define CTRL_DF18  (1 << 2)
-#define CTRL_DF24  (1 << 1)
-#define CTRL_RUN   (1 << 0)
-
-#define CTRL1_RECOVERY_ON_UNDERFLOW(1 << 24)
-#define CTRL1_FIFO_CLEAR   (1 << 21)
-#define CTRL1_SET_BYTE_PACKAGING(x)(((x) & 0xf) << 16)
-#define CTRL1_GET_BYTE_PACKAGING(x)(((x) >> 16) & 0xf)
-#define CTRL1_CUR_FRAME_DONE_IRQ_EN(1 << 13)
-#define CTRL1_CUR_FRAME_DONE_IRQ   (1 << 9)
-
-#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
-
-#define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
-#define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
-#define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0x)
-#define TRANSFER_COUNT_GET_HCOUNT(x)   ((x) & 0x)
-
-#define VDCTRL0_ENABLE_PRESENT (1 << 28)
-#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
-#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
-#define VDCTRL0_ENABLE_ACT_HIGH(1 << 24)
-#define VDCTRL0_VSYNC_PERIOD_UNIT  (1 << 21)
-#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
-#define VDCTRL0_HALF_LINE  (1 << 19)
-#define VDCTRL0_HALF_LINE_MODE (1 << 18)
-#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3)
-#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3)
-
-#define VDCTRL2_SET_HSYNC_PERIOD(x)((x) & 0x3)
-#define VDCTRL2_GET_HSYNC_PERIOD(x)((x) & 0x3)
-
-#define VDCTRL3_MUX_SYNC_SIGNALS   (1 << 29)
-#define VDCTRL3_VSYNC_ONLY (1 << 28)
-#define SET_HOR_WAIT_CNT(x)(((x) & 0xfff) << 16)
-#define GET_HOR_WAIT_CNT(x)(((x) >> 16) & 0xfff)
-#define SET_VERT_WAIT_CNT(x)   ((x) & 0x)
-#define GET_VERT_WAIT_CNT(x)   ((x) & 0x)
-
-#define VDCTRL4_SET_DOTCLK_DLY(x)  (((x) & 0x7) << 29) /* v4 only */
-#define VDCTRL4_GET_DOTCLK_DLY(x)  (((x) >> 29) & 0x7) /* v4 only */
-#define VDCTRL4_SYNC_SIGNALS_ON(1 << 18)
-#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3)
-
-#define DEBUG0_HSYNC   (1 < 26)
-#define DEBUG0_VSYNC   (1 < 25)
+/* reg bit manipulation */
+#define REG_PUT(x, h, l) (((x) << (l)) & GENMASK(h, l))
+#define REG_GET(x, h, l) (((x) & GENMASK(h, l)) >> (l))
+
+#define CTRL_SFTRSTBIT(31)
+#define CTRL_CLKGATE   BIT(30)
+#define CTRL_SHIFT_DIR(x)  REG_PUT((x), 26, 26)
+#define CTRL_SHIFT_NUM(x)  REG_PUT((x), 25, 21)
+#define CTRL_BYPASS_COUNT  BIT(19)
+#define CTRL_VSYNC_MODEBIT(18)
+#define CTRL_DOTCLK_MODE   BIT(17)
+#define CTRL_DATA_SELECT   BIT(16)
+#define CTRL_INPUT_SWIZZLE(x)  REG_PUT((x), 15, 14)
+#define CTRL_CSC_SWIZZLE(x)REG_PUT((x), 13, 12)
+#define CTRL_SET_BUS_WIDTH(x)  REG_PUT((x), 11, 10)
+#define CTRL_GET_BUS_WIDTH(x)  REG_GET((x), 11, 10)
+#define CTRL_BUS_WIDTH_MASKREG_PUT((0x3), 11, 10)
+#define CTRL_SET_WORD_LENGTH(x)REG_PUT((x), 9, 8)
+#define CTRL_GET_WORD_LENGTH(x)REG_GET((x), 9, 8)
+#define CTRL_MASTERBIT(5)
+#define CTRL_DF16  BIT(3)
+#define CTRL_DF18  BIT(2)
+#define CTRL_DF24  BIT(1)
+#define CTRL

[PATCH v3 02/15] drm/mxsfb: Read bus flags from bridge if present

2019-08-21 Thread Robert Chiras
From: Guido Günther 

The bridge might have special requirmentes on the input bus. This
is e.g. used by the imx-nwl bridge.

Signed-off-by: Guido Günther 
Reviewed-by: Stefan Agner 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index de09b93..b69ace8 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -209,7 +209,7 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 {
struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
+   u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -233,6 +233,9 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   if (mxsfb->bridge && mxsfb->bridge->timings)
+   bus_flags = mxsfb->bridge->timings->input_bus_flags;
+
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(mxsfb->clk) / 1000));
-- 
2.7.4



[PATCH v3 01/15] drm/mxsfb: Update mxsfb to support a bridge

2019-08-21 Thread Robert Chiras
Currently, the MXSFB DRM driver only supports a panel. But, its output
display signal can also be redirected to another encoder, like a DSI
controller. In this case, that DSI controller may act like a drm_bridge.
In order support this use-case too, this patch adds support for drm_bridge
in mxsfb.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 17 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 46 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  4 +++-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  | 26 +++--
 4 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1242156..de09b93 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -95,8 +95,11 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private 
*mxsfb)
 
reg = readl(mxsfb->base + LCDC_CTRL);
 
-   if (mxsfb->connector.display_info.num_bus_formats)
-   bus_format = mxsfb->connector.display_info.bus_formats[0];
+   if (mxsfb->connector->display_info.num_bus_formats)
+   bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
+bus_format);
 
reg &= ~CTRL_BUS_WIDTH_MASK;
switch (bus_format) {
@@ -204,8 +207,9 @@ static dma_addr_t mxsfb_get_fb_paddr(struct 
mxsfb_drm_private *mxsfb)
 
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
+   struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -229,6 +233,13 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
+m->crtc_clock,
+(int)(clk_get_rate(mxsfb->clk) / 1000));
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
+bus_flags);
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
+
writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
   TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
   mxsfb->base + mxsfb->devdata->transfer_count);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 878ef68..9dc69b7 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -101,9 +101,25 @@ static void mxsfb_pipe_enable(struct 
drm_simple_display_pipe *pipe,
  struct drm_crtc_state *crtc_state,
  struct drm_plane_state *plane_state)
 {
+   struct drm_connector *connector;
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
struct drm_device *drm = pipe->plane.dev;
 
+   if (!mxsfb->connector) {
+   list_for_each_entry(connector,
+   >mode_config.connector_list,
+   head)
+   if (connector->encoder == >pipe.encoder) {
+   mxsfb->connector = connector;
+   break;
+   }
+   }
+
+   if (!mxsfb->connector) {
+   dev_warn(drm->dev, "No connector attached, using default\n");
+   mxsfb->connector = >panel_connector;
+   }
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -129,6 +145,9 @@ static void mxsfb_pipe_disable(struct 
drm_simple_display_pipe *pipe)
drm_crtc_send_vblank_event(crtc, event);
}
spin_unlock_irq(>event_lock);
+
+   if (mxsfb->connector != >panel_connector)
+   mxsfb->connector = NULL;
 }
 
 static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -226,16 +245,33 @@ static int mxsfb_load(struct drm_device *drm, unsigned 
long flags)
 
ret = drm_simple_display_pipe_init(drm, >pipe, _funcs,
mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
-   >connector);
+   mxsfb->connector);
if (ret < 0) {
dev_err(drm->dev, "Cannot setup simple display pipe\n");
goto err_vblank;
}
 
-   ret = drm_

[PATCH v3 13/15] drm/mxsfb: Clear OUTSTANDING_REQS bits

2019-08-21 Thread Robert Chiras
Bit 21 can alter the CTRL2_OUTSTANDING_REQS value right after the eLCDIF
is enabled, since it comes up with default value of 1 (this behaviour
has been seen on some imx8 platforms).
In order to fix this, clear CTRL2_OUTSTANDING_REQS bits before setting
its value.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index e727f5e..a12f53d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -225,6 +225,13 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk);
 
if (mxsfb->devdata->ipversion >= 4) {
+   /*
+* On some platforms, bit 21 is defaulted to 1, which may alter
+* the below setting. So, to make sure we have the right setting
+* clear all the bits for CTRL2_OUTSTANDING_REQS.
+*/
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
/* Assert LCD Reset bit */
-- 
2.7.4



[PATCH v3 10/15] dt-bindings: display: Add max-memory-bandwidth property for mxsfb

2019-08-21 Thread Robert Chiras
Add new optional property 'max-memory-bandwidth', to limit the maximum
bandwidth used by the MXSFB_DRM driver.

Signed-off-by: Robert Chiras 
---
 Documentation/devicetree/bindings/display/mxsfb.txt | 5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt 
b/Documentation/devicetree/bindings/display/mxsfb.txt
index 472e1ea..c8dca50 100644
--- a/Documentation/devicetree/bindings/display/mxsfb.txt
+++ b/Documentation/devicetree/bindings/display/mxsfb.txt
@@ -14,6 +14,11 @@ Required properties:
 - "pix" for the LCDIF block clock
 - (MX6SX-only) "axi", "disp_axi" for the bus interface clock
 
+Optional properties:
+- max-memory-bandwidth: maximum bandwidth in bytes per second that the
+   controller can handle; if not present, the memory
+   interface is fast enough to handle all possible video modes
+
 Required sub-nodes:
   - port: The connection to an encoder chip.
 
-- 
2.7.4



[PATCH v3 08/15] drm/mxsfb: Signal mode changed when bpp changed

2019-08-21 Thread Robert Chiras
From: Mirela Rabulea 

Add mxsfb_atomic_helper_check to signal mode changed when bpp changed.
This will trigger the execution of disable/enable on
a modeset with different bpp than the current one.

Signed-off-by: Mirela Rabulea 
Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 45 ++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 78a2382..f51c8a3 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -108,9 +109,51 @@ void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+/**
+ * mxsfb_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * On top of the drm imlementation drm_atomic_helper_check,
+ * check if the bpp is changed, if so, signal mode_changed,
+ * this will trigger disable/enable
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+static int mxsfb_atomic_helper_check(struct drm_device *dev,
+struct drm_atomic_state *state)
+{
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_state;
+   int i, ret;
+
+   ret = drm_atomic_helper_check(dev, state);
+   if (ret)
+   return ret;
+
+   for_each_new_crtc_in_state(state, crtc, new_state, i) {
+   struct drm_plane_state *primary_state;
+   int old_bpp = 0;
+   int new_bpp = 0;
+
+   if (!crtc->primary || !crtc->primary->old_fb)
+   continue;
+   primary_state =
+   drm_atomic_get_plane_state(state, crtc->primary);
+   if (!primary_state || !primary_state->fb)
+   continue;
+   old_bpp = crtc->primary->old_fb->format->depth;
+   new_bpp = primary_state->fb->format->depth;
+   if (old_bpp != new_bpp)
+   new_state->mode_changed = true;
+   }
+   return ret;
+}
+
 static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
.fb_create  = drm_gem_fb_create,
-   .atomic_check   = drm_atomic_helper_check,
+   .atomic_check   = mxsfb_atomic_helper_check,
.atomic_commit  = drm_atomic_helper_commit,
 };
 
-- 
2.7.4



[PATCH v3 09/15] drm/mxsfb: Add max-memory-bandwidth property for MXSFB

2019-08-21 Thread Robert Chiras
Because of stability issues, we may want to limit the maximum bandwidth
required by the MXSFB (eLCDIF) driver.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 48 +++
 drivers/gpu/drm/mxsfb/mxsfb_drv.h |  2 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index f51c8a3..deb5e2b 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -161,6 +161,49 @@ static const struct drm_mode_config_helper_funcs 
mxsfb_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 };
 
+enum drm_mode_status mxsfb_pipe_mode_valid(struct drm_crtc *crtc,
+  const struct drm_display_mode *mode)
+{
+   struct drm_simple_display_pipe *pipe =
+   container_of(crtc, struct drm_simple_display_pipe, crtc);
+   struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+   u32 bpp;
+   u64 bw;
+
+   if (!pipe->plane.state->fb)
+   bpp = 32;
+   else
+   bpp = pipe->plane.state->fb->format->depth;
+
+   bw = mode->crtc_clock * 1000;
+   bw = bw * mode->hdisplay * mode->vdisplay * (bpp / 8);
+   bw = div_u64(bw, mode->htotal * mode->vtotal);
+
+   if (mxsfb->max_bw && (bw > mxsfb->max_bw))
+   return MODE_BAD;
+
+   return MODE_OK;
+}
+
+static int mxsfb_pipe_check(struct drm_simple_display_pipe *pipe,
+   struct drm_plane_state *plane_state,
+   struct drm_crtc_state *crtc_state)
+{
+   struct drm_framebuffer *fb = plane_state->fb;
+   struct drm_framebuffer *old_fb = pipe->plane.state->fb;
+
+   /* force 'mode_changed' when fb pitches changed, since
+* the pitch related registers configuration of LCDIF
+* can not be done when LCDIF is running.
+*/
+   if (old_fb && likely(!crtc_state->mode_changed)) {
+   if (old_fb->pitches[0] != fb->pitches[0])
+   crtc_state->mode_changed = true;
+   }
+
+   return 0;
+}
+
 static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
  struct drm_crtc_state *crtc_state,
  struct drm_plane_state *plane_state)
@@ -251,6 +294,8 @@ static void mxsfb_pipe_disable_vblank(struct 
drm_simple_display_pipe *pipe)
 }
 
 static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
+   .mode_valid = mxsfb_pipe_mode_valid,
+   .check  = mxsfb_pipe_check,
.enable = mxsfb_pipe_enable,
.disable= mxsfb_pipe_disable,
.update = mxsfb_pipe_update,
@@ -290,6 +335,9 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
if (IS_ERR(mxsfb->clk_disp_axi))
mxsfb->clk_disp_axi = NULL;
 
+   of_property_read_u32(drm->dev->of_node, "max-memory-bandwidth",
+>max_bw);
+
ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
if (ret)
return ret;
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 8fb65d3..a178173 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -32,6 +32,8 @@ struct mxsfb_drm_private {
struct drm_connector*connector;
struct drm_panel*panel;
struct drm_bridge   *bridge;
+
+   u32 max_bw;
 };
 
 int mxsfb_setup_crtc(struct drm_device *dev);
-- 
2.7.4



[PATCH v3 14/15] drm/mxsfb: Add support for horizontal stride

2019-08-21 Thread Robert Chiras
Besides the eLCDIF block, there is another IP block, used in the past
for EPDC panels. Since the iMX.8mq doesn't have an EPDC connector, this
block is not documented, but we can use it to do additional operations
on the frame buffer.
In this case, we can use the pigeon registers from this IP block in
order to do horizontal crop on the frame buffer processed by the eLCDIF
block.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 79 --
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  1 +
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 16 
 3 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index a12f53d..317575e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -15,6 +15,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -435,13 +436,66 @@ void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+void mxsfb_set_fb_hcrop(struct mxsfb_drm_private *mxsfb, u32 src_w, u32 fb_w)
+{
+   u32 mask_cnt, htotal, hcount;
+   u32 vdctrl2, vdctrl3, vdctrl4, transfer_count;
+   u32 pigeon_12_0, pigeon_12_1, pigeon_12_2;
+
+   if (src_w == fb_w) {
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   return;
+   }
+
+   transfer_count = readl(mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+   hcount = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+
+   transfer_count &= ~TRANSFER_COUNT_SET_HCOUNT(0x);
+   transfer_count |= TRANSFER_COUNT_SET_HCOUNT(fb_w);
+   writel(transfer_count, mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+
+   vdctrl2 = readl(mxsfb->base + LCDC_VDCTRL2);
+   htotal  = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2);
+   htotal  += fb_w - hcount;
+   vdctrl2 &= ~VDCTRL2_SET_HSYNC_PERIOD(0x3);
+   vdctrl2 |= VDCTRL2_SET_HSYNC_PERIOD(htotal);
+   writel(vdctrl2, mxsfb->base + LCDC_VDCTRL2);
+
+   vdctrl4 = readl(mxsfb->base + LCDC_VDCTRL4);
+   vdctrl4 &= ~SET_DOTCLK_H_VALID_DATA_CNT(0x3);
+   vdctrl4 |= SET_DOTCLK_H_VALID_DATA_CNT(fb_w);
+   writel(vdctrl4, mxsfb->base + LCDC_VDCTRL4);
+
+   /* configure related pigeon registers */
+   vdctrl3  = readl(mxsfb->base + LCDC_VDCTRL3);
+   mask_cnt = GET_HOR_WAIT_CNT(vdctrl3) - 5;
+
+   pigeon_12_0 = PIGEON_12_0_SET_STATE_MASK(0x24)  |
+ PIGEON_12_0_SET_MASK_CNT(mask_cnt)|
+ PIGEON_12_0_SET_MASK_CNT_SEL(0x6) |
+ PIGEON_12_0_POL_ACTIVE_LOW|
+ PIGEON_12_0_EN;
+   writel(pigeon_12_0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+
+   pigeon_12_1 = PIGEON_12_1_SET_CLR_CNT(src_w) |
+ PIGEON_12_1_SET_SET_CNT(0x0);
+   writel(pigeon_12_1, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   pigeon_12_2 = 0x0;
+   writel(pigeon_12_2, mxsfb->base + HW_EPDC_PIGEON_12_2);
+}
+
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
   struct drm_plane_state *state)
 {
struct drm_simple_display_pipe *pipe = >pipe;
struct drm_crtc *crtc = >crtc;
+   struct drm_plane_state *new_state = pipe->plane.state;
+   struct drm_framebuffer *fb = pipe->plane.state->fb;
struct drm_pending_vblank_event *event;
-   dma_addr_t paddr;
+   u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
spin_lock_irq(>dev->event_lock);
event = crtc->state->event;
@@ -456,10 +510,27 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   paddr = mxsfb_get_fb_paddr(mxsfb);
-   if (paddr) {
+   if (!fb)
+   return;
+
+   fb_addr = mxsfb_get_fb_paddr(mxsfb);
+   if (mxsfb->devdata->ipversion >= 4) {
+   cpp = fb->format->cpp[0];
+   src_off = (new_state->src_y >> 16) * fb->pitches[0] +
+ (new_state->src_x >> 16) * cpp;
+   fb_addr += fb->offsets[0] + src_off;
+   }
+
+   if (fb_addr) {
clk_prepare_enable(mxsfb->clk_axi);
-   writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
+   writel(fb_addr, mxsfb->base + mxsfb->devdata->next_buf);
clk_disable_unprepare(mxsfb->clk_axi);
}
+
+   if (mxsfb->devdata->ipversion >= 4 &&
+   unlikely(drm_atomic_crtc_needs_modeset(new_state->crtc->state))) {
+   stride = DIV_ROUND_UP(fb->pitches[0], cpp);
+   src_w = new_state->src_w >> 16;
+   mxsfb_set_fb_hcrop(mxsfb, src_w, stride)

[PATCH v3 03/15] drm/mxsfb: Add defines for the rest of registers

2019-08-21 Thread Robert Chiras
Some of the existing registers in this controller are not defined, but
also not used. Add them to the register definitions, so that they can be
easily used in future improvements or fixes.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 932d7ea..71426aa 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -14,19 +14,31 @@
 
 #define LCDC_CTRL  0x00
 #define LCDC_CTRL1 0x10
+#define LCDC_V4_CTRL2  0x20
 #define LCDC_V3_TRANSFER_COUNT 0x20
 #define LCDC_V4_TRANSFER_COUNT 0x30
 #define LCDC_V4_CUR_BUF0x40
 #define LCDC_V4_NEXT_BUF   0x50
 #define LCDC_V3_CUR_BUF0x30
 #define LCDC_V3_NEXT_BUF   0x40
+#define LCDC_TIMING0x60
 #define LCDC_VDCTRL0   0x70
 #define LCDC_VDCTRL1   0x80
 #define LCDC_VDCTRL2   0x90
 #define LCDC_VDCTRL3   0xa0
 #define LCDC_VDCTRL4   0xb0
+#define LCDC_DVICTRL0  0xc0
+#define LCDC_DVICTRL1  0xd0
+#define LCDC_DVICTRL2  0xe0
+#define LCDC_DVICTRL3  0xf0
+#define LCDC_DVICTRL4  0x100
+#define LCDC_V4_DATA   0x180
+#define LCDC_V3_DATA   0x1b0
 #define LCDC_V4_DEBUG0 0x1d0
 #define LCDC_V3_DEBUG0 0x1f0
+#define LCDC_AS_CTRL   0x210
+#define LCDC_AS_BUF0x220
+#define LCDC_AS_NEXT_BUF   0x230
 
 #define CTRL_SFTRST(1 << 31)
 #define CTRL_CLKGATE   (1 << 30)
@@ -45,12 +57,15 @@
 #define CTRL_DF24  (1 << 1)
 #define CTRL_RUN   (1 << 0)
 
+#define CTRL1_RECOVERY_ON_UNDERFLOW(1 << 24)
 #define CTRL1_FIFO_CLEAR   (1 << 21)
 #define CTRL1_SET_BYTE_PACKAGING(x)(((x) & 0xf) << 16)
 #define CTRL1_GET_BYTE_PACKAGING(x)(((x) >> 16) & 0xf)
 #define CTRL1_CUR_FRAME_DONE_IRQ_EN(1 << 13)
 #define CTRL1_CUR_FRAME_DONE_IRQ   (1 << 9)
 
+#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0x)
-- 
2.7.4



[PATCH v3 12/15] drm/mxsfb: Improve the axi clock usage

2019-08-21 Thread Robert Chiras
Currently, the enable of the axi clock return status is ignored, causing
issues when the enable fails then we try to disable it. Therefore, it is
better to check the return status and disable it only when enable
succeeded.
Also, remove the helper functions around clk_axi, since we can directly
use the clk API function for enable/disable the clock. Those functions
are already checking for NULL clk and returning 0 if that's the case.

Signed-off-by: Robert Chiras 
Acked-by: Leonard Crestez 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c |  8 
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 32 +---
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  3 ---
 3 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index a4ba368..e727f5e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -408,7 +408,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 {
dma_addr_t paddr;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
@@ -425,7 +425,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
 {
mxsfb_disable_controller(mxsfb);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
@@ -451,8 +451,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
 
paddr = mxsfb_get_fb_paddr(mxsfb);
if (paddr) {
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
}
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index deb5e2b..dd5809b 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -97,18 +97,6 @@ drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe 
*pipe)
return container_of(pipe, struct mxsfb_drm_private, pipe);
 }
 
-void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_prepare_enable(mxsfb->clk_axi);
-}
-
-void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_disable_unprepare(mxsfb->clk_axi);
-}
-
 /**
  * mxsfb_atomic_helper_check - validate state object
  * @dev: DRM device
@@ -272,25 +260,31 @@ static void mxsfb_pipe_update(struct 
drm_simple_display_pipe *pipe,
 static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+   int ret = 0;
+
+   ret = clk_prepare_enable(mxsfb->clk_axi);
+   if (ret)
+   return ret;
 
/* Clear and enable VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
-   return 0;
+   return ret;
 }
 
 static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
 
+   if (clk_prepare_enable(mxsfb->clk_axi))
+   return;
+
/* Disable and clear VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
@@ -451,7 +445,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
struct mxsfb_drm_private *mxsfb = drm->dev_private;
u32 reg;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
 
reg = readl(mxsfb->base + LCDC_CTRL1);
 
@@ -460,7 +454,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
return IRQ_HANDLED;
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index a178173..54c0644 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -39,9 +39,6 @@ struct mxsfb_drm_private {
 int mxsfb_setup_crtc(struct drm_device *dev);
 int mxsfb

[PATCH v3 11/15] drm/mxsfb: Update mxsfb to support LCD reset

2019-08-21 Thread Robert Chiras
The eLCDIF controller has control pin for the external LCD reset pin.
Add support for it and assert this pin in enable and de-assert it in
disable.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 14 ++
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  2 ++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1be29f5..a4ba368 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -224,9 +224,12 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
-   if (mxsfb->devdata->ipversion >= 4)
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   }
 
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -244,11 +247,14 @@ static void mxsfb_disable_controller(struct 
mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
-   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(0x7),
   mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
-
-   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+   /* De-assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+   }
 
/*
 * Even if we disable the controller here, it will still continue
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index dc4daa0..0f63ba1 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -108,6 +108,8 @@
 #define CTRL2_LINE_PATTERN_BGR 5
 #define CTRL2_LINE_PATTERN_CLR 7
 
+#define CTRL2_LCD_RESETBIT(0)
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   REG_PUT((x), 31, 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   REG_GET((x), 31, 16)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   REG_PUT((x), 15, 0)
-- 
2.7.4



[PATCH v3 07/15] drm/mxsfb: Fix the vblank events

2019-08-21 Thread Robert Chiras
Currently, the vblank support is not correctly implemented in MXSFB_DRM
driver. The call to drm_vblank_init is made with mode_config.num_crtc
which at that time is 0. Because of this, vblank is not activated, so
there won't be any vblank event submitted.
For example, when running modetest with the '-v' parameter will result
in an astronomical refresh rate (1+ Hz), because of that.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 2743975..78a2382 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -38,6 +38,9 @@
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
 
+/* The eLCDIF max possible CRTCs */
+#define MAX_CRTCS 1
+
 enum mxsfb_devtype {
MXSFB_V3,
MXSFB_V4,
@@ -138,6 +141,8 @@ static void mxsfb_pipe_enable(struct 
drm_simple_display_pipe *pipe,
mxsfb->connector = >panel_connector;
}
 
+   drm_crtc_vblank_on(>crtc);
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -164,6 +169,8 @@ static void mxsfb_pipe_disable(struct 
drm_simple_display_pipe *pipe)
}
spin_unlock_irq(>event_lock);
 
+   drm_crtc_vblank_off(>crtc);
+
if (mxsfb->connector != >panel_connector)
mxsfb->connector = NULL;
 }
@@ -246,7 +253,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
 
pm_runtime_enable(drm->dev);
 
-   ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+   ret = drm_vblank_init(drm, MAX_CRTCS);
if (ret < 0) {
dev_err(drm->dev, "Failed to initialise vblank\n");
goto err_vblank;
-- 
2.7.4



Re: [EXT] Re: [PATCH v2 06/15] drm/mxsfb: Update mxsfb with additional pixel formats

2019-08-14 Thread Robert Chiras
Hi Daniel,

On Mi, 2019-08-14 at 12:44 +0100, Daniel Stone wrote:
> Hi Robert,
> 
> On Wed, 14 Aug 2019 at 11:49, Robert Chiras 
> wrote:
> > 
> > +   case DRM_FORMAT_BGR565: /* BG16 */
> > +   if (mxsfb->devdata->ipversion < 4)
> > +   goto err;
> > +   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BG
> > R) |
> > +   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_
> > BGR),
> > +   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
> > +   /* Fall through */
> > +   case DRM_FORMAT_RGB565: /* RG16 */
> > +   ctrl |= CTRL_SET_WORD_LENGTH(0);
> > +   ctrl &= ~CTRL_DF16;
> > +   ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
> > +   break;
> For non-BGR formats, do you need to write RGB line-pattern back to
> the
> CTRL2 register? Otherwise, if you start with BGR565 then switch back
> to RGB565, presumably CTRL2 would still be programmed for BGR so you
> would display inverted channels.
The LINE_PATTERN from LCDC_V4_CTRL2 register is cleared above, with
this code:
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR) |
+  CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
> 
> Same goes for all the other BGR/RGB format pairs below.
> 
> Cheers,
> Daniel

Thanks,
Robert

Re: [EXT] Re: [PATCH v2 09/15] dt-bindings: display: Add max-res property for mxsfb

2019-08-14 Thread Robert Chiras
Hi Stefann,
On Mi, 2019-08-14 at 13:25 +0200, Stefan Agner wrote:
> On 2019-08-14 13:14, Robert Chiras wrote:
> > 
> > Hi Stefan,
> > On Mi, 2019-08-14 at 13:03 +0200, Stefan Agner wrote:
> > > 
> > > On 2019-08-14 12:48, Robert Chiras wrote:
> > > > 
> > > > 
> > > > Add new optional property 'max-res', to limit the maximum
> > > > supported
> > > > resolution by the MXSFB_DRM driver.
> > > I would also mention the reason why we need this.
> > > 
> > > I guess this needs a vendor prefix as well (fsl,max-res). I also
> > > would
> > > like to have the ack of the device tree folks here.
> > Rob Herring also aked be about this, and I'll copy here the reply,
> > with
> > explanations:
> > 
> > Indeed, this limitation is actually due to bandwidth limitation,
> > but
> > the problem is that this limitation comes on i.MX8M (known as
> > mScale
> > 850D), where the memory bandwidth cannot support: GPU/VPU workload
> > in
> > the same time with both DCSS driving 4k@60 and eLCDIF driving 1080p
> > @60.
> > Since eLCDIF is a secondary display we though to add the posibility
> > to
> > limit it's bandwidth by limiting the resolution.
> > If you say that more details are needed, I can add them in the
> > description.
> Oh sorry I missed that.
> 
> Rob Herring also wrote:
> > 
> > I suppose what you are after is bandwidth limits? IIRC, there's
> > already
> > some bindings expressing such limits. Also, wouldn't you need to
> > account
> > for bpp and using the 2nd plane (IIRC that there is one).
> I guess the binding he refers to is max-memory-bandwidth, which is
> used
> in multiple driver already. It makes sense to reuse this property
> instead of inventing a new set of property which is also not taking
> bpp
> into account...
Actually I saw this binding, but I thought it is strictly related to
that driver, where it is documented. Now, that you say this one is used
in many drivers (and recalling that you suggested for my 'max-res' to
add a prefix), I get it now.
> 
> The pl111 driver implements this property, it should be fairly easy
> to
> adopt that code.
Sure, I will do something similar here, too.
> 
> --
> Stefan
> 
> 
> 
> > 
> > > 
> > > 
> > > --
> > > Stefan
> > > 
> > > > 
> > > > 
> > > > 
> > > > Signed-off-by: Robert Chiras 
> > > > ---
> > > >  Documentation/devicetree/bindings/display/mxsfb.txt | 6 ++
> > > >  1 file changed, 6 insertions(+)
> > > > 
> > > > diff --git
> > > > a/Documentation/devicetree/bindings/display/mxsfb.txt
> > > > b/Documentation/devicetree/bindings/display/mxsfb.txt
> > > > index 472e1ea..55e22ed 100644
> > > > --- a/Documentation/devicetree/bindings/display/mxsfb.txt
> > > > +++ b/Documentation/devicetree/bindings/display/mxsfb.txt
> > > > @@ -17,6 +17,12 @@ Required properties:
> > > >  Required sub-nodes:
> > > >    - port: The connection to an encoder chip.
> > > > 
> > > > +Optional properties:
> > > > +- max-res:   an array with a maximum of two integers,
> > > > representing
> > > > the
> > > > + maximum supported resolution, in the form of
> > > > + , ; if one of the item is <0>, the
> > > > default
> > > > + driver-defined maximum resolution for that axis
> > > > is
> > > > used
> > > > +
> > > >  Example:
> > > > 
> > > >   lcdif1: display-controller@222 {
> > Thanks,
> > Robert

Re: [EXT] Re: [PATCH v2 04/15] drm/mxsfb: Reset vital register for a proper initialization

2019-08-14 Thread Robert Chiras
Hi Stefan,

On Mi, 2019-08-14 at 13:11 +0200, Stefan Agner wrote:
> On 2019-08-14 12:48, Robert Chiras wrote:
> > 
> > Some of the regiters need, like LCDC_CTRL and
> > CTRL2_OUTSTANDING_REQS
> Typo in registers, and there is a need to many.
Thanks, will fix this.
> 
> > 
> > needs to be properly cleared and initialized for a better start and
> > stop
> > routine.
> 
> 
> > 
> > 
> > Signed-off-by: Robert Chiras 
> > ---
> >  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 
> >  1 file changed, 12 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > index b69ace8..5e44f57 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > @@ -127,6 +127,10 @@ static void mxsfb_enable_controller(struct
> > mxsfb_drm_private *mxsfb)
> >   clk_prepare_enable(mxsfb->clk_disp_axi);
> >   clk_prepare_enable(mxsfb->clk);
> > 
> > + if (mxsfb->devdata->ipversion >= 4)
> > + writel(CTRL2_OUTSTANDING_REQS(REQ_16),
> > +mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
> > +
> >   /* If it was disabled, re-enable the mode again */
> >   writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
> > 
> > @@ -136,12 +140,19 @@ static void mxsfb_enable_controller(struct
> > mxsfb_drm_private *mxsfb)
> >   writel(reg, mxsfb->base + LCDC_VDCTRL4);
> > 
> >   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
> > + writel(CTRL1_RECOVERY_ON_UNDERFLOW, mxsfb->base + LCDC_CTRL1
> > + REG_SET);
> This seems not to be accounted for in the commit message. Can you do
> this in a separate commit?
> 
> Also I suggest to introduce CTRL1_RECOVERY_ON_UNDERFLOW in that same
> commit.
You are right, I missed this one in the description. I will add this
one too.
> 
> --
> Stefan
> 
> > 
> >  }
> > 
> >  static void mxsfb_disable_controller(struct mxsfb_drm_private
> > *mxsfb)
> >  {
> >   u32 reg;
> > 
> > + if (mxsfb->devdata->ipversion >= 4)
> > + writel(CTRL2_OUTSTANDING_REQS(0x7),
> > +mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
> > +
> > + writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
> > +
> >   /*
> >    * Even if we disable the controller here, it will still
> > continue
> >    * until its FIFOs are running out of data
> > @@ -295,6 +306,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private
> > *mxsfb)
> >   dma_addr_t paddr;
> > 
> >   mxsfb_enable_axi_clk(mxsfb);
> > + writel(0, mxsfb->base + LCDC_CTRL);
> >   mxsfb_crtc_mode_set_nofb(mxsfb);
> > 
> >   /* Write cur_buf as well to avoid an initial corrupt frame */

Thanks,
Robert

Re: [EXT] Re: [PATCH v2 12/15] drm/mxsfb: Improve the axi clock usage

2019-08-14 Thread Robert Chiras
Hi Stefan,

On Mi, 2019-08-14 at 13:06 +0200, Stefan Agner wrote:
> On 2019-08-14 12:48, Robert Chiras wrote:
> > 
> > Currently, the enable of the axi clock return status is ignored,
> > causing
> > issues when the enable fails then we try to disable it. Therefore,
> > it is
> > better to check the return status and disable it only when enable
> > succeeded.
> Is this actually the case in real world sometimes? Why is it failing?
When I noticed that fail, we had some restrictions in SCU firmware, so
that the clock cannot be enabled if the power domain was down. Still,
at that time I noticed it is redundant to have functions that checks if
a clock is NULL or not, since the clk_* functions are already doing
this.
> 
> I guess if we do this in one place, we should do it in all places
> (e.g.
> also in mxsfb_crtc_enable, mxsfb_plane_atomic_update..)
I add specific checks only in the vblank functions, because those
functions can be called before calling the pipe enable/disable
functions which enables the spefic power domain and, at this point, the
clock enable/disable calls should not fail.
> 
> --
> Stefan
> 
> > 
> > Also, remove the helper functions around clk_axi, since we can
> > directly
> > use the clk API function for enable/disable the clock. Those
> > functions
> > are already checking for NULL clk and returning 0 if that's the
> > case.
> 
> > 
> > 
> > Signed-off-by: Robert Chiras 
> > Acked-by: Leonard Crestez 
> > ---
> >  drivers/gpu/drm/mxsfb/mxsfb_crtc.c |  8 
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 32 +-
> > --
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  3 ---
> >  3 files changed, 17 insertions(+), 26 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > index a4ba368..e727f5e 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
> > @@ -408,7 +408,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private
> > *mxsfb)
> >  {
> >   dma_addr_t paddr;
> > 
> > - mxsfb_enable_axi_clk(mxsfb);
> > + clk_prepare_enable(mxsfb->clk_axi);
> >   writel(0, mxsfb->base + LCDC_CTRL);
> >   mxsfb_crtc_mode_set_nofb(mxsfb);
> > 
> > @@ -425,7 +425,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private
> > *mxsfb)
> >  void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
> >  {
> >   mxsfb_disable_controller(mxsfb);
> > - mxsfb_disable_axi_clk(mxsfb);
> > + clk_disable_unprepare(mxsfb->clk_axi);
> >  }
> > 
> >  void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
> > @@ -451,8 +451,8 @@ void mxsfb_plane_atomic_update(struct
> > mxsfb_drm_private *mxsfb,
> > 
> >   paddr = mxsfb_get_fb_paddr(mxsfb);
> >   if (paddr) {
> > - mxsfb_enable_axi_clk(mxsfb);
> > + clk_prepare_enable(mxsfb->clk_axi);
> >   writel(paddr, mxsfb->base + mxsfb->devdata-
> > >next_buf);
> > - mxsfb_disable_axi_clk(mxsfb);
> > + clk_disable_unprepare(mxsfb->clk_axi);
> >   }
> >  }
> > diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > index 6dae2bd..694b287 100644
> > --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
> > @@ -97,18 +97,6 @@ drm_pipe_to_mxsfb_drm_private(struct
> > drm_simple_display_pipe *pipe)
> >   return container_of(pipe, struct mxsfb_drm_private, pipe);
> >  }
> > 
> > -void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
> > -{
> > - if (mxsfb->clk_axi)
> > - clk_prepare_enable(mxsfb->clk_axi);
> > -}
> > -
> > -void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
> > -{
> > - if (mxsfb->clk_axi)
> > - clk_disable_unprepare(mxsfb->clk_axi);
> > -}
> > -
> >  /**
> >   * mxsfb_atomic_helper_check - validate state object
> >   * @dev: DRM device
> > @@ -229,25 +217,31 @@ static void mxsfb_pipe_update(struct
> > drm_simple_display_pipe *pipe,
> >  static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe
> > *pipe)
> >  {
> >   struct mxsfb_drm_private *mxsfb =
> > drm_pipe_to_mxsfb_drm_private(pipe);
> > + int ret = 0;
> > +
> > + ret = clk_prepare_enable(mxsfb->clk_axi);
> > + if (ret)
> > + return ret;
> > 
> >   /* Clear and 

Re: [EXT] Re: [PATCH v2 09/15] dt-bindings: display: Add max-res property for mxsfb

2019-08-14 Thread Robert Chiras
Hi Stefan,
On Mi, 2019-08-14 at 13:03 +0200, Stefan Agner wrote:
> On 2019-08-14 12:48, Robert Chiras wrote:
> > 
> > Add new optional property 'max-res', to limit the maximum supported
> > resolution by the MXSFB_DRM driver.
> I would also mention the reason why we need this.
> 
> I guess this needs a vendor prefix as well (fsl,max-res). I also
> would
> like to have the ack of the device tree folks here.
Rob Herring also aked be about this, and I'll copy here the reply, with
explanations:

Indeed, this limitation is actually due to bandwidth limitation, but
the problem is that this limitation comes on i.MX8M (known as mScale
850D), where the memory bandwidth cannot support: GPU/VPU workload in
the same time with both DCSS driving 4k@60 and eLCDIF driving 1080p@60.
Since eLCDIF is a secondary display we though to add the posibility to
limit it's bandwidth by limiting the resolution.
If you say that more details are needed, I can add them in the
description.
> 
> --
> Stefan
> 
> > 
> > 
> > Signed-off-by: Robert Chiras 
> > ---
> >  Documentation/devicetree/bindings/display/mxsfb.txt | 6 ++
> >  1 file changed, 6 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt
> > b/Documentation/devicetree/bindings/display/mxsfb.txt
> > index 472e1ea..55e22ed 100644
> > --- a/Documentation/devicetree/bindings/display/mxsfb.txt
> > +++ b/Documentation/devicetree/bindings/display/mxsfb.txt
> > @@ -17,6 +17,12 @@ Required properties:
> >  Required sub-nodes:
> >    - port: The connection to an encoder chip.
> > 
> > +Optional properties:
> > +- max-res:   an array with a maximum of two integers, representing
> > the
> > + maximum supported resolution, in the form of
> > + , ; if one of the item is <0>, the
> > default
> > + driver-defined maximum resolution for that axis is
> > used
> > +
> >  Example:
> > 
> >   lcdif1: display-controller@222 {

Thanks,
Robert

[PATCH v2 05/15] drm/mxsfb: Update register definitions using bit manipulation defines

2019-08-14 Thread Robert Chiras
Use BIT(x) and GEN_MASK(h, l) for better representation the inside of
various registers.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 151 ++---
 1 file changed, 89 insertions(+), 62 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 71426aa..9fcb1db 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -40,66 +40,93 @@
 #define LCDC_AS_BUF0x220
 #define LCDC_AS_NEXT_BUF   0x230
 
-#define CTRL_SFTRST(1 << 31)
-#define CTRL_CLKGATE   (1 << 30)
-#define CTRL_BYPASS_COUNT  (1 << 19)
-#define CTRL_VSYNC_MODE(1 << 18)
-#define CTRL_DOTCLK_MODE   (1 << 17)
-#define CTRL_DATA_SELECT   (1 << 16)
-#define CTRL_SET_BUS_WIDTH(x)  (((x) & 0x3) << 10)
-#define CTRL_GET_BUS_WIDTH(x)  (((x) >> 10) & 0x3)
-#define CTRL_BUS_WIDTH_MASK(0x3 << 10)
-#define CTRL_SET_WORD_LENGTH(x)(((x) & 0x3) << 8)
-#define CTRL_GET_WORD_LENGTH(x)(((x) >> 8) & 0x3)
-#define CTRL_MASTER(1 << 5)
-#define CTRL_DF16  (1 << 3)
-#define CTRL_DF18  (1 << 2)
-#define CTRL_DF24  (1 << 1)
-#define CTRL_RUN   (1 << 0)
-
-#define CTRL1_RECOVERY_ON_UNDERFLOW(1 << 24)
-#define CTRL1_FIFO_CLEAR   (1 << 21)
-#define CTRL1_SET_BYTE_PACKAGING(x)(((x) & 0xf) << 16)
-#define CTRL1_GET_BYTE_PACKAGING(x)(((x) >> 16) & 0xf)
-#define CTRL1_CUR_FRAME_DONE_IRQ_EN(1 << 13)
-#define CTRL1_CUR_FRAME_DONE_IRQ   (1 << 9)
-
-#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
-
-#define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
-#define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
-#define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0x)
-#define TRANSFER_COUNT_GET_HCOUNT(x)   ((x) & 0x)
-
-#define VDCTRL0_ENABLE_PRESENT (1 << 28)
-#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27)
-#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26)
-#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25)
-#define VDCTRL0_ENABLE_ACT_HIGH(1 << 24)
-#define VDCTRL0_VSYNC_PERIOD_UNIT  (1 << 21)
-#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20)
-#define VDCTRL0_HALF_LINE  (1 << 19)
-#define VDCTRL0_HALF_LINE_MODE (1 << 18)
-#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3)
-#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3)
-
-#define VDCTRL2_SET_HSYNC_PERIOD(x)((x) & 0x3)
-#define VDCTRL2_GET_HSYNC_PERIOD(x)((x) & 0x3)
-
-#define VDCTRL3_MUX_SYNC_SIGNALS   (1 << 29)
-#define VDCTRL3_VSYNC_ONLY (1 << 28)
-#define SET_HOR_WAIT_CNT(x)(((x) & 0xfff) << 16)
-#define GET_HOR_WAIT_CNT(x)(((x) >> 16) & 0xfff)
-#define SET_VERT_WAIT_CNT(x)   ((x) & 0x)
-#define GET_VERT_WAIT_CNT(x)   ((x) & 0x)
-
-#define VDCTRL4_SET_DOTCLK_DLY(x)  (((x) & 0x7) << 29) /* v4 only */
-#define VDCTRL4_GET_DOTCLK_DLY(x)  (((x) >> 29) & 0x7) /* v4 only */
-#define VDCTRL4_SYNC_SIGNALS_ON(1 << 18)
-#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3)
-
-#define DEBUG0_HSYNC   (1 < 26)
-#define DEBUG0_VSYNC   (1 < 25)
+/* reg bit manipulation */
+#define REG_PUT(x, h, l) (((x) << (l)) & GENMASK(h, l))
+#define REG_GET(x, h, l) (((x) & GENMASK(h, l)) >> (l))
+
+#define CTRL_SFTRSTBIT(31)
+#define CTRL_CLKGATE   BIT(30)
+#define CTRL_SHIFT_DIR(x)  REG_PUT((x), 26, 26)
+#define CTRL_SHIFT_NUM(x)  REG_PUT((x), 25, 21)
+#define CTRL_BYPASS_COUNT  BIT(19)
+#define CTRL_VSYNC_MODEBIT(18)
+#define CTRL_DOTCLK_MODE   BIT(17)
+#define CTRL_DATA_SELECT   BIT(16)
+#define CTRL_INPUT_SWIZZLE(x)  REG_PUT((x), 15, 14)
+#define CTRL_CSC_SWIZZLE(x)REG_PUT((x), 13, 12)
+#define CTRL_SET_BUS_WIDTH(x)  REG_PUT((x), 11, 10)
+#define CTRL_GET_BUS_WIDTH(x)  REG_GET((x), 11, 10)
+#define CTRL_BUS_WIDTH_MASKREG_PUT((0x3), 11, 10)
+#define CTRL_SET_WORD_LENGTH(x)REG_PUT((x), 9, 8)
+#define CTRL_GET_WORD_LENGTH(x)REG_GET((x), 9, 8)
+#define CTRL_MASTERBIT(5)
+#define CTRL_DF16  BIT(3)
+#define CTRL_DF18  BIT(2)
+#define CTRL_DF24  BIT(1)
+#define CTRL

[PATCH v2 01/15] drm/mxsfb: Update mxsfb to support a bridge

2019-08-14 Thread Robert Chiras
Currently, the MXSFB DRM driver only supports a panel. But, its output
display signal can also be redirected to another encoder, like a DSI
controller. In this case, that DSI controller may act like a drm_bridge.
In order support this use-case too, this patch adds support for drm_bridge
in mxsfb.

Signed-off-by: Robert Chiras 
Tested-by: Guido Günther 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 17 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 46 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  4 +++-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  | 26 +++--
 4 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1242156..de09b93 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -95,8 +95,11 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private 
*mxsfb)
 
reg = readl(mxsfb->base + LCDC_CTRL);
 
-   if (mxsfb->connector.display_info.num_bus_formats)
-   bus_format = mxsfb->connector.display_info.bus_formats[0];
+   if (mxsfb->connector->display_info.num_bus_formats)
+   bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
+bus_format);
 
reg &= ~CTRL_BUS_WIDTH_MASK;
switch (bus_format) {
@@ -204,8 +207,9 @@ static dma_addr_t mxsfb_get_fb_paddr(struct 
mxsfb_drm_private *mxsfb)
 
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
+   struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -229,6 +233,13 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
+m->crtc_clock,
+(int)(clk_get_rate(mxsfb->clk) / 1000));
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
+bus_flags);
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
+
writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
   TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
   mxsfb->base + mxsfb->devdata->transfer_count);
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 878ef68..9dc69b7 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -101,9 +101,25 @@ static void mxsfb_pipe_enable(struct 
drm_simple_display_pipe *pipe,
  struct drm_crtc_state *crtc_state,
  struct drm_plane_state *plane_state)
 {
+   struct drm_connector *connector;
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
struct drm_device *drm = pipe->plane.dev;
 
+   if (!mxsfb->connector) {
+   list_for_each_entry(connector,
+   >mode_config.connector_list,
+   head)
+   if (connector->encoder == >pipe.encoder) {
+   mxsfb->connector = connector;
+   break;
+   }
+   }
+
+   if (!mxsfb->connector) {
+   dev_warn(drm->dev, "No connector attached, using default\n");
+   mxsfb->connector = >panel_connector;
+   }
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -129,6 +145,9 @@ static void mxsfb_pipe_disable(struct 
drm_simple_display_pipe *pipe)
drm_crtc_send_vblank_event(crtc, event);
}
spin_unlock_irq(>event_lock);
+
+   if (mxsfb->connector != >panel_connector)
+   mxsfb->connector = NULL;
 }
 
 static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
@@ -226,16 +245,33 @@ static int mxsfb_load(struct drm_device *drm, unsigned 
long flags)
 
ret = drm_simple_display_pipe_init(drm, >pipe, _funcs,
mxsfb_formats, ARRAY_SIZE(mxsfb_formats), NULL,
-   >connector);
+   mxsfb->connector);
if (ret < 0) {
dev_err(drm->dev, "Cannot setup simple display pipe\n");
goto err_vblank;
}
 
-   ret = drm_

[PATCH v2 04/15] drm/mxsfb: Reset vital register for a proper initialization

2019-08-14 Thread Robert Chiras
Some of the regiters need, like LCDC_CTRL and CTRL2_OUTSTANDING_REQS
needs to be properly cleared and initialized for a better start and stop
routine.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index b69ace8..5e44f57 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -127,6 +127,10 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_OUTSTANDING_REQS(REQ_16),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
 
@@ -136,12 +140,19 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
writel(reg, mxsfb->base + LCDC_VDCTRL4);
 
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+   writel(CTRL1_RECOVERY_ON_UNDERFLOW, mxsfb->base + LCDC_CTRL1 + REG_SET);
 }
 
 static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
/*
 * Even if we disable the controller here, it will still continue
 * until its FIFOs are running out of data
@@ -295,6 +306,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
dma_addr_t paddr;
 
mxsfb_enable_axi_clk(mxsfb);
+   writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
/* Write cur_buf as well to avoid an initial corrupt frame */
-- 
2.7.4



[PATCH v2 07/15] drm/mxsfb: Fix the vblank events

2019-08-14 Thread Robert Chiras
Currently, the vblank support is not correctly implemented in MXSFB_DRM
driver. The call to drm_vblank_init is made with mode_config.num_crtc
which at that time is 0. Because of this, vblank is not activated, so
there won't be any vblank event submitted.
For example, when running modetest with the '-v' parameter will result
in an astronomical refresh rate (1+ Hz), because of that.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 2743975..829abec 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -38,6 +38,9 @@
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
 
+/* The eLCDIF max possible CRTCs */
+#define MAX_CRTCS 1
+
 enum mxsfb_devtype {
MXSFB_V3,
MXSFB_V4,
@@ -138,6 +141,8 @@ static void mxsfb_pipe_enable(struct 
drm_simple_display_pipe *pipe,
mxsfb->connector = >panel_connector;
}
 
+   drm_crtc_vblank_on(>crtc);
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -164,6 +169,8 @@ static void mxsfb_pipe_disable(struct 
drm_simple_display_pipe *pipe)
}
spin_unlock_irq(>event_lock);
 
+   drm_crtc_vblank_off(>crtc);
+
if (mxsfb->connector != >panel_connector)
mxsfb->connector = NULL;
 }
@@ -246,7 +253,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
 
pm_runtime_enable(drm->dev);
 
-   ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+   ret = drm_vblank_init(drm, MAX_CRTCS);
if (ret < 0) {
dev_err(drm->dev, "Failed to initialise vblank\n");
goto err_vblank;
@@ -269,6 +276,8 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
goto err_vblank;
}
 
+   drm_crtc_vblank_off(>pipe.crtc);
+
/*
 * Attach panel only if there is one.
 * If there is no panel attach, it must be a bridge. In this case, we
-- 
2.7.4



[PATCH v2 09/15] dt-bindings: display: Add max-res property for mxsfb

2019-08-14 Thread Robert Chiras
Add new optional property 'max-res', to limit the maximum supported
resolution by the MXSFB_DRM driver.

Signed-off-by: Robert Chiras 
---
 Documentation/devicetree/bindings/display/mxsfb.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt 
b/Documentation/devicetree/bindings/display/mxsfb.txt
index 472e1ea..55e22ed 100644
--- a/Documentation/devicetree/bindings/display/mxsfb.txt
+++ b/Documentation/devicetree/bindings/display/mxsfb.txt
@@ -17,6 +17,12 @@ Required properties:
 Required sub-nodes:
   - port: The connection to an encoder chip.
 
+Optional properties:
+- max-res: an array with a maximum of two integers, representing the
+   maximum supported resolution, in the form of
+   , ; if one of the item is <0>, the default
+   driver-defined maximum resolution for that axis is used
+
 Example:
 
lcdif1: display-controller@222 {
-- 
2.7.4



[PATCH v2 10/15] drm/mxsfb: Add max-res property for MXSFB

2019-08-14 Thread Robert Chiras
Because of stability issues, we may want to limit the maximum resolution
supported by the MXSFB (eLCDIF) driver.
This patch add support for a new property which we can use to impose such
limitation.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 59c8ba7..6dae2bd 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -264,6 +264,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
struct platform_device *pdev = to_platform_device(drm->dev);
struct mxsfb_drm_private *mxsfb;
struct resource *res;
+   u32 max_res[2] = {0, 0};
int ret;
 
mxsfb = devm_kzalloc(>dev, sizeof(*mxsfb), GFP_KERNEL);
@@ -344,10 +345,17 @@ static int mxsfb_load(struct drm_device *drm, unsigned 
long flags)
}
}
 
+   of_property_read_u32_array(drm->dev->of_node, "max-res",
+  _res[0], 2);
+   if (!max_res[0])
+   max_res[0] = MXSFB_MAX_XRES;
+   if (!max_res[1])
+   max_res[1] = MXSFB_MAX_YRES;
+
drm->mode_config.min_width  = MXSFB_MIN_XRES;
drm->mode_config.min_height = MXSFB_MIN_YRES;
-   drm->mode_config.max_width  = MXSFB_MAX_XRES;
-   drm->mode_config.max_height = MXSFB_MAX_YRES;
+   drm->mode_config.max_width  = max_res[0];
+   drm->mode_config.max_height = max_res[1];
drm->mode_config.funcs  = _mode_config_funcs;
drm->mode_config.helper_private = _mode_config_helpers;
 
-- 
2.7.4



[PATCH v2 15/15] drm/mxsfb: Add support for live pixel format change

2019-08-14 Thread Robert Chiras
This IP requires full stop and re-start when changing display timings,
but we can change the pixel format while running.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 317575e..5607fc0 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -494,6 +494,7 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
struct drm_crtc *crtc = >crtc;
struct drm_plane_state *new_state = pipe->plane.state;
struct drm_framebuffer *fb = pipe->plane.state->fb;
+   struct drm_framebuffer *old_fb = state->fb;
struct drm_pending_vblank_event *event;
u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
@@ -510,7 +511,7 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   if (!fb)
+   if (!fb || !old_fb)
return;
 
fb_addr = mxsfb_get_fb_paddr(mxsfb);
@@ -533,4 +534,17 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
src_w = new_state->src_w >> 16;
mxsfb_set_fb_hcrop(mxsfb, src_w, stride);
}
+
+   if (old_fb->format->format != fb->format->format) {
+   struct drm_format_name_buf old_fmt_buf;
+   struct drm_format_name_buf new_fmt_buf;
+
+   DRM_DEV_DEBUG_DRIVER(crtc->dev->dev,
+   "Switching pixel format: %s -> %s\n",
+   drm_get_format_name(old_fb->format->format,
+   _fmt_buf),
+   drm_get_format_name(fb->format->format,
+   _fmt_buf));
+   mxsfb_set_pixel_fmt(mxsfb, true);
+   }
 }
-- 
2.7.4



[PATCH v2 14/15] drm/mxsfb: Add support for horizontal stride

2019-08-14 Thread Robert Chiras
Besides the eLCDIF block, there is another IP block, used in the past
for EPDC panels. Since the iMX.8mq doesn't have an EPDC connector, this
block is not documented, but we can use it to do additional operations
on the frame buffer.
In this case, we can use the pigeon registers from this IP block in
order to do horizontal crop on the frame buffer processed by the eLCDIF
block.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 79 --
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 26 -
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 16 
 3 files changed, 115 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index a12f53d..317575e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -15,6 +15,7 @@
 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -435,13 +436,66 @@ void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+void mxsfb_set_fb_hcrop(struct mxsfb_drm_private *mxsfb, u32 src_w, u32 fb_w)
+{
+   u32 mask_cnt, htotal, hcount;
+   u32 vdctrl2, vdctrl3, vdctrl4, transfer_count;
+   u32 pigeon_12_0, pigeon_12_1, pigeon_12_2;
+
+   if (src_w == fb_w) {
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   return;
+   }
+
+   transfer_count = readl(mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+   hcount = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+
+   transfer_count &= ~TRANSFER_COUNT_SET_HCOUNT(0x);
+   transfer_count |= TRANSFER_COUNT_SET_HCOUNT(fb_w);
+   writel(transfer_count, mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+
+   vdctrl2 = readl(mxsfb->base + LCDC_VDCTRL2);
+   htotal  = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2);
+   htotal  += fb_w - hcount;
+   vdctrl2 &= ~VDCTRL2_SET_HSYNC_PERIOD(0x3);
+   vdctrl2 |= VDCTRL2_SET_HSYNC_PERIOD(htotal);
+   writel(vdctrl2, mxsfb->base + LCDC_VDCTRL2);
+
+   vdctrl4 = readl(mxsfb->base + LCDC_VDCTRL4);
+   vdctrl4 &= ~SET_DOTCLK_H_VALID_DATA_CNT(0x3);
+   vdctrl4 |= SET_DOTCLK_H_VALID_DATA_CNT(fb_w);
+   writel(vdctrl4, mxsfb->base + LCDC_VDCTRL4);
+
+   /* configure related pigeon registers */
+   vdctrl3  = readl(mxsfb->base + LCDC_VDCTRL3);
+   mask_cnt = GET_HOR_WAIT_CNT(vdctrl3) - 5;
+
+   pigeon_12_0 = PIGEON_12_0_SET_STATE_MASK(0x24)  |
+ PIGEON_12_0_SET_MASK_CNT(mask_cnt)|
+ PIGEON_12_0_SET_MASK_CNT_SEL(0x6) |
+ PIGEON_12_0_POL_ACTIVE_LOW|
+ PIGEON_12_0_EN;
+   writel(pigeon_12_0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+
+   pigeon_12_1 = PIGEON_12_1_SET_CLR_CNT(src_w) |
+ PIGEON_12_1_SET_SET_CNT(0x0);
+   writel(pigeon_12_1, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   pigeon_12_2 = 0x0;
+   writel(pigeon_12_2, mxsfb->base + HW_EPDC_PIGEON_12_2);
+}
+
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
   struct drm_plane_state *state)
 {
struct drm_simple_display_pipe *pipe = >pipe;
struct drm_crtc *crtc = >crtc;
+   struct drm_plane_state *new_state = pipe->plane.state;
+   struct drm_framebuffer *fb = pipe->plane.state->fb;
struct drm_pending_vblank_event *event;
-   dma_addr_t paddr;
+   u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
spin_lock_irq(>dev->event_lock);
event = crtc->state->event;
@@ -456,10 +510,27 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   paddr = mxsfb_get_fb_paddr(mxsfb);
-   if (paddr) {
+   if (!fb)
+   return;
+
+   fb_addr = mxsfb_get_fb_paddr(mxsfb);
+   if (mxsfb->devdata->ipversion >= 4) {
+   cpp = fb->format->cpp[0];
+   src_off = (new_state->src_y >> 16) * fb->pitches[0] +
+ (new_state->src_x >> 16) * cpp;
+   fb_addr += fb->offsets[0] + src_off;
+   }
+
+   if (fb_addr) {
clk_prepare_enable(mxsfb->clk_axi);
-   writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
+   writel(fb_addr, mxsfb->base + mxsfb->devdata->next_buf);
clk_disable_unprepare(mxsfb->clk_axi);
}
+
+   if (mxsfb->devdata->ipversion >= 4 &&
+   unlikely(drm_atomic_crtc_needs_modeset(new_state->crtc->state))) {
+   stride = DIV_ROUND_UP(fb->pitches[0], cpp);
+   src_w = new_state->src_w >> 16;
+   mxsfb_set_fb_hcrop(mxsfb, 

[PATCH v2 12/15] drm/mxsfb: Improve the axi clock usage

2019-08-14 Thread Robert Chiras
Currently, the enable of the axi clock return status is ignored, causing
issues when the enable fails then we try to disable it. Therefore, it is
better to check the return status and disable it only when enable
succeeded.
Also, remove the helper functions around clk_axi, since we can directly
use the clk API function for enable/disable the clock. Those functions
are already checking for NULL clk and returning 0 if that's the case.

Signed-off-by: Robert Chiras 
Acked-by: Leonard Crestez 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c |  8 
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 32 +---
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  3 ---
 3 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index a4ba368..e727f5e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -408,7 +408,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 {
dma_addr_t paddr;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
@@ -425,7 +425,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
 {
mxsfb_disable_controller(mxsfb);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
@@ -451,8 +451,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
 
paddr = mxsfb_get_fb_paddr(mxsfb);
if (paddr) {
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
}
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 6dae2bd..694b287 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -97,18 +97,6 @@ drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe 
*pipe)
return container_of(pipe, struct mxsfb_drm_private, pipe);
 }
 
-void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_prepare_enable(mxsfb->clk_axi);
-}
-
-void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_disable_unprepare(mxsfb->clk_axi);
-}
-
 /**
  * mxsfb_atomic_helper_check - validate state object
  * @dev: DRM device
@@ -229,25 +217,31 @@ static void mxsfb_pipe_update(struct 
drm_simple_display_pipe *pipe,
 static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+   int ret = 0;
+
+   ret = clk_prepare_enable(mxsfb->clk_axi);
+   if (ret)
+   return ret;
 
/* Clear and enable VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
-   return 0;
+   return ret;
 }
 
 static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
 
+   if (clk_prepare_enable(mxsfb->clk_axi))
+   return;
+
/* Disable and clear VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
@@ -413,7 +407,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
struct mxsfb_drm_private *mxsfb = drm->dev_private;
u32 reg;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
 
reg = readl(mxsfb->base + LCDC_CTRL1);
 
@@ -422,7 +416,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
return IRQ_HANDLED;
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 8fb65d3..d6df8fe 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -37,9 +37,6 @@ struct mxsfb_drm_private {
 int mxsfb_setup_crtc(struct drm_device *dev);
 int mxsfb

[PATCH v2 06/15] drm/mxsfb: Update mxsfb with additional pixel formats

2019-08-14 Thread Robert Chiras
Since version 4 of eLCDIF, there are some registers that can do
transformations on the input data, like re-arranging the pixel
components. By doing that, we can support more pixel formats.
This patch adds support for X/ABGR and RGBX/A. Although, the local alpha
is not supported by eLCDIF, the alpha pixel formats were added to the
supported pixel formats but it will be ignored. This was necessary since
there are systems (like Android) that requires such pixel formats.

Also, add support for the following pixel formats:
16 bpp: RG16 ,BG16, XR15, XB15, AR15, AB15

Set the bus format based on input from the user and panel
capabilities.
Save the bus format in crtc->mode.private_flags, so the bridge can
use it.

Signed-off-by: Robert Chiras 
Signed-off-by: Mirela Rabulea 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 147 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  30 ++--
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |   3 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  15 
 4 files changed, 163 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 5e44f57..1be29f5 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -43,14 +43,17 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private 
*mxsfb, u32 val)
 }
 
 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
-static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb, bool update)
 {
struct drm_crtc *crtc = >pipe.crtc;
struct drm_device *drm = crtc->dev;
const u32 format = crtc->primary->state->fb->format->format;
-   u32 ctrl, ctrl1;
+   u32 ctrl = 0, ctrl1 = 0;
+   bool bgr_format = true;
+   struct drm_format_name_buf format_name_buf;
 
-   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
+   if (!update)
+   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 
/*
 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
@@ -59,64 +62,158 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private 
*mxsfb)
 * to arbitrary value. This limitation should not pose an issue.
 */
 
-   /* CTRL1 contains IRQ config and status bits, preserve those. */
-   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
-   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   if (!update) {
+   /* CTRL1 contains IRQ config and status bits, preserve those. */
+   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
+   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   }
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Setting up %s mode\n",
+drm_get_format_name(format, _name_buf));
+
+   /* Do some clean-up that we might have from a previous mode */
+   ctrl &= ~CTRL_SHIFT_DIR(1);
+   ctrl &= ~CTRL_SHIFT_NUM(0x3f);
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR) |
+  CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_CLR),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
 
switch (format) {
-   case DRM_FORMAT_RGB565:
-   dev_dbg(drm->dev, "Setting up RGB565 mode\n");
+   case DRM_FORMAT_BGR565: /* BG16 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR) |
+   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_RGB565: /* RG16 */
+   ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl &= ~CTRL_DF16;
+   ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
+   break;
+   case DRM_FORMAT_XBGR1555: /* XB15 */
+   case DRM_FORMAT_ABGR1555: /* AB15 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR) |
+   CTRL2_EVEN_LINE_PATTERN(CTRL2_LINE_PATTERN_BGR),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_XRGB1555: /* XR15 */
+   case DRM_FORMAT_ARGB1555: /* AR15 */
ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl |= CTRL_DF16;
ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
break;
-   case DRM_FORMAT_XRGB:
-   dev_dbg(drm->dev, "Setting up XRGB mode\n");
+   case DRM_FORMAT_RGBX: /* RX24 */
+   case DRM_FORMAT_RGBA: /* RA24 */
+   /* RGBX - > 

[PATCH v2 08/15] drm/mxsfb: Signal mode changed when bpp changed

2019-08-14 Thread Robert Chiras
From: Mirela Rabulea 

Add mxsfb_atomic_helper_check to signal mode changed when bpp changed.
This will trigger the execution of disable/enable on
a modeset with different bpp than the current one.

Signed-off-by: Mirela Rabulea 
Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 45 ++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 829abec..59c8ba7 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -108,9 +109,51 @@ void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+/**
+ * mxsfb_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * On top of the drm imlementation drm_atomic_helper_check,
+ * check if the bpp is changed, if so, signal mode_changed,
+ * this will trigger disable/enable
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+static int mxsfb_atomic_helper_check(struct drm_device *dev,
+struct drm_atomic_state *state)
+{
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_state;
+   int i, ret;
+
+   ret = drm_atomic_helper_check(dev, state);
+   if (ret)
+   return ret;
+
+   for_each_new_crtc_in_state(state, crtc, new_state, i) {
+   struct drm_plane_state *primary_state;
+   int old_bpp = 0;
+   int new_bpp = 0;
+
+   if (!crtc->primary || !crtc->primary->old_fb)
+   continue;
+   primary_state =
+   drm_atomic_get_plane_state(state, crtc->primary);
+   if (!primary_state || !primary_state->fb)
+   continue;
+   old_bpp = crtc->primary->old_fb->format->depth;
+   new_bpp = primary_state->fb->format->depth;
+   if (old_bpp != new_bpp)
+   new_state->mode_changed = true;
+   }
+   return ret;
+}
+
 static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
.fb_create  = drm_gem_fb_create,
-   .atomic_check   = drm_atomic_helper_check,
+   .atomic_check   = mxsfb_atomic_helper_check,
.atomic_commit  = drm_atomic_helper_commit,
 };
 
-- 
2.7.4



[PATCH v2 03/15] drm/mxsfb: Add defines for the rest of registers

2019-08-14 Thread Robert Chiras
Some of the existing registers in this controller are not defined, but
also not used. Add them to the register definitions, so that they can be
easily used in future improvements or fixes.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 932d7ea..71426aa 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -14,19 +14,31 @@
 
 #define LCDC_CTRL  0x00
 #define LCDC_CTRL1 0x10
+#define LCDC_V4_CTRL2  0x20
 #define LCDC_V3_TRANSFER_COUNT 0x20
 #define LCDC_V4_TRANSFER_COUNT 0x30
 #define LCDC_V4_CUR_BUF0x40
 #define LCDC_V4_NEXT_BUF   0x50
 #define LCDC_V3_CUR_BUF0x30
 #define LCDC_V3_NEXT_BUF   0x40
+#define LCDC_TIMING0x60
 #define LCDC_VDCTRL0   0x70
 #define LCDC_VDCTRL1   0x80
 #define LCDC_VDCTRL2   0x90
 #define LCDC_VDCTRL3   0xa0
 #define LCDC_VDCTRL4   0xb0
+#define LCDC_DVICTRL0  0xc0
+#define LCDC_DVICTRL1  0xd0
+#define LCDC_DVICTRL2  0xe0
+#define LCDC_DVICTRL3  0xf0
+#define LCDC_DVICTRL4  0x100
+#define LCDC_V4_DATA   0x180
+#define LCDC_V3_DATA   0x1b0
 #define LCDC_V4_DEBUG0 0x1d0
 #define LCDC_V3_DEBUG0 0x1f0
+#define LCDC_AS_CTRL   0x210
+#define LCDC_AS_BUF0x220
+#define LCDC_AS_NEXT_BUF   0x230
 
 #define CTRL_SFTRST(1 << 31)
 #define CTRL_CLKGATE   (1 << 30)
@@ -45,12 +57,15 @@
 #define CTRL_DF24  (1 << 1)
 #define CTRL_RUN   (1 << 0)
 
+#define CTRL1_RECOVERY_ON_UNDERFLOW(1 << 24)
 #define CTRL1_FIFO_CLEAR   (1 << 21)
 #define CTRL1_SET_BYTE_PACKAGING(x)(((x) & 0xf) << 16)
 #define CTRL1_GET_BYTE_PACKAGING(x)(((x) >> 16) & 0xf)
 #define CTRL1_CUR_FRAME_DONE_IRQ_EN(1 << 13)
 #define CTRL1_CUR_FRAME_DONE_IRQ   (1 << 9)
 
+#define CTRL2_OUTSTANDING_REQS__REQ_16 (4 << 21)
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   ((x) & 0x)
-- 
2.7.4



[PATCH v2 02/15] drm/mxsfb: Read bus flags from bridge if present

2019-08-14 Thread Robert Chiras
From: Guido Günther 

The bridge might have special requirmentes on the input bus. This
is e.g. used by the imx-nwl bridge.

Signed-off-by: Guido Günther 
Reviewed-by: Stefan Agner 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index de09b93..b69ace8 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -209,7 +209,7 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 {
struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
+   u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -233,6 +233,9 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   if (mxsfb->bridge && mxsfb->bridge->timings)
+   bus_flags = mxsfb->bridge->timings->input_bus_flags;
+
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(mxsfb->clk) / 1000));
-- 
2.7.4



[PATCH v2 00/15] Improvements and fixes for mxsfb DRM driver

2019-08-14 Thread Robert Chiras
This patch-set improves the use of eLCDIF block on iMX 8 SoCs (like 8MQ, 8MM
and 8QXP). Following, are the new features added and fixes from this
patch-set:

1. Add support for drm_bridge
On 8MQ and 8MM, the LCDIF block is not directly connected to a parallel
display connector, where an LCD panel can be attached, but instead it is
connected to DSI controller. Since this DSI stands between the display
controller (eLCDIF) and the physical connector, the DSI can be implemented
as a DRM bridge. So, in order to be able to connect the mxsfb driver to
the DSI driver, the support for a drm_bridge was needed in mxsfb DRM
driver (the actual driver for the eLCDIF block).

2. Add support for additional pixel formats
Some of the pixel formats needed by Android were not implemented in this
driver, but they were actually supported. So, add support for them.

3. Add support for horizontal stride
Having support for horizontal stride allows the use of eLCDIF with a GPU
(for example) that can only output resolution sizes multiple of a power of
8. For example, 1080 is not a power of 16, so in order to support 1920x1080
output from GPUs that can produce linear buffers only in sizes multiple to 16,
this feature is needed.

3. Few minor features and bug-fixing
The addition of max-res DT property was actually needed in order to limit
the bandwidth usage of the eLCDIF block. This is need on systems where
multiple display controllers are presend and the memory bandwidth is not
enough to handle all of them at maximum capacity (like it is the case on
8MQ, where there are two display controllers: DCSS and eLCDIF).
The rest of the patches are bug-fixes.

v2:
- Collected Tested-by from Guido
- Split the first patch, which added more than one feature into relevant
  patches, explaining each feature added
- Also split the second patch into more patches, to differentiate between
  the feature itself (additional pixel formats support) and the cleanup
  of the register definitions for a better representation (guido)
- Included a patch submitted by Guido, while he was testing my patch-set

Guido Günther (1):
  drm/mxsfb: Read bus flags from bridge if present

Mirela Rabulea (1):
  drm/mxsfb: Signal mode changed when bpp changed

Robert Chiras (13):
  drm/mxsfb: Update mxsfb to support a bridge
  drm/mxsfb: Add defines for the rest of registers
  drm/mxsfb: Reset vital register for a proper initialization
  drm/mxsfb: Update register definitions using bit manipulation defines
  drm/mxsfb: Update mxsfb with additional pixel formats
  drm/mxsfb: Fix the vblank events
  dt-bindings: display: Add max-res property for mxsfb
  drm/mxsfb: Add max-res property for MXSFB
  drm/mxsfb: Update mxsfb to support LCD reset
  drm/mxsfb: Improve the axi clock usage
  drm/mxsfb: Clear OUTSTANDING_REQS bits
  drm/mxsfb: Add support for horizontal stride
  drm/mxsfb: Add support for live pixel format change

 .../devicetree/bindings/display/mxsfb.txt  |   6 +
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 287 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 190 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  10 +-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  |  26 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 193 +-
 6 files changed, 573 insertions(+), 139 deletions(-)

-- 
2.7.4



[PATCH v2 11/15] drm/mxsfb: Update mxsfb to support LCD reset

2019-08-14 Thread Robert Chiras
The eLCDIF controller has control pin for the external LCD reset pin.
Add support for it and assert this pin in enable and de-assert it in
disable.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 14 ++
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  2 ++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 1be29f5..a4ba368 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -224,9 +224,12 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
-   if (mxsfb->devdata->ipversion >= 4)
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   }
 
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -244,11 +247,14 @@ static void mxsfb_disable_controller(struct 
mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
-   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(0x7),
   mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
-
-   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+   /* De-assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+   }
 
/*
 * Even if we disable the controller here, it will still continue
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index dc4daa0..0f63ba1 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -108,6 +108,8 @@
 #define CTRL2_LINE_PATTERN_BGR 5
 #define CTRL2_LINE_PATTERN_CLR 7
 
+#define CTRL2_LCD_RESETBIT(0)
+
 #define TRANSFER_COUNT_SET_VCOUNT(x)   REG_PUT((x), 31, 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   REG_GET((x), 31, 16)
 #define TRANSFER_COUNT_SET_HCOUNT(x)   REG_PUT((x), 15, 0)
-- 
2.7.4



[PATCH v2 13/15] drm/mxsfb: Clear OUTSTANDING_REQS bits

2019-08-14 Thread Robert Chiras
Bit 21 can alter the CTRL2_OUTSTANDING_REQS value right after the eLCDIF
is enabled, since it comes up with default value of 1 (this behaviour
has been seen on some imx8 platforms).
In order to fix this, clear CTRL2_OUTSTANDING_REQS bits before setting
its value.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index e727f5e..a12f53d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -225,6 +225,13 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk);
 
if (mxsfb->devdata->ipversion >= 4) {
+   /*
+* On some platforms, bit 21 is defaulted to 1, which may alter
+* the below setting. So, to make sure we have the right setting
+* clear all the bits for CTRL2_OUTSTANDING_REQS.
+*/
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
/* Assert LCD Reset bit */
-- 
2.7.4



Re: [EXT] Re: [PATCH 05/10] dt-bindings: display: Add max-res property for mxsfb

2019-08-14 Thread Robert Chiras
On Lu, 2019-07-22 at 11:48 -0600, Rob Herring wrote:
> On Wed, Jun 26, 2019 at 04:32:13PM +0300, Robert Chiras wrote:
> > 
> > Add new optional property 'max-res', to limit the maximum supported
> > resolution by the MXSFB_DRM driver.
> Bindings are for h/w description, not driver config.
> 
> > 
> > 
> > Signed-off-by: Robert Chiras 
> > ---
> >  Documentation/devicetree/bindings/display/mxsfb.txt | 6 ++
> >  1 file changed, 6 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt
> > b/Documentation/devicetree/bindings/display/mxsfb.txt
> > index 472e1ea..55e22ed 100644
> > --- a/Documentation/devicetree/bindings/display/mxsfb.txt
> > +++ b/Documentation/devicetree/bindings/display/mxsfb.txt
> > @@ -17,6 +17,12 @@ Required properties:
> >  Required sub-nodes:
> >    - port: The connection to an encoder chip.
> > 
> > +Optional properties:
> > +- max-res:   an array with a maximum of two integers, representing
> > the
> > + maximum supported resolution, in the form of
> > + , ; if one of the item is <0>, the
> > default
> > + driver-defined maximum resolution for that axis is
> > used
> I suppose what you are after is bandwidth limits? IIRC, there's
> already
> some bindings expressing such limits. Also, wouldn't you need to
> account
> for bpp and using the 2nd plane (IIRC that there is one).
I am sorry for this late reply, but I was looking after the existing
bindings expressing such limits. I didn't find such bindings related to
this driver though, I found some limits present in some other drivers.
Indeed, this limitation is actually due to bandwidth limitation, but
the problem is that this limitation comes i.MX8M (known as mScale
850D), where the memory bandwidth cannot support: GPU/VPU workload in
the same time with both DCSS driving 4k@60 and eLCDIF driving 1080p@60.
Since eLCDIF is a secondary display we though to add the posibility to
limit it's bandwidth by limiting the resolution.
Indeed, there is also a second plane, but currently not yet supported
(there is no support for second plane in MXSFB in the upstream driver
or in our internal tree).
If you think this limitation doesn't make sense, I can just drop it.
> 
> Rob

Thanks,
Robert

Re: [EXT] Re: [PATCH 00/10] Improvements and fixes for mxsfb DRM driver

2019-08-13 Thread Robert Chiras
On Ma, 2019-08-13 at 12:23 +0200, Guido Günther wrote:
> Hi Robert,
> On Wed, Jun 26, 2019 at 04:32:08PM +0300, Robert Chiras wrote:
> > 
> > This patch-set improves the use of eLCDIF block on iMX 8 SoCs (like
> > 8MQ, 8MM
> > and 8QXP). Following, are the new features added and fixes from
> > this
> > patch-set:
> There was some feedback on various patches, do you intend to pick
> that
> up again? That would be cool since there's some overlapping work
> popping
> up already e.g. in
> 
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> Fpatchwork.freedesktop.org%2Fseries%2F64595%2Fdata=02%7C01%7Crob
> ert.chiras%40nxp.com%7C6ca6724a656b41912f0408d71fd83da0%7C686ea1d3bc2
> b4c6fa92cd99c5c301635%7C0%7C0%7C637012885918631196sdata=b3CrbNu%
> 2FcsWBOA%2BcaQLX%2BrlrK7%2Fhf2%2F1vZS3eQGN7aM%3Dreserved=0
> 
> showing up and it's the base for the tiny
> 
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2
> Fpatchwork.freedesktop.org%2Fseries%2F64300%2Fdata=02%7C01%7Crob
> ert.chiras%40nxp.com%7C6ca6724a656b41912f0408d71fd83da0%7C686ea1d3bc2
> b4c6fa92cd99c5c301635%7C0%7C0%7C637012885918641196sdata=h6KLVnSx
> xBwvK%2FvPF9zt4DQR6WnF1pyQSwKBTO4rQTg%3Dreserved=0
> 
> Cheers,
>  -- Guido

Hi Guido,

Yes, I plan to submit a next revision, but first I wanted to try it with your 
patch-set for the nwl-dsi driver.
Thanks for the heads-up.

Best regards,
Robert

Re: [EXT] Re: [PATCH 00/10] Improvements and fixes for mxsfb DRM driver

2019-07-12 Thread Robert Chiras
Hi Guido,

On Jo, 2019-07-11 at 17:04 +0200, Guido Günther wrote:
> Hi Robert,
> On Wed, Jun 26, 2019 at 04:32:08PM +0300, Robert Chiras wrote:
> > 
> > This patch-set improves the use of eLCDIF block on iMX 8 SoCs (like
> > 8MQ, 8MM
> > and 8QXP). Following, are the new features added and fixes from
> > this
> > patch-set:
> > 
> > 1. Add support for drm_bridge
> > On 8MQ and 8MM, the LCDIF block is not directly connected to a
> > parallel
> > display connector, where an LCD panel can be attached, but instead
> > it is
> > connected to DSI controller. Since this DSI stands between the
> > display
> > controller (eLCDIF) and the physical connector, the DSI can be
> > implemented
> > as a DRM bridge. So, in order to be able to connect the mxsfb
> > driver to
> > the DSI driver, the support for a drm_bridge was needed in mxsfb
> > DRM
> > driver (the actual driver for the eLCDIF block).
> So I wanted to test this but with both my somewhat cleaned up nwl
> driver¹ and the nwl driver forward ported from the nxp vendor tree
> I'm
> looking at a black screen with current mainline - while my dcss
> forward
> port gives me nice output on mipi dsi. Do you have a tree that uses
> mipi
> dsi on imx8mq where I could look at to check for differences?
Somewhere on the pixel path (between the display controller and the
DSI) there is a block that inverts the polarity. I can't remember
exactly what was the role of this block, but the polarity is inverted
when eLCDIF is used in combination with the DSI.
If you take a look at my DSI driver from NXP releases (I guess you have
them), you will see there is a hack in mode_fixup:

unsigned int *flags = >flags;
if (dsi->sync_pol {
*flags |= DRM_MODE_FLAG_PHSYNC;
*flags |= DRM_MODE_FLAG_PVSYNC;
*flags &= ~DRM_MODE_FLAG_NHSYNC;
*flags &= ~DRM_MODE_FLAG_NVSYNC;
} else {
*flags &= ~DRM_MODE_FLAG_PHSYNC;
*flags &= ~DRM_MODE_FLAG_PVSYNC;
*flags |= DRM_MODE_FLAG_NHSYNC;
*flags |= DRM_MODE_FLAG_NVSYNC;
}

I know it's not clean, but it works for now. You can try this in your
driver and see if it helps.
These days I will also take your nwl-dsi driver and test it, and also
add support for bridge and eLCDIF to see if I can make it work.

Best regards,
Robert
> 
> Cheers,
>  -- Guido
> 
> > 
> > 
> > 2. Add support for additional pixel formats
> > Some of the pixel formats needed by Android were not implemented in
> > this
> > driver, but they were actually supported. So, add support for them.
> > 
> > 3. Add support for horizontal stride
> > Having support for horizontal stride allows the use of eLCDIF with
> > a GPU
> > (for example) that can only output resolution sizes multiple of a
> > power of
> > 8. For example, 1080 is not a power of 16, so in order to support
> > 1920x1080
> > output from GPUs that can produce linear buffers only in sizes
> > multiple to 16,
> > this feature is needed.
> > 
> > 3. Few minor features and bug-fixing
> > The addition of max-res DT property was actually needed in order to
> > limit
> > the bandwidth usage of the eLCDIF block. This is need on systems
> > where
> > multiple display controllers are presend and the memory bandwidth
> > is not
> > enough to handle all of them at maximum capacity (like it is the
> > case on
> > 8MQ, where there are two display controllers: DCSS and eLCDIF).
> > The rest of the patches are bug-fixes.
> > 
> > Mirela Rabulea (1):
> >   drm/mxsfb: Signal mode changed when bpp changed
> > 
> > Robert Chiras (9):
> >   drm/mxsfb: Update mxsfb to support a bridge
> >   drm/mxsfb: Update mxsfb with additional pixel formats
> >   drm/mxsfb: Fix the vblank events
> >   dt-bindings: display: Add max-res property for mxsfb
> >   drm/mxsfb: Add max-res property for MXSFB
> >   drm/mxsfb: Update mxsfb to support LCD reset
> >   drm/mxsfb: Improve the axi clock usage
> >   drm/mxsfb: Clear OUTSTANDING_REQS bits
> >   drm/mxsfb: Add support for horizontal stride
> > 
> >  .../devicetree/bindings/display/mxsfb.txt  |   6 +
> >  drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 290
> > ++---
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 189
> > +++---
> >  drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  10 +-
> >  drivers/gpu/drm/mxsfb/mxsfb_out.c  |  26 +-
> >  drivers/gpu/drm/mxsfb/mxsfb_regs.h | 128 ++---
> >  6 files changed, 531 insertions(+), 118 deletions(-)
> > 
> > --
> &

[PATCH 06/10] drm/mxsfb: Add max-res property for MXSFB

2019-06-27 Thread Robert Chiras
Because of stability issues, we may want to limit the maximum resolution
supported by the MXSFB (eLCDIF) driver.
This patch add support for a new property which we can use to impose such
limitation.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 64575df..9a1ee70 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -260,6 +260,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
struct platform_device *pdev = to_platform_device(drm->dev);
struct mxsfb_drm_private *mxsfb;
struct resource *res;
+   u32 max_res[2] = {0, 0};
int ret;
 
mxsfb = devm_kzalloc(>dev, sizeof(*mxsfb), GFP_KERNEL);
@@ -340,10 +341,17 @@ static int mxsfb_load(struct drm_device *drm, unsigned 
long flags)
}
}
 
+   of_property_read_u32_array(drm->dev->of_node, "max-res",
+  _res[0], 2);
+   if (!max_res[0])
+   max_res[0] = MXSFB_MAX_XRES;
+   if (!max_res[1])
+   max_res[1] = MXSFB_MAX_YRES;
+
drm->mode_config.min_width  = MXSFB_MIN_XRES;
drm->mode_config.min_height = MXSFB_MIN_YRES;
-   drm->mode_config.max_width  = MXSFB_MAX_XRES;
-   drm->mode_config.max_height = MXSFB_MAX_YRES;
+   drm->mode_config.max_width  = max_res[0];
+   drm->mode_config.max_height = max_res[1];
drm->mode_config.funcs  = _mode_config_funcs;
drm->mode_config.helper_private = _mode_config_helpers;
 
-- 
2.7.4

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

[PATCH 05/10] dt-bindings: display: Add max-res property for mxsfb

2019-06-27 Thread Robert Chiras
Add new optional property 'max-res', to limit the maximum supported
resolution by the MXSFB_DRM driver.

Signed-off-by: Robert Chiras 
---
 Documentation/devicetree/bindings/display/mxsfb.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt 
b/Documentation/devicetree/bindings/display/mxsfb.txt
index 472e1ea..55e22ed 100644
--- a/Documentation/devicetree/bindings/display/mxsfb.txt
+++ b/Documentation/devicetree/bindings/display/mxsfb.txt
@@ -17,6 +17,12 @@ Required properties:
 Required sub-nodes:
   - port: The connection to an encoder chip.
 
+Optional properties:
+- max-res: an array with a maximum of two integers, representing the
+   maximum supported resolution, in the form of
+   , ; if one of the item is <0>, the default
+   driver-defined maximum resolution for that axis is used
+
 Example:
 
lcdif1: display-controller@222 {
-- 
2.7.4

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

[PATCH 04/10] drm/mxsfb: Signal mode changed when bpp changed

2019-06-27 Thread Robert Chiras
From: Mirela Rabulea 

Add mxsfb_atomic_helper_check to signal mode changed when bpp changed.
This will trigger the execution of disable/enable on
a modeset with different bpp than the current one.

Signed-off-by: Mirela Rabulea 
Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 44 ++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 8d14921..64575df 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -105,9 +105,51 @@ void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+/**
+ * mxsfb_atomic_helper_check - validate state object
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * On top of the drm imlementation drm_atomic_helper_check,
+ * check if the bpp is changed, if so, signal mode_changed,
+ * this will trigger disable/enable
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+static int mxsfb_atomic_helper_check(struct drm_device *dev,
+struct drm_atomic_state *state)
+{
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *new_state;
+   int i, ret;
+
+   ret = drm_atomic_helper_check(dev, state);
+   if (ret)
+   return ret;
+
+   for_each_new_crtc_in_state(state, crtc, new_state, i) {
+   struct drm_plane_state *primary_state;
+   int old_bpp = 0;
+   int new_bpp = 0;
+
+   if (!crtc->primary || !crtc->primary->old_fb)
+   continue;
+   primary_state =
+   drm_atomic_get_plane_state(state, crtc->primary);
+   if (!primary_state || !primary_state->fb)
+   continue;
+   old_bpp = crtc->primary->old_fb->format->depth;
+   new_bpp = primary_state->fb->format->depth;
+   if (old_bpp != new_bpp)
+   new_state->mode_changed = true;
+   }
+   return ret;
+}
+
 static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
.fb_create  = drm_gem_fb_create,
-   .atomic_check   = drm_atomic_helper_check,
+   .atomic_check   = mxsfb_atomic_helper_check,
.atomic_commit  = drm_atomic_helper_commit,
 };
 
-- 
2.7.4

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

[PATCH 07/10] drm/mxsfb: Update mxsfb to support LCD reset

2019-06-26 Thread Robert Chiras
The eLCDIF controller has control pin for the external LCD reset pin.
Add support for it and assert this pin in enable and de-assert it in
disable.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 10 --
 drivers/gpu/drm/mxsfb/mxsfb_regs.h |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index e48396d..d9429fc 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -222,9 +222,12 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
-   if (mxsfb->devdata->ipversion >= 4)
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS__REQ_16,
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   }
 
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
@@ -242,9 +245,12 @@ static void mxsfb_disable_controller(struct 
mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
-   if (mxsfb->devdata->ipversion >= 4)
+   if (mxsfb->devdata->ipversion >= 4) {
writel(CTRL2_OUTSTANDING_REQS(0x7),
   mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+   /* De-assert LCD Reset bit */
+   writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+   }
 
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
 
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h 
b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
index 9ee0d3c7..2583a69 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h
@@ -87,6 +87,7 @@
 #define CTRL2_OUTSTANDING_REQS(x)  REG_PUT((x), 23, 21)
 #define CTRL2_ODD_LINE_PATTERN(x)  REG_PUT((x), 18, 16)
 #define CTRL2_EVEN_LINE_PATTERN(x) REG_PUT((x), 14, 12)
+#define CTRL2_LCD_RESETBIT(0)
 
 #define TRANSFER_COUNT_SET_VCOUNT(x)   (((x) & 0x) << 16)
 #define TRANSFER_COUNT_GET_VCOUNT(x)   (((x) >> 16) & 0x)
-- 
2.7.4



[PATCH 08/10] drm/mxsfb: Improve the axi clock usage

2019-06-26 Thread Robert Chiras
Currently, the enable of the axi clock return status is ignored, causing
issues when the enable fails then we try to disable it. Therefore, it is
better to check the return status and disable it only when enable
succeeded.
Also, remove the helper functions around clk_axi, since we can directly
use the clk API function for enable/disable the clock. Those functions
are already checking for NULL clk and returning 0 if that's the case.

Signed-off-by: Robert Chiras 
Acked-by: Leonard Crestez 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c |  8 
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 32 +---
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  3 ---
 3 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index d9429fc..45ca16b 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -403,7 +403,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 {
dma_addr_t paddr;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
@@ -420,7 +420,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
 void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
 {
mxsfb_disable_controller(mxsfb);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
@@ -448,9 +448,9 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
 
paddr = mxsfb_get_fb_paddr(mxsfb);
if (paddr) {
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
}
 
if (!fb || !old_fb)
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 9a1ee70..a164f4d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -93,18 +93,6 @@ drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe 
*pipe)
return container_of(pipe, struct mxsfb_drm_private, pipe);
 }
 
-void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_prepare_enable(mxsfb->clk_axi);
-}
-
-void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
-{
-   if (mxsfb->clk_axi)
-   clk_disable_unprepare(mxsfb->clk_axi);
-}
-
 /**
  * mxsfb_atomic_helper_check - validate state object
  * @dev: DRM device
@@ -225,25 +213,31 @@ static void mxsfb_pipe_update(struct 
drm_simple_display_pipe *pipe,
 static int mxsfb_pipe_enable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+   int ret = 0;
+
+   ret = clk_prepare_enable(mxsfb->clk_axi);
+   if (ret)
+   return ret;
 
/* Clear and enable VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
-   return 0;
+   return ret;
 }
 
 static void mxsfb_pipe_disable_vblank(struct drm_simple_display_pipe *pipe)
 {
struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
 
+   if (clk_prepare_enable(mxsfb->clk_axi))
+   return;
+
/* Disable and clear VBLANK IRQ */
-   mxsfb_enable_axi_clk(mxsfb);
writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 }
 
 static struct drm_simple_display_pipe_funcs mxsfb_funcs = {
@@ -409,7 +403,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
struct mxsfb_drm_private *mxsfb = drm->dev_private;
u32 reg;
 
-   mxsfb_enable_axi_clk(mxsfb);
+   clk_prepare_enable(mxsfb->clk_axi);
 
reg = readl(mxsfb->base + LCDC_CTRL1);
 
@@ -418,7 +412,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data)
 
writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
 
-   mxsfb_disable_axi_clk(mxsfb);
+   clk_disable_unprepare(mxsfb->clk_axi);
 
return IRQ_HANDLED;
 }
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.h 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
index 8fb65d3..d6df8fe 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.h
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.h
@@ -37,9 +37,6 @@ struct mxsfb_drm_private {
 int mxsfb_setup_crtc(struct 

[PATCH 10/10] drm/mxsfb: Add support for horizontal stride

2019-06-26 Thread Robert Chiras
Besides the eLCDIF block, there is another IP block, used in the past
for EPDC panels. Since the iMX.8mq doesn't have an EPDC connector, this
block is not documented, but we can use it to do additional operations
on the frame buffer.
In this case, we can use the pigeon registers from this IP block in
order to do horizontal crop on the frame buffer processed by the eLCDIF
block.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 79 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 26 -
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 16 
 3 files changed, 113 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 02a5684..712494e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -9,6 +9,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -430,15 +431,67 @@ void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+void mxsfb_set_fb_hcrop(struct mxsfb_drm_private *mxsfb, u32 src_w, u32 fb_w)
+{
+   u32 mask_cnt, htotal, hcount;
+   u32 vdctrl2, vdctrl3, vdctrl4, transfer_count;
+   u32 pigeon_12_0, pigeon_12_1, pigeon_12_2;
+
+   if (src_w == fb_w) {
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+   writel(0x0, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   return;
+   }
+
+   transfer_count = readl(mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+   hcount = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+
+   transfer_count &= ~TRANSFER_COUNT_SET_HCOUNT(0x);
+   transfer_count |= TRANSFER_COUNT_SET_HCOUNT(fb_w);
+   writel(transfer_count, mxsfb->base + LCDC_V4_TRANSFER_COUNT);
+
+   vdctrl2 = readl(mxsfb->base + LCDC_VDCTRL2);
+   htotal  = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2);
+   htotal  += fb_w - hcount;
+   vdctrl2 &= ~VDCTRL2_SET_HSYNC_PERIOD(0x3);
+   vdctrl2 |= VDCTRL2_SET_HSYNC_PERIOD(htotal);
+   writel(vdctrl2, mxsfb->base + LCDC_VDCTRL2);
+
+   vdctrl4 = readl(mxsfb->base + LCDC_VDCTRL4);
+   vdctrl4 &= ~SET_DOTCLK_H_VALID_DATA_CNT(0x3);
+   vdctrl4 |= SET_DOTCLK_H_VALID_DATA_CNT(fb_w);
+   writel(vdctrl4, mxsfb->base + LCDC_VDCTRL4);
+
+   /* configure related pigeon registers */
+   vdctrl3  = readl(mxsfb->base + LCDC_VDCTRL3);
+   mask_cnt = GET_HOR_WAIT_CNT(vdctrl3) - 5;
+
+   pigeon_12_0 = PIGEON_12_0_SET_STATE_MASK(0x24)  |
+ PIGEON_12_0_SET_MASK_CNT(mask_cnt)|
+ PIGEON_12_0_SET_MASK_CNT_SEL(0x6) |
+ PIGEON_12_0_POL_ACTIVE_LOW|
+ PIGEON_12_0_EN;
+   writel(pigeon_12_0, mxsfb->base + HW_EPDC_PIGEON_12_0);
+
+   pigeon_12_1 = PIGEON_12_1_SET_CLR_CNT(src_w) |
+ PIGEON_12_1_SET_SET_CNT(0x0);
+   writel(pigeon_12_1, mxsfb->base + HW_EPDC_PIGEON_12_1);
+
+   pigeon_12_2 = 0x0;
+   writel(pigeon_12_2, mxsfb->base + HW_EPDC_PIGEON_12_2);
+}
+
 void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
   struct drm_plane_state *old_state)
 {
struct drm_simple_display_pipe *pipe = >pipe;
struct drm_crtc *crtc = >crtc;
+   struct drm_plane_state *state = pipe->plane.state;
struct drm_framebuffer *fb = pipe->plane.state->fb;
struct drm_framebuffer *old_fb = old_state->fb;
struct drm_pending_vblank_event *event;
-   dma_addr_t paddr;
+   u32 fb_addr, src_off, src_w, stride, cpp = 0;
 
spin_lock_irq(>dev->event_lock);
event = crtc->state->event;
@@ -453,15 +506,29 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
}
spin_unlock_irq(>dev->event_lock);
 
-   paddr = mxsfb_get_fb_paddr(mxsfb);
-   if (paddr) {
+   if (!fb || !old_fb)
+   return;
+
+   fb_addr = mxsfb_get_fb_paddr(mxsfb);
+   if (mxsfb->devdata->ipversion >= 4) {
+   cpp = fb->format->cpp[0];
+   src_off = (state->src_y >> 16) * fb->pitches[0] +
+ (state->src_x >> 16) * cpp;
+   fb_addr += fb->offsets[0] + src_off;
+   }
+
+   if (fb_addr) {
clk_prepare_enable(mxsfb->clk_axi);
-   writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
+   writel(fb_addr, mxsfb->base + mxsfb->devdata->next_buf);
clk_disable_unprepare(mxsfb->clk_axi);
}
 
-   if (!fb || !old_fb)
-   return;
+   if (mxsfb->devdata->ipversion >= 4 &&
+   unlikely(drm_atomic_crtc_needs_modeset(state->crtc->state))) {
+   stride = DIV_ROUND_UP(fb->pitches[0]

[PATCH 00/10] Improvements and fixes for mxsfb DRM driver

2019-06-26 Thread Robert Chiras
This patch-set improves the use of eLCDIF block on iMX 8 SoCs (like 8MQ, 8MM
and 8QXP). Following, are the new features added and fixes from this
patch-set:

1. Add support for drm_bridge
On 8MQ and 8MM, the LCDIF block is not directly connected to a parallel
display connector, where an LCD panel can be attached, but instead it is
connected to DSI controller. Since this DSI stands between the display
controller (eLCDIF) and the physical connector, the DSI can be implemented
as a DRM bridge. So, in order to be able to connect the mxsfb driver to
the DSI driver, the support for a drm_bridge was needed in mxsfb DRM
driver (the actual driver for the eLCDIF block).

2. Add support for additional pixel formats
Some of the pixel formats needed by Android were not implemented in this
driver, but they were actually supported. So, add support for them.

3. Add support for horizontal stride
Having support for horizontal stride allows the use of eLCDIF with a GPU
(for example) that can only output resolution sizes multiple of a power of
8. For example, 1080 is not a power of 16, so in order to support 1920x1080
output from GPUs that can produce linear buffers only in sizes multiple to 16,
this feature is needed.

3. Few minor features and bug-fixing
The addition of max-res DT property was actually needed in order to limit
the bandwidth usage of the eLCDIF block. This is need on systems where
multiple display controllers are presend and the memory bandwidth is not
enough to handle all of them at maximum capacity (like it is the case on
8MQ, where there are two display controllers: DCSS and eLCDIF).
The rest of the patches are bug-fixes.

Mirela Rabulea (1):
  drm/mxsfb: Signal mode changed when bpp changed

Robert Chiras (9):
  drm/mxsfb: Update mxsfb to support a bridge
  drm/mxsfb: Update mxsfb with additional pixel formats
  drm/mxsfb: Fix the vblank events
  dt-bindings: display: Add max-res property for mxsfb
  drm/mxsfb: Add max-res property for MXSFB
  drm/mxsfb: Update mxsfb to support LCD reset
  drm/mxsfb: Improve the axi clock usage
  drm/mxsfb: Clear OUTSTANDING_REQS bits
  drm/mxsfb: Add support for horizontal stride

 .../devicetree/bindings/display/mxsfb.txt  |   6 +
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 290 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 189 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  10 +-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  |  26 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 128 ++---
 6 files changed, 531 insertions(+), 118 deletions(-)

-- 
2.7.4



[PATCH 02/10] drm/mxsfb: Update mxsfb with additional pixel formats

2019-06-26 Thread Robert Chiras
Since version 4 of eLCDIF, there are some registers that can do
transformations on the input data, like re-arranging the pixel
components. By doing that, we can support more pixel formats.
This patch adds support for X/ABGR and RGBX/A. Although, the local alpha
is not supported by eLCDIF, the alpha pixel formats were added to the
supported pixel formats but it will be ignored. This was necessary since
there are systems (like Android) that requires such pixel formats.

Also, add support for the following pixel formats:
16 bpp: RG16 ,BG16, XR15, XB15, AR15, AB15
Set the bus format based on input from the user and panel capabilities.
Save the bus format in crtc->mode.private_flags, so the bridge can use
it.

Signed-off-by: Robert Chiras 
Signed-off-by: Mirela Rabulea 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 158 ++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  |  30 +--
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |   3 +-
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 100 ++-
 4 files changed, 217 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 14bde024..e48396d 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -41,14 +41,17 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private 
*mxsfb, u32 val)
 }
 
 /* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
-static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb, bool update)
 {
struct drm_crtc *crtc = >pipe.crtc;
struct drm_device *drm = crtc->dev;
const u32 format = crtc->primary->state->fb->format->format;
-   u32 ctrl, ctrl1;
+   u32 ctrl = 0, ctrl1 = 0;
+   bool bgr_format = true;
+   struct drm_format_name_buf format_name_buf;
 
-   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
+   if (!update)
+   ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
 
/*
 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
@@ -57,64 +60,158 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private 
*mxsfb)
 * to arbitrary value. This limitation should not pose an issue.
 */
 
-   /* CTRL1 contains IRQ config and status bits, preserve those. */
-   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
-   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   if (!update) {
+   /* CTRL1 contains IRQ config and status bits, preserve those. */
+   ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
+   ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+   }
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Setting up %s mode\n",
+drm_get_format_name(format, _name_buf));
+
+   /* Do some clean-up that we might have from a previous mode */
+   ctrl &= ~CTRL_SHIFT_DIR(1);
+   ctrl &= ~CTRL_SHIFT_NUM(0x3f);
+   if (mxsfb->devdata->ipversion >= 4)
+   writel(CTRL2_ODD_LINE_PATTERN(0x7) |
+  CTRL2_EVEN_LINE_PATTERN(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
 
switch (format) {
-   case DRM_FORMAT_RGB565:
-   dev_dbg(drm->dev, "Setting up RGB565 mode\n");
+   case DRM_FORMAT_BGR565: /* BG16 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(0x5) |
+   CTRL2_EVEN_LINE_PATTERN(0x5),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_RGB565: /* RG16 */
+   ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl &= ~CTRL_DF16;
+   ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
+   break;
+   case DRM_FORMAT_XBGR1555: /* XB15 */
+   case DRM_FORMAT_ABGR1555: /* AB15 */
+   if (mxsfb->devdata->ipversion < 4)
+   goto err;
+   writel(CTRL2_ODD_LINE_PATTERN(0x5) |
+   CTRL2_EVEN_LINE_PATTERN(0x5),
+   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+   /* Fall through */
+   case DRM_FORMAT_XRGB1555: /* XR15 */
+   case DRM_FORMAT_ARGB1555: /* AR15 */
ctrl |= CTRL_SET_WORD_LENGTH(0);
+   ctrl |= CTRL_DF16;
ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
break;
-   case DRM_FORMAT_XRGB:
-   dev_dbg(drm->dev, "Setting up XRGB mode\n");
+   case DRM_FORMAT_RGBX: /* RX24 */
+   case DRM_FORMAT_RGBA: /* RA24 */
+   /* RGBX - > 0RGB */
+   ctrl |= CTRL_SHIFT_DIR(1);
+   ctrl |= CTRL_SHIFT_NUM(8);
+   bgr_

[PATCH 09/10] drm/mxsfb: Clear OUTSTANDING_REQS bits

2019-06-26 Thread Robert Chiras
Bit 21 can alter the CTRL2_OUTSTANDING_REQS value right after the eLCDIF
is enabled, since it comes up with default value of 1 (this behaviour
has been seen on some imx8 platforms).
In order to fix this, clear CTRL2_OUTSTANDING_REQS bits before setting
its value.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 45ca16b..02a5684 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -223,7 +223,14 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk);
 
if (mxsfb->devdata->ipversion >= 4) {
-   writel(CTRL2_OUTSTANDING_REQS__REQ_16,
+   /*
+* On some platforms, bit 21 is defaulted to 1, which may alter
+* the below setting. So, to make sure we have the right setting
+* clear all the bits for CTRL2_OUTSTANDING_REQS.
+*/
+   writel(CTRL2_OUTSTANDING_REQS(0x7),
+  mxsfb->base + LCDC_V4_CTRL2 + REG_CLR);
+   writel(CTRL2_OUTSTANDING_REQS(REQ_16),
   mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
/* Assert LCD Reset bit */
writel(CTRL2_LCD_RESET, mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
-- 
2.7.4



[PATCH 03/10] drm/mxsfb: Fix the vblank events

2019-06-26 Thread Robert Chiras
Currently, the vblank support is not correctly implemented in MXSFB_DRM
driver. The call to drm_vblank_init is made with mode_config.num_crtc
which at that time is 0. Because of this, vblank is not activated, so
there won't be any vblank event submitted.
For example, when running modetest with the '-v' parameter will result
in an astronomical refresh rate (1+ Hz), because of that.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c 
b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index d9fb734..8d14921 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -35,6 +35,9 @@
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
 
+/* The eLCDIF max possible CRTCs */
+#define MAX_CRTCS 1
+
 enum mxsfb_devtype {
MXSFB_V3,
MXSFB_V4,
@@ -135,6 +138,8 @@ static void mxsfb_pipe_enable(struct 
drm_simple_display_pipe *pipe,
mxsfb->connector = >panel_connector;
}
 
+   drm_crtc_vblank_on(>crtc);
+
pm_runtime_get_sync(drm->dev);
drm_panel_prepare(mxsfb->panel);
mxsfb_crtc_enable(mxsfb);
@@ -161,6 +166,8 @@ static void mxsfb_pipe_disable(struct 
drm_simple_display_pipe *pipe)
}
spin_unlock_irq(>event_lock);
 
+   drm_crtc_vblank_off(>crtc);
+
if (mxsfb->connector != >panel_connector)
mxsfb->connector = NULL;
 }
@@ -243,7 +250,7 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
 
pm_runtime_enable(drm->dev);
 
-   ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+   ret = drm_vblank_init(drm, MAX_CRTCS);
if (ret < 0) {
dev_err(drm->dev, "Failed to initialise vblank\n");
goto err_vblank;
@@ -266,6 +273,8 @@ static int mxsfb_load(struct drm_device *drm, unsigned long 
flags)
goto err_vblank;
}
 
+   drm_crtc_vblank_off(>pipe.crtc);
+
/*
 * Attach panel only if there is one.
 * If there is no panel attach, it must be a bridge. In this case, we
-- 
2.7.4



[PATCH 01/10] drm/mxsfb: Update mxsfb to support a bridge

2019-06-26 Thread Robert Chiras
Currently, the MXSFB DRM driver only supports a panel. But, its output
display signal can also be redirected to another encoder, like a DSI
controller. In this case, that DSI controller may act like a drm_bridge.
In order support this use-case too, this patch adds support for
drm_bridge in mxsfb.

Signed-off-by: Robert Chiras 
---
 drivers/gpu/drm/mxsfb/mxsfb_crtc.c | 46 +++---
 drivers/gpu/drm/mxsfb/mxsfb_drv.c  | 46 +-
 drivers/gpu/drm/mxsfb/mxsfb_drv.h  |  4 +++-
 drivers/gpu/drm/mxsfb/mxsfb_out.c  | 26 +++--
 drivers/gpu/drm/mxsfb/mxsfb_regs.h | 15 +
 5 files changed, 116 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c 
b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
index 93f4133..14bde024 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
@@ -93,8 +93,11 @@ static void mxsfb_set_bus_fmt(struct mxsfb_drm_private 
*mxsfb)
 
reg = readl(mxsfb->base + LCDC_CTRL);
 
-   if (mxsfb->connector.display_info.num_bus_formats)
-   bus_format = mxsfb->connector.display_info.bus_formats[0];
+   if (mxsfb->connector->display_info.num_bus_formats)
+   bus_format = mxsfb->connector->display_info.bus_formats[0];
+
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
+bus_format);
 
reg &= ~CTRL_BUS_WIDTH_MASK;
switch (bus_format) {
@@ -122,6 +125,9 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
clk_prepare_enable(mxsfb->clk_disp_axi);
clk_prepare_enable(mxsfb->clk);
 
+   writel(CTRL2_OUTSTANDING_REQS__REQ_16,
+  mxsfb->base + LCDC_V4_CTRL2 + REG_SET);
+
/* If it was disabled, re-enable the mode again */
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
 
@@ -131,12 +137,15 @@ static void mxsfb_enable_controller(struct 
mxsfb_drm_private *mxsfb)
writel(reg, mxsfb->base + LCDC_VDCTRL4);
 
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+   writel(CTRL1_RECOVERY_ON_UNDERFLOW, mxsfb->base + LCDC_CTRL1 + REG_SET);
 }
 
 static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
 {
u32 reg;
 
+   writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_CLR);
+
/*
 * Even if we disable the controller here, it will still continue
 * until its FIFOs are running out of data
@@ -202,8 +211,9 @@ static dma_addr_t mxsfb_get_fb_paddr(struct 
mxsfb_drm_private *mxsfb)
 
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
+   struct drm_device *drm = mxsfb->pipe.crtc.dev;
struct drm_display_mode *m = >pipe.crtc.state->adjusted_mode;
-   const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+   const u32 bus_flags = mxsfb->connector->display_info.bus_flags;
u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
int err;
 
@@ -227,6 +237,13 @@ static void mxsfb_crtc_mode_set_nofb(struct 
mxsfb_drm_private *mxsfb)
 
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
 
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
+m->crtc_clock,
+(int)(clk_get_rate(mxsfb->clk) / 1000));
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
+bus_flags);
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
+
writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
   TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
   mxsfb->base + mxsfb->devdata->transfer_count);
@@ -279,6 +296,7 @@ void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
dma_addr_t paddr;
 
mxsfb_enable_axi_clk(mxsfb);
+   writel(0, mxsfb->base + LCDC_CTRL);
mxsfb_crtc_mode_set_nofb(mxsfb);
 
/* Write cur_buf as well to avoid an initial corrupt frame */
@@ -302,6 +320,8 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
 {
struct drm_simple_display_pipe *pipe = >pipe;
struct drm_crtc *crtc = >crtc;
+   struct drm_framebuffer *fb = pipe->plane.state->fb;
+   struct drm_framebuffer *old_fb = old_state->fb;
struct drm_pending_vblank_event *event;
dma_addr_t paddr;
 
@@ -324,4 +344,24 @@ void mxsfb_plane_atomic_update(struct mxsfb_drm_private 
*mxsfb,
writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
mxsfb_disable_axi_clk(mxsfb);
}
+
+   if (!fb || !old_fb)
+   return;
+
+   /*
+* TODO: Currently, we only support pixel format change, but we need
+* also to care about size changes too
+ 

Re: [EXT] Re: [PATCH v5 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-26 Thread Robert Chiras
Hi Sam,

On Mi, 2019-06-26 at 13:33 +0200, Sam Ravnborg wrote:
> Hi Robert.
> 
> On Wed, Jun 26, 2019 at 01:20:20PM +0300, Robert Chiras wrote:
> > 
> > This patch adds Raydium RM67191 TFT LCD panel driver (MIPI-DSI
> > protocol).
> I was about to apply these - but I get following warnings during
> build:
>   CC  drivers/gpu/drm/panel/panel-raydium-rm67191.o
> /home/sam/drm/linux.git/drivers/gpu/drm/panel/panel-raydium-
> rm67191.c: In function ‘rad_bl_get_brightness’:
> /home/sam/drm/linux.git/drivers/gpu/drm/panel/panel-raydium-
> rm67191.c:470:17: warning: unused variable ‘dev’ [-Wunused-variable]
>   struct device *dev = >dev;
>  ^~~
> /home/sam/drm/linux.git/drivers/gpu/drm/panel/panel-raydium-
> rm67191.c: In function ‘rad_bl_update_status’:
> /home/sam/drm/linux.git/drivers/gpu/drm/panel/panel-raydium-
> rm67191.c:492:17: warning: unused variable ‘dev’ [-Wunused-variable]
>   struct device *dev = >dev;
>  ^~~
> 
> Please fix and update your scripts to catch this in the future.
Oh, I am sorry about that, seems that I missed that :(
Fixed and submitted.
> 
> Sam

Thanks,
Robert

[PATCH v6 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-26 Thread Robert Chiras
Add dt-bindings documentation for Raydium RM67191 DSI panel.

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
Reviewed-by: Fabio Estevam 
---
 .../bindings/display/panel/raydium,rm67191.txt | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt 
b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
new file mode 100644
index 000..1042469
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
@@ -0,0 +1,41 @@
+Raydium RM67171 OLED LCD panel with MIPI-DSI protocol
+
+Required properties:
+- compatible:  "raydium,rm67191"
+- reg: virtual channel for MIPI-DSI protocol
+   must be <0>
+- dsi-lanes:   number of DSI lanes to be used
+   must be <3> or <4>
+- port:input port node with endpoint definition as
+   defined in Documentation/devicetree/bindings/graph.txt;
+   the input port should be connected to a MIPI-DSI device
+   driver
+
+Optional properties:
+- reset-gpios: a GPIO spec for the RST_B GPIO pin
+- v3p3-supply: phandle to 3.3V regulator that powers the VDD_3V3 pin
+- v1p8-supply: phandle to 1.8V regulator that powers the VDD_1V8 pin
+- width-mm:see panel-common.txt
+- height-mm:   see panel-common.txt
+- video-mode:  0 - burst-mode
+   1 - non-burst with sync event
+   2 - non-burst with sync pulse
+
+Example:
+
+   panel@0 {
+   compatible = "raydium,rm67191";
+   reg = <0>;
+   pinctrl-0 = <_mipi_dsi_0_1_en>;
+   pinctrl-names = "default";
+   reset-gpios = < 7 GPIO_ACTIVE_LOW>;
+   dsi-lanes = <4>;
+   width-mm = <68>;
+   height-mm = <121>;
+
+   port {
+   panel_in: endpoint {
+   remote-endpoint = <_out>;
+   };
+   };
+   };
-- 
2.7.4



[PATCH v6 0/2] Add DSI panel driver for Raydium RM67191

2019-06-26 Thread Robert Chiras
This patch-set contains the DRM panel driver and dt-bindings documentation
for the DSI driven panel: Raydium RM67191.

v6:
- Collected Reviewed-by from Fabio
- Removed unused variables (sam)

v5:
- Removed unnecessary debug messages (fabio)
- Handled error case for gpio pin (fabio)

v4:
- Changed default_timing structure type from 'struct display_timing' to
  'struct drm_display_mode' (fabio)
- Replaced devm_gpiod_get with devm_gpiod_get_optional (fabio)
- Added power regulators (fabio)
- Removed pm_ops (fabio)

v3:
- Added myself to MAINTAINERS for this driver (sam)
- Removed display-timings property (fabio)
- Fixed dt description (sam)
- Re-arranged calls inside get_modes function (sam)
- Changed ifdefs with _maybe_unused for suspend/resume functions (sam)
- Collected Reviewed-by from Sam

v2:
- Fixed 'reset-gpio' to 'reset-gpios' property naming (fabio)
- Changed the state of the reset gpio to active low and fixed how it is
  handled in driver (fabio)
- Fixed copyright statement (daniel)
- Reordered includes (sam)
- Added defines for panel specific color formats (fabio)
- Removed unnecessary tests in enable and unprepare (sam)
- Removed the unnecessary backlight write in enable (sam)
*** SUBJECT HERE ***

*** BLURB HERE ***

Robert Chiras (2):
  dt-bindings: display: panel: Add support for Raydium RM67191 panel
  drm/panel: Add support for Raydium RM67191 panel driver

 .../bindings/display/panel/raydium,rm67191.txt |  41 ++
 MAINTAINERS|   6 +
 drivers/gpu/drm/panel/Kconfig  |   9 +
 drivers/gpu/drm/panel/Makefile |   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c  | 668 +
 5 files changed, 725 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

-- 
2.7.4



[PATCH v6 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-26 Thread Robert Chiras
This patch adds Raydium RM67191 TFT LCD panel driver (MIPI-DSI
protocol).

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
Reviewed-by: Fabio Estevam 
---
 MAINTAINERS   |   6 +
 drivers/gpu/drm/panel/Kconfig |   9 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 668 ++
 4 files changed, 684 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d660071..bf17f83 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5101,6 +5101,12 @@ S:   Maintained
 F: drivers/gpu/drm/qxl/
 F: include/uapi/drm/qxl_drm.h
 
+DRM DRIVER FOR RAYDIUM RM67191 PANELS
+M: Robert Chiras 
+S: Maintained
+F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
+F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
+
 DRM DRIVER FOR RAGE 128 VIDEO CARDS
 S: Orphan / Obsolete
 F: drivers/gpu/drm/r128/
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index d9d931a..8be1ac1 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -159,6 +159,15 @@ config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
  Pi 7" Touchscreen.  To compile this driver as a module,
  choose M here.
 
+config DRM_PANEL_RAYDIUM_RM67191
+   tristate "Raydium RM67191 FHD 1080x1920 DSI video mode panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Raydium RM67191 FHD
+ (1080x1920) DSI panel.
+
 config DRM_PANEL_RAYDIUM_RM68200
tristate "Raydium RM68200 720x1280 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index fb0cb3a..1fc0f68 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += 
panel-orisetech-otm8009a.o
 obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
 obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += 
panel-raspberrypi-touchscreen.o
+obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
new file mode 100644
index 000..6a5d370
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -0,0 +1,668 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Raydium RM67191 MIPI-DSI panel driver
+ *
+ * Copyright 2019 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* Panel specific color-format bits */
+#define COL_FMT_16BPP 0x55
+#define COL_FMT_18BPP 0x66
+#define COL_FMT_24BPP 0x77
+
+/* Write Manufacture Command Set Control */
+#define WRMAUCCTR 0xFE
+
+/* Manufacturer Command Set pages (CMD2) */
+struct cmd_set_entry {
+   u8 cmd;
+   u8 param;
+};
+
+/*
+ * There is no description in the Reference Manual about these commands.
+ * We received them from vendor, so just use them as is.
+ */
+static const struct cmd_set_entry manufacturer_cmd_set[] = {
+   {0xFE, 0x0B},
+   {0x28, 0x40},
+   {0x29, 0x4F},
+   {0xFE, 0x0E},
+   {0x4B, 0x00},
+   {0x4C, 0x0F},
+   {0x4D, 0x20},
+   {0x4E, 0x40},
+   {0x4F, 0x60},
+   {0x50, 0xA0},
+   {0x51, 0xC0},
+   {0x52, 0xE0},
+   {0x53, 0xFF},
+   {0xFE, 0x0D},
+   {0x18, 0x08},
+   {0x42, 0x00},
+   {0x08, 0x41},
+   {0x46, 0x02},
+   {0x72, 0x09},
+   {0xFE, 0x0A},
+   {0x24, 0x17},
+   {0x04, 0x07},
+   {0x1A, 0x0C},
+   {0x0F, 0x44},
+   {0xFE, 0x04},
+   {0x00, 0x0C},
+   {0x05, 0x08},
+   {0x06, 0x08},
+   {0x08, 0x08},
+   {0x09, 0x08},
+   {0x0A, 0xE6},
+   {0x0B, 0x8C},
+   {0x1A, 0x12},
+   {0x1E, 0xE0},
+   {0x29, 0x93},
+   {0x2A, 0x93},
+   {0x2F, 0x02},
+   {0x31, 0x02},
+   {0x33, 0x05},
+   {0x37, 0x2D},
+   {0x38, 0x2D},
+   {0x3A, 0x1E},
+   {0x3B, 0x1E},
+   {0x3D, 0x27},
+   {0x3F, 0x80},
+   {0x40, 0x40},
+   {0x41, 0xE0},
+   {0x4F, 0x2F},
+   {0x50, 0x1E},
+   {0xFE, 0x06},
+   {0x00, 0xCC},
+   {0x05, 0x05},
+   {0x07, 0xA2},
+   {0x08, 0xCC},
+   {0x0D, 0x03},
+   {0x0F, 0xA2},
+   {0x32, 0xCC},
+   {0x37, 0x05},
+   {0x39, 0x83},
+   {0x3A, 0xCC},
+   {0x41, 0x04},
+   {0

[PATCH v5 0/2] Add DSI panel driver for Raydium RM67191

2019-06-26 Thread Robert Chiras
This patch-set contains the DRM panel driver and dt-bindings documentation
for the DSI driven panel: Raydium RM67191.

v5:
- Removed unnecessary debug messages (fabio)
- Handled error case for gpio pin (fabio)

v4:
- Changed default_timing structure type from 'struct display_timing' to
  'struct drm_display_mode' (fabio)
- Replaced devm_gpiod_get with devm_gpiod_get_optional (fabio)
- Added power regulators (fabio)
- Removed pm_ops (fabio)

v3:
- Added myself to MAINTAINERS for this driver (sam)
- Removed display-timings property (fabio)
- Fixed dt description (sam)
- Re-arranged calls inside get_modes function (sam)
- Changed ifdefs with _maybe_unused for suspend/resume functions (sam)
- Collected Reviewed-by from Sam

v2:
- Fixed 'reset-gpio' to 'reset-gpios' property naming (fabio)
- Changed the state of the reset gpio to active low and fixed how it is
  handled in driver (fabio)
- Fixed copyright statement (daniel)
- Reordered includes (sam)
- Added defines for panel specific color formats (fabio)
- Removed unnecessary tests in enable and unprepare (sam)
- Removed the unnecessary backlight write in enable (sam)

Robert Chiras (2):
  dt-bindings: display: panel: Add support for Raydium RM67191 panel
  drm/panel: Add support for Raydium RM67191 panel driver

 .../bindings/display/panel/raydium,rm67191.txt |  41 ++
 MAINTAINERS|   6 +
 drivers/gpu/drm/panel/Kconfig  |   9 +
 drivers/gpu/drm/panel/Makefile |   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c  | 670 +
 5 files changed, 727 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

-- 
2.7.4



[PATCH v5 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-26 Thread Robert Chiras
Add dt-bindings documentation for Raydium RM67191 DSI panel.

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
---
 .../bindings/display/panel/raydium,rm67191.txt | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt 
b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
new file mode 100644
index 000..1042469
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
@@ -0,0 +1,41 @@
+Raydium RM67171 OLED LCD panel with MIPI-DSI protocol
+
+Required properties:
+- compatible:  "raydium,rm67191"
+- reg: virtual channel for MIPI-DSI protocol
+   must be <0>
+- dsi-lanes:   number of DSI lanes to be used
+   must be <3> or <4>
+- port:input port node with endpoint definition as
+   defined in Documentation/devicetree/bindings/graph.txt;
+   the input port should be connected to a MIPI-DSI device
+   driver
+
+Optional properties:
+- reset-gpios: a GPIO spec for the RST_B GPIO pin
+- v3p3-supply: phandle to 3.3V regulator that powers the VDD_3V3 pin
+- v1p8-supply: phandle to 1.8V regulator that powers the VDD_1V8 pin
+- width-mm:see panel-common.txt
+- height-mm:   see panel-common.txt
+- video-mode:  0 - burst-mode
+   1 - non-burst with sync event
+   2 - non-burst with sync pulse
+
+Example:
+
+   panel@0 {
+   compatible = "raydium,rm67191";
+   reg = <0>;
+   pinctrl-0 = <_mipi_dsi_0_1_en>;
+   pinctrl-names = "default";
+   reset-gpios = < 7 GPIO_ACTIVE_LOW>;
+   dsi-lanes = <4>;
+   width-mm = <68>;
+   height-mm = <121>;
+
+   port {
+   panel_in: endpoint {
+   remote-endpoint = <_out>;
+   };
+   };
+   };
-- 
2.7.4



[PATCH v5 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-26 Thread Robert Chiras
This patch adds Raydium RM67191 TFT LCD panel driver (MIPI-DSI
protocol).

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
---
 MAINTAINERS   |   6 +
 drivers/gpu/drm/panel/Kconfig |   9 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 670 ++
 4 files changed, 686 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a2f487..cd93030e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5089,6 +5089,12 @@ S:   Maintained
 F: drivers/gpu/drm/qxl/
 F: include/uapi/drm/qxl_drm.h
 
+DRM DRIVER FOR RAYDIUM RM67191 PANELS
+M: Robert Chiras 
+S: Maintained
+F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
+F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
+
 DRM DRIVER FOR RAGE 128 VIDEO CARDS
 S: Orphan / Obsolete
 F: drivers/gpu/drm/r128/
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index d9d931a..8be1ac1 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -159,6 +159,15 @@ config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
  Pi 7" Touchscreen.  To compile this driver as a module,
  choose M here.
 
+config DRM_PANEL_RAYDIUM_RM67191
+   tristate "Raydium RM67191 FHD 1080x1920 DSI video mode panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Raydium RM67191 FHD
+ (1080x1920) DSI panel.
+
 config DRM_PANEL_RAYDIUM_RM68200
tristate "Raydium RM68200 720x1280 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index fb0cb3a..1fc0f68 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += 
panel-orisetech-otm8009a.o
 obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
 obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += 
panel-raspberrypi-touchscreen.o
+obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
new file mode 100644
index 000..0773002
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -0,0 +1,670 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Raydium RM67191 MIPI-DSI panel driver
+ *
+ * Copyright 2019 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* Panel specific color-format bits */
+#define COL_FMT_16BPP 0x55
+#define COL_FMT_18BPP 0x66
+#define COL_FMT_24BPP 0x77
+
+/* Write Manufacture Command Set Control */
+#define WRMAUCCTR 0xFE
+
+/* Manufacturer Command Set pages (CMD2) */
+struct cmd_set_entry {
+   u8 cmd;
+   u8 param;
+};
+
+/*
+ * There is no description in the Reference Manual about these commands.
+ * We received them from vendor, so just use them as is.
+ */
+static const struct cmd_set_entry manufacturer_cmd_set[] = {
+   {0xFE, 0x0B},
+   {0x28, 0x40},
+   {0x29, 0x4F},
+   {0xFE, 0x0E},
+   {0x4B, 0x00},
+   {0x4C, 0x0F},
+   {0x4D, 0x20},
+   {0x4E, 0x40},
+   {0x4F, 0x60},
+   {0x50, 0xA0},
+   {0x51, 0xC0},
+   {0x52, 0xE0},
+   {0x53, 0xFF},
+   {0xFE, 0x0D},
+   {0x18, 0x08},
+   {0x42, 0x00},
+   {0x08, 0x41},
+   {0x46, 0x02},
+   {0x72, 0x09},
+   {0xFE, 0x0A},
+   {0x24, 0x17},
+   {0x04, 0x07},
+   {0x1A, 0x0C},
+   {0x0F, 0x44},
+   {0xFE, 0x04},
+   {0x00, 0x0C},
+   {0x05, 0x08},
+   {0x06, 0x08},
+   {0x08, 0x08},
+   {0x09, 0x08},
+   {0x0A, 0xE6},
+   {0x0B, 0x8C},
+   {0x1A, 0x12},
+   {0x1E, 0xE0},
+   {0x29, 0x93},
+   {0x2A, 0x93},
+   {0x2F, 0x02},
+   {0x31, 0x02},
+   {0x33, 0x05},
+   {0x37, 0x2D},
+   {0x38, 0x2D},
+   {0x3A, 0x1E},
+   {0x3B, 0x1E},
+   {0x3D, 0x27},
+   {0x3F, 0x80},
+   {0x40, 0x40},
+   {0x41, 0xE0},
+   {0x4F, 0x2F},
+   {0x50, 0x1E},
+   {0xFE, 0x06},
+   {0x00, 0xCC},
+   {0x05, 0x05},
+   {0x07, 0xA2},
+   {0x08, 0xCC},
+   {0x0D, 0x03},
+   {0x0F, 0xA2},
+   {0x32, 0xCC},
+   {0x37, 0x05},
+   {0x39, 0x83},
+   {0x3A, 0xCC},
+   {0x41, 0x04},
+   {0x43, 0x83},
+   {0x44, 0

[PATCH v4 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-25 Thread Robert Chiras
Add dt-bindings documentation for Raydium RM67191 DSI panel.

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
---
 .../bindings/display/panel/raydium,rm67191.txt | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt 
b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
new file mode 100644
index 000..1042469
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
@@ -0,0 +1,41 @@
+Raydium RM67171 OLED LCD panel with MIPI-DSI protocol
+
+Required properties:
+- compatible:  "raydium,rm67191"
+- reg: virtual channel for MIPI-DSI protocol
+   must be <0>
+- dsi-lanes:   number of DSI lanes to be used
+   must be <3> or <4>
+- port:input port node with endpoint definition as
+   defined in Documentation/devicetree/bindings/graph.txt;
+   the input port should be connected to a MIPI-DSI device
+   driver
+
+Optional properties:
+- reset-gpios: a GPIO spec for the RST_B GPIO pin
+- v3p3-supply: phandle to 3.3V regulator that powers the VDD_3V3 pin
+- v1p8-supply: phandle to 1.8V regulator that powers the VDD_1V8 pin
+- width-mm:see panel-common.txt
+- height-mm:   see panel-common.txt
+- video-mode:  0 - burst-mode
+   1 - non-burst with sync event
+   2 - non-burst with sync pulse
+
+Example:
+
+   panel@0 {
+   compatible = "raydium,rm67191";
+   reg = <0>;
+   pinctrl-0 = <_mipi_dsi_0_1_en>;
+   pinctrl-names = "default";
+   reset-gpios = < 7 GPIO_ACTIVE_LOW>;
+   dsi-lanes = <4>;
+   width-mm = <68>;
+   height-mm = <121>;
+
+   port {
+   panel_in: endpoint {
+   remote-endpoint = <_out>;
+   };
+   };
+   };
-- 
2.7.4



[PATCH v4 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-25 Thread Robert Chiras
This patch adds Raydium RM67191 TFT LCD panel driver (MIPI-DSI
protocol).

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
---
 MAINTAINERS   |   6 +
 drivers/gpu/drm/panel/Kconfig |   9 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 673 ++
 4 files changed, 689 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a2f487..cd93030e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5089,6 +5089,12 @@ S:   Maintained
 F: drivers/gpu/drm/qxl/
 F: include/uapi/drm/qxl_drm.h
 
+DRM DRIVER FOR RAYDIUM RM67191 PANELS
+M: Robert Chiras 
+S: Maintained
+F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
+F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
+
 DRM DRIVER FOR RAGE 128 VIDEO CARDS
 S: Orphan / Obsolete
 F: drivers/gpu/drm/r128/
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index d9d931a..8be1ac1 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -159,6 +159,15 @@ config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
  Pi 7" Touchscreen.  To compile this driver as a module,
  choose M here.
 
+config DRM_PANEL_RAYDIUM_RM67191
+   tristate "Raydium RM67191 FHD 1080x1920 DSI video mode panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Raydium RM67191 FHD
+ (1080x1920) DSI panel.
+
 config DRM_PANEL_RAYDIUM_RM68200
tristate "Raydium RM68200 720x1280 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index fb0cb3a..1fc0f68 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += 
panel-orisetech-otm8009a.o
 obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
 obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += 
panel-raspberrypi-touchscreen.o
+obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
new file mode 100644
index 000..1735b0f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Raydium RM67191 MIPI-DSI panel driver
+ *
+ * Copyright 2019 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* Panel specific color-format bits */
+#define COL_FMT_16BPP 0x55
+#define COL_FMT_18BPP 0x66
+#define COL_FMT_24BPP 0x77
+
+/* Write Manufacture Command Set Control */
+#define WRMAUCCTR 0xFE
+
+/* Manufacturer Command Set pages (CMD2) */
+struct cmd_set_entry {
+   u8 cmd;
+   u8 param;
+};
+
+/*
+ * There is no description in the Reference Manual about these commands.
+ * We received them from vendor, so just use them as is.
+ */
+static const struct cmd_set_entry manufacturer_cmd_set[] = {
+   {0xFE, 0x0B},
+   {0x28, 0x40},
+   {0x29, 0x4F},
+   {0xFE, 0x0E},
+   {0x4B, 0x00},
+   {0x4C, 0x0F},
+   {0x4D, 0x20},
+   {0x4E, 0x40},
+   {0x4F, 0x60},
+   {0x50, 0xA0},
+   {0x51, 0xC0},
+   {0x52, 0xE0},
+   {0x53, 0xFF},
+   {0xFE, 0x0D},
+   {0x18, 0x08},
+   {0x42, 0x00},
+   {0x08, 0x41},
+   {0x46, 0x02},
+   {0x72, 0x09},
+   {0xFE, 0x0A},
+   {0x24, 0x17},
+   {0x04, 0x07},
+   {0x1A, 0x0C},
+   {0x0F, 0x44},
+   {0xFE, 0x04},
+   {0x00, 0x0C},
+   {0x05, 0x08},
+   {0x06, 0x08},
+   {0x08, 0x08},
+   {0x09, 0x08},
+   {0x0A, 0xE6},
+   {0x0B, 0x8C},
+   {0x1A, 0x12},
+   {0x1E, 0xE0},
+   {0x29, 0x93},
+   {0x2A, 0x93},
+   {0x2F, 0x02},
+   {0x31, 0x02},
+   {0x33, 0x05},
+   {0x37, 0x2D},
+   {0x38, 0x2D},
+   {0x3A, 0x1E},
+   {0x3B, 0x1E},
+   {0x3D, 0x27},
+   {0x3F, 0x80},
+   {0x40, 0x40},
+   {0x41, 0xE0},
+   {0x4F, 0x2F},
+   {0x50, 0x1E},
+   {0xFE, 0x06},
+   {0x00, 0xCC},
+   {0x05, 0x05},
+   {0x07, 0xA2},
+   {0x08, 0xCC},
+   {0x0D, 0x03},
+   {0x0F, 0xA2},
+   {0x32, 0xCC},
+   {0x37, 0x05},
+   {0x39, 0x83},
+   {0x3A, 0xCC},
+   {0x41, 0x04},
+   {0x43, 0x83},
+   {0x44, 0

[PATCH v4 0/2] Add DSI panel driver for Raydium RM67191

2019-06-25 Thread Robert Chiras
This patch-set contains the DRM panel driver and dt-bindings documentation
for the DSI driven panel: Raydium RM67191.

v4:
- Changed default_timing structure type from 'struct display_timing' to
  'struct drm_display_mode' (fabio)
- Replaced devm_gpiod_get with devm_gpiod_get_optional (fabio)
- Added power regulators (fabio)
- Removed pm_ops (fabio)

v3:
- Added myself to MAINTAINERS for this driver (sam)
- Removed display-timings property (fabio)
- Fixed dt description (sam)
- Re-arranged calls inside get_modes function (sam)
- Changed ifdefs with _maybe_unused for suspend/resume functions (sam)
- Collected Reviewed-by from Sam

v2:
- Fixed 'reset-gpio' to 'reset-gpios' property naming (fabio)
- Changed the state of the reset gpio to active low and fixed how it is
  handled in driver (fabio)
- Fixed copyright statement (daniel)
- Reordered includes (sam)
- Added defines for panel specific color formats (fabio)
- Removed unnecessary tests in enable and unprepare (sam)
- Removed the unnecessary backlight write in enable (sam)

Robert Chiras (2):
  dt-bindings: display: panel: Add support for Raydium RM67191 panel
  drm/panel: Add support for Raydium RM67191 panel driver

 .../bindings/display/panel/raydium,rm67191.txt |  41 ++
 MAINTAINERS|   6 +
 drivers/gpu/drm/panel/Kconfig  |   9 +
 drivers/gpu/drm/panel/Makefile |   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c  | 673 +
 5 files changed, 730 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

-- 
2.7.4



Re: [EXT] Re: [PATCH v3 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-25 Thread Robert Chiras
On Lu, 2019-06-24 at 13:12 -0300, Fabio Estevam wrote:
> Caution: EXT Email
> 
> Hi Robert,
> 
> On Mon, Jun 24, 2019 at 4:44 AM Robert Chiras 
> wrote:
> 
> > 
> > > 
> > > You did not handle the "power" regulator.
> > There is no need for a power regulator.
> I am sure the panel requires power to be applied so that it can work
> :-)
Yes, of course there are power lines to the panel. I will add them to
the next revision.
> 
> > 
> > > 
> > > Can't you simply remove them?
> > The reset gpio pin is shared between the DSI display controller and
> Looking at the imx8mq-evk schematics it is not clear for me what pin
> in shared between the OLED display and touch screen.
> 
> Could you please clarify which pin you are referring to?
It's about the DSI_EN pin on the DSI LCD IF physical port J1501. This
goes into RST_B_1V8 on the panel port which is used for both display
and touch resets.
> 
> > 
> > touch controller, both found on the same panel. Since, the touch
> > driver
> > also acceses this gpio pin, in some cases the display can be put to
> > sleep, but the touch is still active. This is why, during suspend I
> > release the gpio resource, and I have to take it back in resume.
> > Without this release/acquire mechanism during suspend/resume,
> > stress-
> > tests showed some failures: the resume freezes completly.
> Looking at the imx8mq-evk dts from the vendor tree I see that the
> touchscreen is not supported in mainline yet.
> 
> Maybe there is a better way to solve this, so what if you don't
> introduce the suspend/resume hooks for now and then we revisit this
> after the touchscreen driver is added?
You are right. We can do this too. I will remove it for now.

Re: [EXT] Re: [PATCH v3 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-24 Thread Robert Chiras
On Vi, 2019-06-21 at 12:46 -0300, Fabio Estevam wrote:
> Caution: EXT Email
> 
> Hi Robert,
> 
> On Fri, Jun 21, 2019 at 11:16 AM Robert Chiras  > wrote:
> 
> > 
> > From what I've seen in the schematics, the power lines on the DSI
> > port
> > on all the i.MX8 cores are coming from a PMIC providing power for
> > all
> > the peripherals. Since I didn't find a way to cut the power on a
> > single
> > peripheral (like DSI, for example) it doesn't make sense for power-
> > supply property. For now, at least.
> This panel driver is not supposed to only work with i.MX8 NXP
> reference boards.
> 
> The dt-bindings should be as accurate as possible from day one, so
> describing the power-supply is important.
> 
> Please look at the panel datasheet and describe the required power
> supplies accordingly.
OK, I will add the power regulators as they are described in panel
datasheet. I just won't be able to test them.
> 
> Thanks

Re: [EXT] Re: [PATCH v3 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-24 Thread Robert Chiras
Hi Fabio,

Thanks for your feedback. I will handle them all, but for the pm_ops I
have some comments. See inline.

On Vi, 2019-06-21 at 10:59 -0300, Fabio Estevam wrote:
> Hi Robert,
> 
> On Thu, Jun 20, 2019 at 10:31 AM Robert Chiras  > wrote:
> 
> > 
> > +fail:
> > +   if (rad->reset)
> > +   gpiod_set_value_cansleep(rad->reset, 1);
> gpiod_set_value_cansleep() can handle NULL, so no need for the if()
> check.
> 
> > 
> > +static const struct display_timing rad_default_timing = {
> > +   .pixelclock = { 13200, 13200, 13200 },
> Having the same information listed three times does not seem useful.
> 
> You could use a drm_display_mode structure with a single entry
> instead.
> 
> > 
> > +   videomode_from_timing(_default_timing, >vm);
> > +
> > +   of_property_read_u32(np, "width-mm", >width_mm);
> > +   of_property_read_u32(np, "height-mm", >height_mm);
> > +
> > +   panel->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> Since this is optional it would be better to use
> devm_gpiod_get_optional() instead.
> 
> 
> > 
> > +
> > +   if (IS_ERR(panel->reset))
> > +   panel->reset = NULL;
> > +   else
> > +   gpiod_set_value_cansleep(panel->reset, 1);
> This is not handling defer probing, so it would be better to do like
> this:
> 
> panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> if (IS_ERR(panel->reset))
>   return  PTR_ERR(panel->reset);
> 
> > 
> > +   memset(_props, 0, sizeof(bl_props));
> > +   bl_props.type = BACKLIGHT_RAW;
> > +   bl_props.brightness = 255;
> > +   bl_props.max_brightness = 255;
> > +
> > +   panel->backlight = devm_backlight_device_register(dev,
> > dev_name(dev),
> > + dev, dsi,
> > + _bl_o
> > ps,
> > + _props
> > );
> Could you put more parameters into the same line?
> 
> Using 4 lines seems excessive.
> 
> > 
> > +   if (IS_ERR(panel->backlight)) {
> > +   ret = PTR_ERR(panel->backlight);
> > +   dev_err(dev, "Failed to register backlight (%d)\n",
> > ret);
> > +   return ret;
> > +   }
> > +
> > +   drm_panel_init(>panel);
> > +   panel->panel.funcs = _panel_funcs;
> > +   panel->panel.dev = dev;
> > +   dev_set_drvdata(dev, panel);
> > +
> > +   ret = drm_panel_add(>panel);
> > +
> Unneeded blank line
> 
> > 
> > +   if (ret < 0)
> > +   return ret;
> > +
> > +   ret = mipi_dsi_attach(dsi);
> > +   if (ret < 0)
> > +   drm_panel_remove(>panel);
> > +
> > +   return ret;
> You did not handle the "power" regulator.
There is no need for a power regulator.
> 
> > 
> > +static int __maybe_unused rad_panel_suspend(struct device *dev)
> > +{
> > +   struct rad_panel *rad = dev_get_drvdata(dev);
> > +
> > +   if (!rad->reset)
> > +   return 0;
> > +
> > +   devm_gpiod_put(dev, rad->reset);
> > +   rad->reset = NULL;
> > +
> > +   return 0;
> > +}
> > +
> > +static int __maybe_unused rad_panel_resume(struct device *dev)
> > +{
> > +   struct rad_panel *rad = dev_get_drvdata(dev);
> > +
> > +   if (rad->reset)
> > +   return 0;
> > +
> > +   rad->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> Why do you call devm_gpiod_get() once again?
> 
> I am having a hard time to understand the need for this
> suspend/resume hooks.
> 
> Can't you simply remove them?
The reset gpio pin is shared between the DSI display controller and
touch controller, both found on the same panel. Since, the touch driver
also acceses this gpio pin, in some cases the display can be put to
sleep, but the touch is still active. This is why, during suspend I
release the gpio resource, and I have to take it back in resume.
Without this release/acquire mechanism during suspend/resume, stress-
tests showed some failures: the resume freezes completly.

Re: [EXT] Re: [PATCH v3 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-21 Thread Robert Chiras
Hi Fabio,

On Vi, 2019-06-21 at 11:00 -0300, Fabio Estevam wrote:
> Hi Robert,
> 
> On Thu, Jun 20, 2019 at 10:32 AM Robert Chiras  > wrote:
> > 
> > 
> > Add dt-bindings documentation for Raydium RM67191 DSI panel.
> > 
> > Signed-off-by: Robert Chiras 
> > Reviewed-by: Sam Ravnborg 
> > ---
> >  .../bindings/display/panel/raydium,rm67191.txt | 39
> > ++
> >  1 file changed, 39 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/panel/raydium,rm67191.t
> > xt
> > b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.t
> > xt
> > new file mode 100644
> > index 000..52af272
> > --- /dev/null
> > +++
> > b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.t
> > xt
> > @@ -0,0 +1,39 @@
> > +Raydium RM67171 OLED LCD panel with MIPI-DSI protocol
> > +
> > +Required properties:
> > +- compatible:  "raydium,rm67191"
> > +- reg: virtual channel for MIPI-DSI protocol
> > +   must be <0>
> > +- dsi-lanes:   number of DSI lanes to be used
> > +   must be <3> or <4>
> > +- port:input port node with endpoint definition as
> > +   defined in
> > Documentation/devicetree/bindings/graph.txt;
> > +   the input port should be connected to a
> > MIPI-DSI device
> > +   driver
> > +
> > +Optional properties:
> > +- reset-gpios: a GPIO spec for the RST_B GPIO pin
> > +- width-mm:see panel-common.txt
> > +- height-mm:   see panel-common.txt
> > +- video-mode:  0 - burst-mode
> > +   1 - non-burst with sync event
> > +   2 - non-burst with sync po ulse
> No power-supply property?
From what I've seen in the schematics, the power lines on the DSI port
on all the i.MX8 cores are coming from a PMIC providing power for all
the peripherals. Since I didn't find a way to cut the power on a single
peripheral (like DSI, for example) it doesn't make sense for power-
supply property. For now, at least.

[PATCH v3 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-20 Thread Robert Chiras
This patch adds Raydium RM67191 TFT LCD panel driver (MIPI-DSI
protocol).

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
---
 MAINTAINERS   |   6 +
 drivers/gpu/drm/panel/Kconfig |   9 +
 drivers/gpu/drm/panel/Makefile|   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c | 690 ++
 4 files changed, 706 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a2f487..cd93030e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5089,6 +5089,12 @@ S:   Maintained
 F: drivers/gpu/drm/qxl/
 F: include/uapi/drm/qxl_drm.h
 
+DRM DRIVER FOR RAYDIUM RM67191 PANELS
+M: Robert Chiras 
+S: Maintained
+F: drivers/gpu/drm/panel/panel-raydium-rm67191.c
+F: Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
+
 DRM DRIVER FOR RAGE 128 VIDEO CARDS
 S: Orphan / Obsolete
 F: drivers/gpu/drm/r128/
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index d9d931a..8be1ac1 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -159,6 +159,15 @@ config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN
  Pi 7" Touchscreen.  To compile this driver as a module,
  choose M here.
 
+config DRM_PANEL_RAYDIUM_RM67191
+   tristate "Raydium RM67191 FHD 1080x1920 DSI video mode panel"
+   depends on OF
+   depends on DRM_MIPI_DSI
+   depends on BACKLIGHT_CLASS_DEVICE
+   help
+ Say Y here if you want to enable support for Raydium RM67191 FHD
+ (1080x1920) DSI panel.
+
 config DRM_PANEL_RAYDIUM_RM68200
tristate "Raydium RM68200 720x1280 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index fb0cb3a..1fc0f68 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += 
panel-orisetech-otm8009a.o
 obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o
 obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
 obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += 
panel-raspberrypi-touchscreen.o
+obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o
 obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o
 obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o
 obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o
diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c 
b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
new file mode 100644
index 000..c4d7dfd
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -0,0 +1,690 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Raydium RM67191 MIPI-DSI panel driver
+ *
+ * Copyright 2019 NXP
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* Panel specific color-format bits */
+#define COL_FMT_16BPP 0x55
+#define COL_FMT_18BPP 0x66
+#define COL_FMT_24BPP 0x77
+
+/* Write Manufacture Command Set Control */
+#define WRMAUCCTR 0xFE
+
+/* Manufacturer Command Set pages (CMD2) */
+struct cmd_set_entry {
+   u8 cmd;
+   u8 param;
+};
+
+/*
+ * There is no description in the Reference Manual about these commands.
+ * We received them from vendor, so just use them as is.
+ */
+static const struct cmd_set_entry manufacturer_cmd_set[] = {
+   {0xFE, 0x0B},
+   {0x28, 0x40},
+   {0x29, 0x4F},
+   {0xFE, 0x0E},
+   {0x4B, 0x00},
+   {0x4C, 0x0F},
+   {0x4D, 0x20},
+   {0x4E, 0x40},
+   {0x4F, 0x60},
+   {0x50, 0xA0},
+   {0x51, 0xC0},
+   {0x52, 0xE0},
+   {0x53, 0xFF},
+   {0xFE, 0x0D},
+   {0x18, 0x08},
+   {0x42, 0x00},
+   {0x08, 0x41},
+   {0x46, 0x02},
+   {0x72, 0x09},
+   {0xFE, 0x0A},
+   {0x24, 0x17},
+   {0x04, 0x07},
+   {0x1A, 0x0C},
+   {0x0F, 0x44},
+   {0xFE, 0x04},
+   {0x00, 0x0C},
+   {0x05, 0x08},
+   {0x06, 0x08},
+   {0x08, 0x08},
+   {0x09, 0x08},
+   {0x0A, 0xE6},
+   {0x0B, 0x8C},
+   {0x1A, 0x12},
+   {0x1E, 0xE0},
+   {0x29, 0x93},
+   {0x2A, 0x93},
+   {0x2F, 0x02},
+   {0x31, 0x02},
+   {0x33, 0x05},
+   {0x37, 0x2D},
+   {0x38, 0x2D},
+   {0x3A, 0x1E},
+   {0x3B, 0x1E},
+   {0x3D, 0x27},
+   {0x3F, 0x80},
+   {0x40, 0x40},
+   {0x41, 0xE0},
+   {0x4F, 0x2F},
+   {0x50, 0x1E},
+   {0xFE, 0x06},
+   {0x00, 0xCC},
+   {0x05, 0x05},
+   {0x07, 0xA2},
+   {0x08, 0xCC},
+   {0x0D, 0x03},
+   {0x0F, 0xA2},
+   {0x32, 0xCC},
+   {0x37, 0x05},
+   {0x39, 0x83},
+   {0x3A, 0xCC},
+   {0x41, 0x04},
+   {0x43, 0x83},
+   {0x44, 0

[PATCH v3 0/2] Add DSI panel driver for Raydium RM67191

2019-06-20 Thread Robert Chiras
This patch-set contains the DRM panel driver and dt-bindings documentation
for the DSI driven panel: Raydium RM67191.

v3:
- Added myself to MAINTAINERS for this driver (sam)
- Removed display-timings property (fabio)
- Fixed dt description (sam)
- Re-arranged calls inside get_modes function (sam)
- Changed ifdefs with _maybe_unused for suspend/resume functions (sam)
- Collected Reviewed-by from Sam

v2:
- Fixed 'reset-gpio' to 'reset-gpios' property naming (fabio)
- Changed the state of the reset gpio to active low and fixed how it is
  handled in driver (fabio)
- Fixed copyright statement (daniel)
- Reordered includes (sam)
- Added defines for panel specific color formats (fabio)
- Removed unnecessary tests in enable and unprepare (sam)
- Removed the unnecessary backlight write in enable (sam)

Robert Chiras (2):
  dt-bindings: display: panel: Add support for Raydium RM67191 panel
  drm/panel: Add support for Raydium RM67191 panel driver

 .../bindings/display/panel/raydium,rm67191.txt |  39 ++
 MAINTAINERS|   6 +
 drivers/gpu/drm/panel/Kconfig  |   9 +
 drivers/gpu/drm/panel/Makefile |   1 +
 drivers/gpu/drm/panel/panel-raydium-rm67191.c  | 690 +
 5 files changed, 745 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
 create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c

-- 
2.7.4



[PATCH v3 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-20 Thread Robert Chiras
Add dt-bindings documentation for Raydium RM67191 DSI panel.

Signed-off-by: Robert Chiras 
Reviewed-by: Sam Ravnborg 
---
 .../bindings/display/panel/raydium,rm67191.txt | 39 ++
 1 file changed, 39 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt

diff --git 
a/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt 
b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
new file mode 100644
index 000..52af272
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm67191.txt
@@ -0,0 +1,39 @@
+Raydium RM67171 OLED LCD panel with MIPI-DSI protocol
+
+Required properties:
+- compatible:  "raydium,rm67191"
+- reg: virtual channel for MIPI-DSI protocol
+   must be <0>
+- dsi-lanes:   number of DSI lanes to be used
+   must be <3> or <4>
+- port:input port node with endpoint definition as
+   defined in Documentation/devicetree/bindings/graph.txt;
+   the input port should be connected to a MIPI-DSI device
+   driver
+
+Optional properties:
+- reset-gpios: a GPIO spec for the RST_B GPIO pin
+- width-mm:see panel-common.txt
+- height-mm:   see panel-common.txt
+- video-mode:  0 - burst-mode
+   1 - non-burst with sync event
+   2 - non-burst with sync pulse
+
+Example:
+
+   panel@0 {
+   compatible = "raydium,rm67191";
+   reg = <0>;
+   pinctrl-0 = <_mipi_dsi_0_1_en>;
+   pinctrl-names = "default";
+   reset-gpios = < 7 GPIO_ACTIVE_LOW>;
+   dsi-lanes = <4>;
+   width-mm = <68>;
+   height-mm = <121>;
+
+   port {
+   panel_in: endpoint {
+   remote-endpoint = <_out>;
+   };
+   };
+   };
-- 
2.7.4



Re: [EXT] Re: [PATCH v2 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-20 Thread Robert Chiras
On Mi, 2019-06-19 at 10:28 -0300, Fabio Estevam wrote:
> Caution: EXT Email
> 
> Hi Robert,
> 
> On Tue, Jun 18, 2019 at 10:31 AM Robert Chiras  > wrote:
> 
> > 
> > +static const struct display_timing rad_default_timing = {
> > +   .pixelclock = { 6600, 13200, 13200 },
> > +   .hactive = { 1080, 1080, 1080 },
> > +   .hfront_porch = { 20, 20, 20 },
> > +   .hsync_len = { 2, 2, 2 },
> > +   .hback_porch = { 34, 34, 34 },
> > +   .vactive = { 1920, 1920, 1920 },
> > +   .vfront_porch = { 10, 10, 10 },
> > +   .vsync_len = { 2, 2, 2 },
> > +   .vback_porch = { 4, 4, 4 },
> Are you sure that the sync_len and porch parameters are the same for
> both 66MHz and 132MHz?
Probably they are not, since I didn't get this panel to work well with
66Hz. So I will just keep 132MHz, since these are the only timinings we
received from vendor.

Re: [EXT] Re: [PATCH v2 2/2] drm/panel: Add support for Raydium RM67191 panel driver

2019-06-20 Thread Robert Chiras
Hi Sam,

On Mi, 2019-06-19 at 15:25 +0200, Sam Ravnborg wrote:
> On Tue, Jun 18, 2019 at 04:30:46PM +0300, Robert Chiras wrote:
> > 
> > This patch adds Raydium RM67191 TFT LCD panel driver (MIPI-DSI
> > protocol).
> > 
> > Signed-off-by: Robert Chiras 
> Please include in the changelog a list of what was updated - like
> this:
> 
> v2:
> - added kconif symbol sorted (sam)
> - another nitpick (foo)
> - etc
> 
> In general try to namme who gave feedback to give them some credit.
Thanks. I will keep this in mind, next time
> 
> Who is maintainer for this onwards?
I can offer myself to maintain this.
> 
> > 
> > ---
> >  drivers/gpu/drm/panel/Kconfig |   9 +
> >  drivers/gpu/drm/panel/Makefile|   1 +
> >  drivers/gpu/drm/panel/panel-raydium-rm67191.c | 709
> > ++
> >  3 files changed, 719 insertions(+)
> >  create mode 100644 drivers/gpu/drm/panel/panel-raydium-rm67191.c
> > 
> > +static int rad_panel_prepare(struct drm_panel *panel)
> > +{
> > + struct rad_panel *rad = to_rad_panel(panel);
> > +
> > + if (rad->prepared)
> > + return 0;
> > +
> > + if (rad->reset) {
> > + gpiod_set_value_cansleep(rad->reset, 1);
> > + usleep_range(3000, 5000);
> > + gpiod_set_value_cansleep(rad->reset, 0);
> So writing a 0 will release reset.
> > 
> > + usleep_range(18000, 2);
> > + }
> > +
> > + rad->prepared = true;
> > +
> > + return 0;
> > +}
> > +
> > +static int rad_panel_unprepare(struct drm_panel *panel)
> > +{
> > + struct rad_panel *rad = to_rad_panel(panel);
> > +
> > + if (!rad->prepared)
> > + return 0;
> > +
> > + if (rad->reset) {
> > + gpiod_set_value_cansleep(rad->reset, 1);
> > + usleep_range(15000, 17000);
> > + gpiod_set_value_cansleep(rad->reset, 0);
> Looks strange that reset is released in unprepare.
> I would expect it to stay reset to minimize power etc.
Yes, it looks strange indeed. The reason here is coming from the fact
that this panel also has touch-screen that shares this reset pin with
the OLED display. While the display may be turned off, the touch driver
may need to keep the connection active with the touch controller from
this panel. This is the reason for releasing the reset pin in
unprepare. I will add this in a comment in the code, to eliminate the
confusion.
> 
> > 
> > +
> > + ret = drm_display_info_set_bus_formats(
> > >display_info,
> > +rad_bus_formats,
> > +ARRAY_SIZE(rad_bus_for
> > mats));
> Other drivers has this as the last stement in their enable function.
> I did not check why, but maybe something to invest a few minutes
> into.
> Be different only if there is a reason to do so.
Ok, I will move this as the last statement. I also noticed that the
other panel drivers do not check the return of this call, like I do
here, so I will also remove this too.
> 
> > 
> > + if (ret)
> > + return ret;
> > +
> > + drm_mode_probed_add(panel->connector, mode);
> > +
> > + return 1;
> > +}
> > +
> > +
> > +#ifdef CONFIG_PM
> > +static int rad_panel_suspend(struct device *dev)
> > +{
> > + struct rad_panel *rad = dev_get_drvdata(dev);
> > +
> > + if (!rad->reset)
> > + return 0;
> > +
> > + devm_gpiod_put(dev, rad->reset);
> > + rad->reset = NULL;
> > +
> > + return 0;
> > +}
> > +
> > +static int rad_panel_resume(struct device *dev)
> > +{
> > + struct rad_panel *rad = dev_get_drvdata(dev);
> > +
> > + if (rad->reset)
> > + return 0;
> > +
> > + rad->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
> > + if (IS_ERR(rad->reset))
> > + rad->reset = NULL;
> > +
> > + return PTR_ERR_OR_ZERO(rad->reset);
> > +}
> > +
> > +#endif
> Use __maybe_unused for the tw functions above.
> And loose the ifdef...
Thanks. Will apply.
> 
> > 
> > +
> > +static const struct dev_pm_ops rad_pm_ops = {
> > + SET_RUNTIME_PM_OPS(rad_panel_suspend, rad_panel_resume, NULL)
> > + SET_SYSTEM_SLEEP_PM_OPS(rad_panel_suspend, rad_panel_resume)
> > +};
> > +
> > +static const struct of_device_id r

Re: [EXT] Re: [PATCH v2 1/2] dt-bindings: display: panel: Add support for Raydium RM67191 panel

2019-06-20 Thread Robert Chiras
On Mi, 2019-06-19 at 10:21 -0300, Fabio Estevam wrote:
> Caution: EXT Email
> 
> Hi Robert,
> 
> On Tue, Jun 18, 2019 at 10:33 AM Robert Chiras  > wrote:
> 
> > 
> > +Optional properties:
> > +- reset-gpios: a GPIO spec for the RST_B GPIO pin
> > +- pinctrl-0phandle to the pin settings for the reset
> > pin
> > +- width-mm:physical panel width [mm]
> > +- height-mm:   physical panel height [mm]
> > +- display-timings: timings for the connected panel according
> > to [1]
> Still not convinced we need the 'display-timings' property, even as
> an
> optional property. My understanding is that passing display timings
> in
> the devicetree is not encouraged.
> 
> Last time you said you need to pass ''display-timings' to workaround
> the problem of connecting this panel to mx8m DCSS or eLCDIF.
> 
> The panel timings come from the LCD manufacturer and it is agnostic
> to
> what display controller interface it is connected to.
> 
> So I suggest making sure the timings passed in the driver are correct
> as per the vendor datasheet. If they are correct and one specific
> interface is not able to drive it, then probably it is a bug in this
> specific display controller interface or in the SoC clock driver.

I understand. I will remove the display-timings from dt and also from
driver. Currently, this panel works in this form with both LCDIF and
DCSS on our 8M SoC so, as you said, probably the issue we were seeing
in our tree was coming from elsewhere.

  1   2   >