[PATCH v6 00/22] drm/sun4i: Allwinner A64 MIPI-DSI support

293 views
Skip to first unread message

Jagan Teki

unread,
Jan 24, 2019, 2:59:20 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Here is next version changes for Allwinner A64 MIPI-DSI support

This series grouped the changes from previous version A64 MIPI-DSI[1]
along with burst mode[2].

Though the series seems to have more patches, but all patches are ordered
in a way that the review process is as smooth as possible.

Overall the series is grouped into four different sets to support three
different panels types that can fit into the DSI controller.

set:1 for 4-lane, burst mode:
- patch 0001: 0009, DSI controller changes that support burst mode.
all the patches fixed the previous comments along with proper commit message.

set:2 for A64 DSI changes:
- patch 0010: 0011, PLL-MIPI changes related to A64
- patch 0012: 0013, VCC-DSI supply change on DSI controller
- patch 0014: 0015: dt-bindings patches for A64 DSI and DPHY documentation
- patch 0016: A64 DSI pipeline patch
- patch 0017: Overlay patch that enable Feiyang FY07024DI26A30-D burst mode
panel on Pine64-LTS to validate set:1 changes

set:3 for 4-lane, non-burst mode:
- patch 0018: msg type MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM support
- patch 0019: Overlay patch that enable Bananapi S070WV20-CT16 ICN6211
panel on Bananapi M64 to validate set:3 changes

set:4 for 2-lane, non-burst mode:
- patch 0020: 0021, DSI hfp and hbp timings fixes
- patch 0022: patch to enable Techstar TS8550B panel on Amarula A64-Relic
to validate set:4 changes.

Changes for v6:
- dropped unneeded changes, patches
- fixed all burst mode patches as per previous version comments
- rebase on master
- update proper commit message
- dropped unneeded comments
- order the patches that make review easy
Changes for v5:
- collect Rob, Acked-by
- droped "Fix VBP size calculation" patch
- updated vblk timing calculation.
- droped techstar, bananapi dsi panel drivers which may require
bridge or other setup. it's under discussion.
Changes for v4:
- droppoed untested CCU_FEATURE_FIXED_POSTDIV check code in
nkm min, max rate patches
- create two patches for "Add Allwinner A64 MIPI DSI support"
one for has_mod_clk quirk and other one for A64 support
- use existing driver code construct for hblk computation
- dropped "Increase hfp packet overhead" patch [2], though BSP added
this but we have no issues as of now.
(no issues on panel side w/o this change)
- create separate function for vblk computation
- enable vcc-dsi regulator in dsi_runtime_resume
- collect Rob, Acked-by
- update MAINTAINERS file for panel drivers
- cleanup commit messages
- fixed checkpatch warnings/errors

[1] https://patchwork.kernel.org/cover/10721509/
[2] https://patchwork.kernel.org/cover/10686655/

Any inputs?
Jagan.

Jagan Teki (22):
drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction
delay
drm/sun4i: sun6i_mipi_dsi: Support instruction loop selection
drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
drm/sun4i: sun6i_mipi_dsi: Simplify drq to support all modes
drm/sun4i: tcon: Export get tcon0 routine
drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
drm/sun4i: sun6i_mipi_dsi: Setup burst mode
drm/sun4i: sun6i_mipi_dsi: Enable 2byte trail for 4-lane burst mode
drm/sun4i: sun6i_mipi_dsi: Enable burst mode HBP, HSA_HSE
clk: sunxi-ng: Add check for minimal rate to NKM PLLs
clk: sunxi-ng: a64: Add minimum rate for PLL_MIPI
dt-bindings: sun6i-dsi: Add VCC-DSI supply property
drm/sun4i: sun6i_mipi_dsi: Add support for VCC-DSI voltage regulator
dt-bindings: sun6i-dsi: Add A64 DSI compatible (w/ A31 fallback)
dt-bindings: sun6i-dsi: Add A64 DPHY compatible (w/ A31 fallback)
arm64: dts: allwinner: a64: Add DSI pipeline
[DO NOT MERGE] arm64: allwinner: a64: pine64-lts: Enable Feiyang FY07024DI26A30-D DSI
panel
drm/sun4i: sun6i_mipi_dsi: Add DSI Generic short write 2 param
transfer
[DO NOT MERGE] arm64: dts: allwinner: bananapi-m64: Bananapi S070WV20-CT16 DSI panel
drm/sun4i: sun6i_mipi_dsi: Fix DSI hbp timing value
drm/sun4i: sun6i_mipi_dsi: Fix DSI hfp timing value
arm64: dts: allwinner: a64-amarula-relic: Add Techstar TS8550B
MIPI-DSI panel

.../bindings/display/sunxi/sun6i-dsi.txt | 5 +
.../allwinner/sun50i-a64-amarula-relic.dts | 39 +++++
.../dts/allwinner/sun50i-a64-bananapi-m64.dts | 43 +++++
.../dts/allwinner/sun50i-a64-pine64-lts.dts | 39 +++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 47 +++++
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 1 +
drivers/clk/sunxi-ng/ccu_nkm.c | 5 +
drivers/clk/sunxi-ng/ccu_nkm.h | 1 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 165 ++++++++++++++++--
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 4 +
12 files changed, 337 insertions(+), 16 deletions(-)

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:24 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Loop N1 instruction delay varies between burst and non-burst
video modes. for burst mode panels it is computed based on the
panel clock along with horizontal sync and porch timings and
the rest it is simply (50 - 1)

Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1=
(panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50;
=> (((mode->htotal - mode->hdisplay) * 150) /
((mode->clock / 1000) * 8)) - 50;

So, this patch add loop N1 computation for burst mode, for non-burst
which is already available.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index e3b34a345546..a5fcee750bee 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -354,6 +354,24 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
SUN6I_DSI_INST_JUMP_CFG_NUM(1));
};

+static u16 sun6i_dsi_setup_inst_delay(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode)
+{
+ struct mipi_dsi_device *device = dsi->device;
+ u32 hsync_porch, dclk;
+ u16 delay;
+
+ hsync_porch = (mode->htotal - mode->hdisplay);
+ dclk = (mode->clock / 1000);
+
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ delay = ((hsync_porch * 150) / (dclk * 8)) - 50;
+ else
+ delay = 50 - 1;
+
+ return delay;
+}
+
static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
@@ -383,7 +401,7 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
- u16 delay = 50 - 1;
+ u16 delay = sun6i_dsi_setup_inst_delay(dsi, mode);

regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:29 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Instruction loop selection would require before writing
loop number registers, so enable idle, LP11 bits on
loop selection register.

Reference code available in BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

(dsi_dev[sel]->dsi_inst_loop_sel.dwval = 2<<(4*DSI_INST_ID_LP11) |
3<<(4*DSI_INST_ID_DLY);

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index a5fcee750bee..813d5523f1c7 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -403,6 +403,9 @@ static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
{
u16 delay = sun6i_dsi_setup_inst_delay(dsi, mode);

+ regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_SEL_REG,
+ DSI_INST_ID_HSC << (4 * DSI_INST_ID_LP11) |
+ DSI_INST_ID_HSD << (4 * DSI_INST_ID_DLY));
regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
SUN6I_DSI_INST_LOOP_NUM_N1(delay));
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:35 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Burst mode display timings are different from conventional
video mode, for burst mode most of the timings hsa, hbp, hfp,
vblk are 0 and hblk is computed as (mode->hdisplay * Bpp)

This patch add burst mode timings and directly goto alloc buffer.

Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

dsi_hsa = 0;
dsi_hbp = 0;
dsi_hact = x*dsi_pixel_bits[format]/8;
dsi_hblk = dsi_hact;
dsi_hfp = 0;
dsi_vblk = 0;

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 813d5523f1c7..0f02bcc997a5 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -477,6 +477,12 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,

/* Do all timing calculations up front to allocate buffer space */

+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
+ hbp = hfp = hsa = vblk = 0;
+ hblk = (mode->hdisplay * Bpp);
+ goto alloc_buf;
+ }
+
/*
* A sync period is composed of a blanking packet (4 bytes +
* payload + 2 bytes) and a sync event packet (4 bytes). Its
@@ -515,6 +521,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
*/
vblk = 0;

+alloc_buf:
/* How many bytes do we need to send all payloads? */
bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
buffer = kmalloc(bytes, GFP_KERNEL);
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:41 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Allwinner MIPI DSI drq has enable mode and set bits.
- for burst mode, drq need to set enable mode bit.
- for non-burst video modes, drq need to set enable mode,
set bits for those front proch greater than 20 and for
rest drq is not used.

This patch simplifies existing drq code by grouping into
sun6i_dsi_get_drq and support all video modes.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 39 ++++++++++++++++----------
1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 0f02bcc997a5..16a86d35dc5a 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -354,6 +354,28 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
SUN6I_DSI_INST_JUMP_CFG_NUM(1));
};

+static int sun6i_dsi_get_drq(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode)
+{
+ struct mipi_dsi_device *device = dsi->device;
+
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ return SUN6I_DSI_TCON_DRQ_ENABLE_MODE;
+
+ if ((mode->hsync_start - mode->hdisplay) > 20) {
+ /* Maaaaaagic */
+ u16 drq = (mode->hsync_start - mode->hdisplay) - 20;
+
+ drq *= mipi_dsi_pixel_format_to_bpp(device->format);
+ drq /= 32;
+
+ return (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
+ SUN6I_DSI_TCON_DRQ_SET(drq));
+ }
+
+ return 0;
+}
+
static u16 sun6i_dsi_setup_inst_delay(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
@@ -381,21 +403,8 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
- struct mipi_dsi_device *device = dsi->device;
- u32 val = 0;
-
- if ((mode->hsync_end - mode->hdisplay) > 20) {
- /* Maaaaaagic */
- u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
-
- drq *= mipi_dsi_pixel_format_to_bpp(device->format);
- drq /= 32;
-
- val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
- SUN6I_DSI_TCON_DRQ_SET(drq));
- }
-
- regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG, val);
+ regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG,
+ sun6i_dsi_get_drq(dsi, mode));
}

static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:48 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Sometimes tcon attributes like tcon divider, clock rate etc are needed
in interface drivers like DSI. So for such cases interface driver must
probe the respective tcon and get the attributes.

Since tcon0 probe is already available, via sun4i_get_tcon0 function,
export the same instead of probing tcon explicitly.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 ++-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 0420f5c978b9..3da75a0c5c5d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
* are located in TCON0. This helper returns a pointer to TCON0's
* sun4i_tcon structure, or NULL if not found.
*/
-static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
+struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
{
struct sun4i_drv *drv = drm->dev_private;
struct sun4i_tcon *tcon;
@@ -235,6 +235,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)

return NULL;
}
+EXPORT_SYMBOL(sun4i_get_tcon0);

void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
const struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index b5214d71610f..a52696db14a5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -274,6 +274,7 @@ struct sun4i_tcon {
struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);

+struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm);
void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
const struct drm_encoder *encoder,
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:53 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Probe tcon0 during dsi_bind, so-that the tcon attributes like
divider value, clock rate can get whenever it need.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 +
2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 16a86d35dc5a..2aeaa19a8d1e 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -24,6 +24,7 @@
#include <drm/drm_panel.h>

#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"

#include <video/mipi_display.h>
@@ -947,6 +948,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,
struct drm_device *drm = data;
struct sun4i_drv *drv = drm->dev_private;
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
+ struct sun4i_tcon *tcon0 = sun4i_get_tcon0(drm);
int ret;

if (!dsi->panel)
@@ -954,6 +956,11 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,

dsi->drv = drv;

+ if (!tcon0)
+ return -EINVAL;
+
+ dsi->tcon = tcon0;
+
drm_encoder_helper_add(&dsi->encoder,
&sun6i_dsi_enc_helper_funcs);
ret = drm_encoder_init(drm,
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index dbbc5b3ecbda..257cca660da0 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -33,6 +33,7 @@ struct sun6i_dsi {

struct device *dev;
struct sun4i_drv *drv;
+ struct sun4i_tcon *tcon;
struct mipi_dsi_device *device;
struct drm_panel *panel;
};
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 2:59:59 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Setting up burst mode display would require to compute
- Horizontal timing edge values to fill burst drq register
- Line, sync values to fill burst line register

Since there is no direct documentation for these computations
the edge and line formulas are taken from BSP code (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

line_num = panel->lcd_ht*dsi_pixel_bits[panel->lcd_dsi_format]/
(8*panel->lcd_dsi_lane);
edge1 = sync_point+(panel->lcd_x+panel->lcd_hbp+20)*
dsi_pixel_bits[panel->lcd_dsi_format] /(8*panel->lcd_dsi_lane);
edge1 = (edge1>line_num)?line_num:edge1;
edge0 = edge1+(panel->lcd_x+40)*tcon_div/8;
edge0 = (edge0>line_num)?(edge0-line_num):1;

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 70 ++++++++++++++++++++++++--
1 file changed, 67 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 2aeaa19a8d1e..46ad142e66e8 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -355,6 +355,41 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
SUN6I_DSI_INST_JUMP_CFG_NUM(1));
};

+static u32 sun6i_dsi_get_edge1(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode, u32 sync_point)
+{
+ struct mipi_dsi_device *device = dsi->device;
+ unsigned int bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+ u32 hact_sync_bp;
+
+ /* Horizontal timings duration excluding front porch */
+ hact_sync_bp = (mode->hdisplay + mode->htotal - mode->hsync_start);
+
+ return (sync_point + ((hact_sync_bp + 20) * bpp / (8 * device->lanes)));
+}
+
+static u32 sun6i_dsi_get_edge0(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode, u32 edge1)
+{
+ struct sun4i_tcon *tcon = dsi->tcon;
+ unsigned long dclk_rate, dclk_parent_rate, tcon0_div;
+
+ dclk_rate = clk_get_rate(tcon->dclk);
+ dclk_parent_rate = clk_get_rate(clk_get_parent(tcon->dclk));
+ tcon0_div = dclk_parent_rate / dclk_rate;
+
+ return (edge1 + (mode->hdisplay + 40) * tcon0_div / 8);
+}
+
+static u32 sun6i_dsi_get_line_num(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode)
+{
+ struct mipi_dsi_device *device = dsi->device;
+ unsigned int bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+
+ return (mode->htotal * bpp / (8 * device->lanes));
+}
+
static int sun6i_dsi_get_drq(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
@@ -404,8 +439,32 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
- regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG,
- sun6i_dsi_get_drq(dsi, mode));
+ struct mipi_dsi_device *device = dsi->device;
+ u32 sync_point = 40;
+ u32 line_num = sun6i_dsi_get_line_num(dsi, mode);
+ u32 edge1 = sun6i_dsi_get_edge1(dsi, mode, sync_point);
+ u32 edge0 = sun6i_dsi_get_edge0(dsi, mode, edge1);
+ u32 val;
+
+ if (edge1 > line_num)
+ edge1 = line_num;
+
+ if (edge0 > line_num)
+ edge0 -= line_num;
+ else
+ edge0 = 1;
+
+ regmap_write(dsi->regs, SUN6I_DSI_BURST_DRQ_REG,
+ SUN6I_DSI_BURST_DRQ_EDGE1(edge1) |
+ SUN6I_DSI_BURST_DRQ_EDGE0(edge0));
+ regmap_write(dsi->regs, SUN6I_DSI_BURST_LINE_REG,
+ SUN6I_DSI_BURST_LINE_NUM(line_num) |
+ SUN6I_DSI_BURST_LINE_SYNC_POINT(sync_point));
+
+ /* enable burst mode */
+ regmap_read(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, &val);
+ val |= SUN6I_DSI_BASIC_CTL_VIDEO_BURST;
+ regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);
}

static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
@@ -667,7 +726,12 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION |
SUN6I_DSI_BASIC_CTL1_VIDEO_MODE);

- sun6i_dsi_setup_burst(dsi, mode);
+ regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG,
+ sun6i_dsi_get_drq(dsi, mode));
+
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ sun6i_dsi_setup_burst(dsi, mode);
+
sun6i_dsi_setup_inst_loop(dsi, mode);
sun6i_dsi_setup_format(dsi, mode);
sun6i_dsi_setup_timings(dsi, mode);
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:04 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
For 4-lane, burst mode panels would need to enable 2byte trail_fill
along with filling trail_env in dsi base control register.

Similar reference code avialable in BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

if (panel->lcd_dsi_lane == 4)
{
dsi_dev[sel]->dsi_basic_ctl.bits.trail_inv = 0xc;
dsi_dev[sel]->dsi_basic_ctl.bits.trail_fill = 1;
}

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 46ad142e66e8..a2ad9fa7f8d5 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -33,6 +33,8 @@
#define SUN6I_DSI_CTL_EN BIT(0)

#define SUN6I_DSI_BASIC_CTL_REG 0x00c
+#define SUN6I_DSI_BASIC_CTL_TRAIL_INV(n) (((n) & 0xf) << 4)
+#define SUN6I_DSI_BASIC_CTL_TRAIL_FILL BIT(3)
#define SUN6I_DSI_BASIC_CTL_HBP_DIS BIT(2)
#define SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS BIT(1)
#define SUN6I_DSI_BASIC_CTL_VIDEO_BURST BIT(0)
@@ -464,6 +466,10 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
/* enable burst mode */
regmap_read(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, &val);
val |= SUN6I_DSI_BASIC_CTL_VIDEO_BURST;
+ if (device->lanes == 4) {
+ val |= SUN6I_DSI_BASIC_CTL_TRAIL_INV(0xc);
+ val |= SUN6I_DSI_BASIC_CTL_TRAIL_FILL;
+ }
regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);
}

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:10 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Horizontal back porch, sync active and sync end bits are
needed to disable for burst mode panel operations.

So, disable them via dsi base control register.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index a2ad9fa7f8d5..3d7c03161954 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -549,12 +549,17 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
u16 hbp, hfp, hsa, hblk, vblk;
size_t bytes;
u8 *buffer;
+ u32 val = 0;

/* Do all timing calculations up front to allocate buffer space */

if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
hbp = hfp = hsa = vblk = 0;
hblk = (mode->hdisplay * Bpp);
+
+ regmap_read(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, &val);
+ val |= SUN6I_DSI_BASIC_CTL_HBP_DIS;
+ val |= SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS;
goto alloc_buf;
}

@@ -603,7 +608,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
if (WARN_ON(!buffer))
return;

- regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, 0);
+ regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);

regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG,
sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_START,
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:15 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Some NKM PLLs doesn't work well when their output clock rate is set below
certain rate.

So, add support for minimal rate for relevant PLLs.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Acked-by: Stephen Boyd <sb...@kernel.org>
---
drivers/clk/sunxi-ng/ccu_nkm.c | 5 +++++
drivers/clk/sunxi-ng/ccu_nkm.h | 1 +
2 files changed, 6 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 841840e35e61..096ff4f4839a 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -125,6 +125,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nkm->fixed_post_div;

+ if (rate < nkm->min_rate) {
+ rate = nkm->min_rate;
+ return rate;
+ }
+
ccu_nkm_find_best(*parent_rate, rate, &_nkm);

rate = *parent_rate * _nkm.n * _nkm.k / _nkm.m;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h
index cc6efb70a102..ff5bd00f429f 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.h
+++ b/drivers/clk/sunxi-ng/ccu_nkm.h
@@ -35,6 +35,7 @@ struct ccu_nkm {
struct ccu_mux_internal mux;

unsigned int fixed_post_div;
+ unsigned int min_rate;

struct ccu_common common;
};
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:20 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Minimum PLL used for MIPI is 500MHz, as per manual, but
lowering the min rate by 300MHz can result proper working
nkms divider with the help of desired dclock rate from
panel driver.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Acked-by: Stephen Boyd <sb...@kernel.org>
---
drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 932836d26e2b..296d489aad6e 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -183,6 +183,7 @@ static struct ccu_nkm pll_mipi_clk = {
.n = _SUNXI_CCU_MULT(8, 4),
.k = _SUNXI_CCU_MULT_MIN(4, 2, 2),
.m = _SUNXI_CCU_DIV(0, 4),
+ .min_rate = 300000000,
.common = {
.reg = 0x040,
.hw.init = CLK_HW_INIT("pll-mipi", "pll-video0",
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:24 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Most of the Allwinner MIPI DSI controllers are supply with
VCC-DSI pin. which need to supply for some of the boards to
trigger the power.

So, document the supply property so-that the required board
can eable it via device tree.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Reviewed-by: Rob Herring <ro...@kernel.org>
---
Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
index 6a6cf5de08b0..69e233e8fad1 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
@@ -27,6 +27,9 @@ Required properties:
first port should be the input endpoint, usually coming from the
associated TCON.

+Optional properties:
+ - vcc-dsi-supply: the VCC-DSI power supply of the DSI encoder
+
Any MIPI-DSI device attached to this should be described according to
the bindings defined in ../mipi-dsi-bus.txt

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:29 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Some boards have VCC-DSI pin connected to voltage regulator which may
not be turned on by default.

Add support for such boards by adding voltage regulator handling code to
MIPI DSI driver.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 14 ++++++++++++++
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 3 +++
2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 3d7c03161954..9be414131460 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1107,6 +1107,12 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
return PTR_ERR(base);
}

+ dsi->regulator = devm_regulator_get(dev, "vcc-dsi");
+ if (IS_ERR(dsi->regulator)) {
+ dev_err(dev, "Couldn't get VCC-DSI supply\n");
+ return PTR_ERR(dsi->regulator);
+ }
+
dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
&sun6i_dsi_regmap_config);
if (IS_ERR(dsi->regs)) {
@@ -1183,6 +1189,13 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
{
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
+ int err;
+
+ err = regulator_enable(dsi->regulator);
+ if (err) {
+ dev_err(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err);
+ return err;
+ }

reset_control_deassert(dsi->reset);
clk_prepare_enable(dsi->mod_clk);
@@ -1215,6 +1228,7 @@ static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)

clk_disable_unprepare(dsi->mod_clk);
reset_control_assert(dsi->reset);
+ regulator_disable(dsi->regulator);

return 0;
}
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 257cca660da0..06cce0d0d3ad 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,6 +13,8 @@
#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>

+#include <linux/regulator/consumer.h>
+
struct sun6i_dphy {
struct clk *bus_clk;
struct clk *mod_clk;
@@ -28,6 +30,7 @@ struct sun6i_dsi {
struct clk *bus_clk;
struct clk *mod_clk;
struct regmap *regs;
+ struct regulator *regulator;
struct reset_control *reset;
struct sun6i_dphy *dphy;

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:34 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The MIPI DSI controller in Allwinner A64 is similar to A33.

But unlike A33, A64 doesn't have DSI_SCLK gating which eventually
set the mod clock rate for the controller.

So, use the DSI_DPHY gating for the similar purpose of mod clock
so-that the controller can operate properly.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Reviewed-by: Rob Herring <ro...@kernel.org>
---
Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
index 69e233e8fad1..dbda2e567760 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
@@ -12,6 +12,7 @@ The DSI Encoder generates the DSI signal from the TCON's.
Required properties:
- compatible: value must be one of:
* allwinner,sun6i-a31-mipi-dsi
+ * "allwinner,sun50i-a64-mipi-dsi", "allwinner,sun6i-a31-mipi-dsi"
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the DSI encoder
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:41 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The MIPI DSI PHY controller on Allwinner A64 is similar
on the one on A31.

Add A64 compatible and append A31 compatible as fallback.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Reviewed-by: Rob Herring <ro...@kernel.org>
---
Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
index dbda2e567760..9c553637c72b 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
@@ -40,6 +40,7 @@ D-PHY
Required properties:
- compatible: value must be one of:
* allwinner,sun6i-a31-mipi-dphy
+ * "allwinner,sun50i-a64-mipi-dphy", "allwinner,sun6i-a31-mipi-dphy"
- reg: base address and size of memory-mapped region
- clocks: phandles to the clocks feeding the DSI encoder
* bus: the DSI interface clock
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:49 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The A64 has a MIPI-DSI block which is similar to A31.

Add dsi, dphy nodes with A31 fallback compatible and finally
connect the dsi node to tcon0 node to make proper DSI pipeline.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index cdc154b14a7e..e18d81aff813 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -358,6 +358,12 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
+
+ tcon0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon0>;
+ allwinner,tcon-channel = <1>;
+ };
};
};
};
@@ -935,6 +941,47 @@
status = "disabled";
};

+ dsi: dsi@1ca0000 {
+ compatible = "allwinner,sun50i-a64-mipi-dsi",
+ "allwinner,sun6i-a31-mipi-dsi";
+ reg = <0x01ca0000 0x1000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_DSI_DPHY>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ dsi_in_tcon0: endpoint {
+ remote-endpoint = <&tcon0_out_dsi>;
+ };
+ };
+ };
+ };
+
+ dphy: d-phy@1ca1000 {
+ compatible = "allwinner,sun50i-a64-mipi-dphy",
+ "allwinner,sun6i-a31-mipi-dphy";
+ reg = <0x01ca1000 0x1000>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_DSI_DPHY>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ status = "disabled";
+ #phy-cells = <0>;
+ };
+
csi: csi@1cb0000 {
compatible = "allwinner,sun50i-a64-csi";
reg = <0x01cb0000 0x1000>;
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:53 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Feiyang FY07024DI26A30-D MIPI_DSI panel is desiged to attach with
DSI connector on pine64 boards, enable the same for pine64 LTS.

DSI panel connected via board DSI port with,
- DC1SW as AVDD supply
- DLDO2 as DVDD supply
- DLDO1 as VCC-DSI supply
- PD24 gpio for reset pin
- PH10 gpio for backlight enable pin

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
.../dts/allwinner/sun50i-a64-pine64-lts.dts | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
index 72d6961dc312..341b1c035604 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
@@ -5,9 +5,48 @@
*/

#include "sun50i-a64-sopine-baseboard.dts"
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "Pine64 LTS";
compatible = "pine64,pine64-lts", "allwinner,sun50i-r18",
"allwinner,sun50i-a64";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&r_pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 512>;
+ default-brightness-level = <8>;
+ enable-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PH10 */
+ };
+};
+
+&de {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ vcc-dsi-supply = <&reg_dldo1>; /* VCC3V3-DSI */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "feiyang,fy07024di26a30d";
+ reg = <0>;
+ avdd-supply = <&reg_dc1sw>; /* VCC-LCD */
+ dvdd-supply = <&reg_dldo2>; /* VCC-MIPI */
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD24 */
+ backlight = <&backlight>;
+ };
+};
+
+&r_pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_pwm_pin>;
+ status = "okay";
};
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:00:59 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Short transfer write support for DCS and Generic transfer types
share similar way to process command sequence in DSI block so
add generic write 2 param transfer type macro so-that the panels
which are requesting similar transfer type may process properly.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 9be414131460..58bda0928aef 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -983,6 +983,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
switch (msg->type) {
case MIPI_DSI_DCS_SHORT_WRITE:
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
ret = sun6i_dsi_dcs_write_short(dsi, msg);
break;

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:01:05 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
This patch add support for Bananapi S070WV20-CT16 DSI panel to
BPI-M64 board.

DSI panel connected via board DSI port with,
- DLDO1 as VDD supply
- PD6 gpio for reset pin
- PD5 gpio for backlight enable pin
- PD7 gpio for backlight vdd supply

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
.../dts/allwinner/sun50i-a64-bananapi-m64.dts | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index c99f66271287..14ecc57c72cf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -45,6 +45,7 @@
#include "sun50i-a64.dtsi"

#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "BananaPi-M64";
@@ -56,6 +57,15 @@
serial1 = &uart1;
};

+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&r_pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 512>;
+ default-brightness-level = <2>;
+ enable-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PD5 */
+ power-supply = <&reg_vdd_backlight>;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -126,6 +136,15 @@
};
};

+ reg_vdd_backlight: vdd-backlight {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-backlight";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 3 7 GPIO_ACTIVE_HIGH>; /* LCD-PWR-EN: PD7 */
+ enable-active-high;
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
@@ -169,6 +188,24 @@
status = "okay";
};

+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "bananapi,s070wv20-ct16-icn6211";
+ reg = <0>;
+ reset-gpios = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD6 */
+ vdd-supply = <&reg_dldo1>;
+ backlight = <&backlight>;
+ };
+};
+
&ehci0 {
status = "okay";
};
@@ -261,6 +298,12 @@
status = "okay";
};

+&r_pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_pwm_pin>;
+ status = "okay";
+};
+
&r_rsb {

Jagan Teki

unread,
Jan 24, 2019, 3:01:11 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Current driver is calculating hbp maximum value by subtracting
hsync_start with hdisplay which is front porch value, but the
hbp refers to back porch.

Back porch value is calculating by subtracting htotal with
hsync_end as per drm_mode timings, and BSP code from BPI-M64-bsp
is eventually following the same.

BPI-M64-bsp is computing hbp as
(in drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
dsi_hbp = (hbp-hspw)*dsi_pixel_bits[format]/8 - (4+2);
=> (panel->lcd_hbp - timmings->hor_sync_time)
=> (timmings->hor_back_porch + timmings->hor_sync_time -
timmings->hor_sync_time)
=> timmings->hor_back_porch
=> mode->htotal - mode->hsync_end

So, update the MIPI-DSI hbp value accordingly.

Tested on 2-lane, 4-lane DSI LCD panels.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 58bda0928aef..e24719cabba2 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -578,7 +578,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
*/
#define HBP_PACKET_OVERHEAD 6
hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
- (mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
+ (mode->htotal - mode->hsync_end) * Bpp - HBP_PACKET_OVERHEAD);

/*
* The frontporch is set using a blanking packet (4 bytes +
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:01:17 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Current driver is calculating hfp maximum value by subtracting
htotal with hsync_end which is front back value, but the
hpp refers to front porch.

Front porch value is calculating by subtracting hsync_start with
hdisplay as per drm_mode timings, and BSP code from BPI-M64-bsp
is eventually following the same.

BPI-M64-bsp is computing hfp as (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

dsi_hbp = (hbp-hspw)*dsi_pixel_bits[format]/8 - (4+2);
dsi_hact = x * dsi_pixel_bits[format]/8;
dsi_hblk = (ht-hspw)*dsi_pixel_bits[format]/8-(4+4+2);
dsi_hfp = dsi_hblk - (4+dsi_hact+2) - (4+dsi_hbp+2);

Example,
u32 fmt = dsi_pixel_bits[format]/8;
=> ((ht-hspw)*fmt - 10) - (6 + x * fmt) - (6 + (hbp-hspw)*fmt - 6)
=> (ht - hspw - x - (hbp - hspw)) * fmt - 16
=> (ht - x - hbp) * fmt - 16
=> (ht - x - (timmings->hor_total_time - timmings->hor_front_porch - x)
* fmt - 16
=> (timmings->hor_total_time - x - timmings->hor_total_time +
timmings->hor_front_porch + x) * fmt - 16
=> timmings->hor_front_porch * fmt - 16

So, update the DSI hfp timing accordingly.

Tested on 2-lane, 4-lane MIPI-DSI LCD panels.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index e24719cabba2..9f72eb5f54a6 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -586,7 +586,8 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
*/
#define HFP_PACKET_OVERHEAD 6
hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
- (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
+ (mode->hsync_start - mode->hdisplay) * Bpp -
+ HFP_PACKET_OVERHEAD);

/*
* hblk seems to be the line + porches length.
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Jan 24, 2019, 3:01:24 PM1/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Amarula A64-Relic board by default bound with Techstar TS8550B
MIPI-DSI panel, add support for it.

DSI panel connected via board DSI port with,
- DLDO2 as VCC supply
- DLDO2 as IOVCC supply
- DLDO1 as VCC-DSI supply
- PD24 gpio for reset pin
- PD23 gpio for backlight enable pin

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
.../allwinner/sun50i-a64-amarula-relic.dts | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
index f180c841ac3c..703055f2a4fb 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
@@ -9,6 +9,7 @@
#include "sun50i-a64.dtsi"

#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "Amarula A64-Relic";
@@ -18,6 +19,14 @@
serial0 = &uart0;
};

+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 512>;
+ default-brightness-level = <2>;
+ enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PD23 */
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -83,6 +92,30 @@
};
};

+&de {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ vcc-dsi-supply = <&reg_dldo1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "techstar,ts8550b", "sitronix,st7701";
+ reg = <0>;
+ VCC-supply = <&reg_dldo2>;
+ IOVCC-supply = <&reg_dldo2>;
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD24 */
+ backlight = <&backlight>;
+ };
+};
+
&ehci0 {
status = "okay";
};
@@ -160,6 +193,12 @@
status = "okay";
};

+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pin>;

Maxime Ripard

unread,
Jan 25, 2019, 10:47:42 AM1/25/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
On Fri, Jan 25, 2019 at 01:28:50AM +0530, Jagan Teki wrote:
> Most of the Allwinner MIPI DSI controllers are supply with
> VCC-DSI pin. which need to supply for some of the boards to
> trigger the power.
>
> So, document the supply property so-that the required board
> can eable it via device tree.
>
> Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> Reviewed-by: Rob Herring <ro...@kernel.org>
> ---
> Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> index 6a6cf5de08b0..69e233e8fad1 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> @@ -27,6 +27,9 @@ Required properties:
> first port should be the input endpoint, usually coming from the
> associated TCON.
>
> +Optional properties:
> + - vcc-dsi-supply: the VCC-DSI power supply of the DSI encoder
> +

It looks like the VCC power rail is found on all the Allwinner SoCs,
so it should be made mandatory.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
signature.asc

Maxime Ripard

unread,
Jan 25, 2019, 10:52:39 AM1/25/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
On Fri, Jan 25, 2019 at 01:28:52AM +0530, Jagan Teki wrote:
> The MIPI DSI controller in Allwinner A64 is similar to A33.
>
> But unlike A33, A64 doesn't have DSI_SCLK gating which eventually
> set the mod clock rate for the controller.
>
> So, use the DSI_DPHY gating for the similar purpose of mod clock
> so-that the controller can operate properly.
>
> Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> Reviewed-by: Rob Herring <ro...@kernel.org>
> ---
> Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> index 69e233e8fad1..dbda2e567760 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> @@ -12,6 +12,7 @@ The DSI Encoder generates the DSI signal from the TCON's.
> Required properties:
> - compatible: value must be one of:
> * allwinner,sun6i-a31-mipi-dsi
> + * "allwinner,sun50i-a64-mipi-dsi", "allwinner,sun6i-a31-mipi-dsi"

The other line doesn't have quotes, we should be consistent
signature.asc

Maxime Ripard

unread,
Jan 25, 2019, 10:52:55 AM1/25/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
On Fri, Jan 25, 2019 at 01:28:53AM +0530, Jagan Teki wrote:
> The MIPI DSI PHY controller on Allwinner A64 is similar
> on the one on A31.
>
> Add A64 compatible and append A31 compatible as fallback.
>
> Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> Reviewed-by: Rob Herring <ro...@kernel.org>
> ---
> Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> index dbda2e567760..9c553637c72b 100644
> --- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> +++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
> @@ -40,6 +40,7 @@ D-PHY
> Required properties:
> - compatible: value must be one of:
> * allwinner,sun6i-a31-mipi-dphy
> + * "allwinner,sun50i-a64-mipi-dphy", "allwinner,sun6i-a31-mipi-dphy"

Same remark than patch 14
signature.asc

Maxime Ripard

unread,
Jan 25, 2019, 1:51:24 PM1/25/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
This one looks weird. There's only a single clock in the A64, and it
seems to be for the D-PHY only.

And the rate is fixed at 148.5 MHz apparently, as opposed to the
current code that is running at twice that speed.

Maxime Ripard

unread,
Jan 25, 2019, 4:24:35 PM1/25/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> Minimum PLL used for MIPI is 500MHz, as per manual, but
> lowering the min rate by 300MHz can result proper working
> nkms divider with the help of desired dclock rate from
> panel driver.
>
> Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> Acked-by: Stephen Boyd <sb...@kernel.org>

Going 200MHz below the minimum doesn't seem really reasonable. What
is the issue that you are trying to fix here?

It looks like it's picking bad dividers, but if that's the case, this
isn't the proper fix.

Jagan Teki

unread,
Jan 26, 2019, 11:09:20 AM1/26/19
to maxime...@bootlin.com, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
You mean to say, remove quotes like this


allwinner,sun50i-a64-mipi-dsi, allwinner,sun6i-a31-mipi-dsi

This make confusion with comma with allwinner vs next compatible string
isn't it? (In fact I did follow the similar like TCON in sun4i-drm.txt)

Jagan Teki

unread,
Jan 28, 2019, 4:36:23 AM1/28/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime...@bootlin.com> wrote:
>
> On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > lowering the min rate by 300MHz can result proper working
> > nkms divider with the help of desired dclock rate from
> > panel driver.
> >
> > Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> > Acked-by: Stephen Boyd <sb...@kernel.org>
>
> Going 200MHz below the minimum doesn't seem really reasonable. What
> is the issue that you are trying to fix here?
>
> It looks like it's picking bad dividers, but if that's the case, this
> isn't the proper fix.

As I stated in earlier patches, the whole idea is pick the desired
dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
is unable to get the proper dclk divider at the end, so it eventually
picking up wrong divider value and fired vblank timeout.

So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
get the desired clock something like below.
[ 2.415773] [drm] No driver support for vblank timestamp query.
[ 2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
[ 2.424172] ideal = 220000000, rounded = 0
[ 2.424176] ideal = 275000000, rounded = 0
[ 2.424194] ccu_nkm_round_rate: rate = 330000000
[ 2.424197] ideal = 330000000, rounded = 330000000
[ 2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
[ 2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
[ 2.424209] ideal = 220000000, rounded = 0
[ 2.424213] ideal = 275000000, rounded = 0
[ 2.424230] ccu_nkm_round_rate: rate = 330000000
[ 2.424233] ideal = 330000000, rounded = 330000000
[ 2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
[ 2.424253] ccu_nkm_round_rate: rate = 330000000
[ 2.424270] ccu_nkm_round_rate: rate = 330000000
[ 2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[ 2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[ 2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
[ 2.424309] ccu_nkm_set_rate: _nkm.n = 5
[ 2.424311] ccu_nkm_set_rate: _nkm.k = 2
[ 2.424313] ccu_nkm_set_rate: _nkm.m = 9
[ 2.424661] sun4i_dclk_set_rate div 6
[ 2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000

But look like this wouldn't valid for all other dclock rates, say BPI
panel has 30MHz clock that would failed with this logic.

On the other side Allwinner BSP calculating dclk divider based on the
SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
calculated based on the bpp/lanes.

Since the above min_rate is not desired for possible panels clock, I
think we can rely on BSP to make a move here. I'm planning to do these
changes in next version.

Let me know if you have any comments here?

[1] https://patchwork.kernel.org/patch/10777519/

Maxime Ripard

unread,
Jan 29, 2019, 9:54:12 AM1/29/19
to Jagan Teki, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
Yep

> This make confusion with comma with allwinner vs next compatible string
> isn't it? (In fact I did follow the similar like TCON in sun4i-drm.txt)

There's no really clear consensus here, andd i don't really have a
strong opinion on the matter either. Since the YAML schemas are going
to have it without double quotes, I guess we should use that
convention as well, but we want to remain consistent at least.
signature.asc

Maxime Ripard

unread,
Jan 29, 2019, 10:13:53 AM1/29/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
signature.asc

Jagan Teki

unread,
Jan 29, 2019, 12:31:45 PM1/29/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
Ahh.. I thought this initially but as far as DSI clock computation is
concern, the L12 tcon_div is local variable which is used for edge0
computation in burst mode and not for the dsi clock computation. Since
the BSP is unable to get the tcon_div during edge0 computation, they
defined it locally I think.

You can see the lcd_clk_config() code [2], where we can see DSI clock
computation using dsi_div value.

Here is dump after the in Line 792 which is after computation[3]
[ 10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
[ 10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
[ 10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000

The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
into dsi_div 6. So this can be our actual divider values dclk_min_div,
dclk_max_div in sun4i_dclk_round_rate (from
drivers/gpu/drm/sun4i/sun4i_dotclock.c)

We can even confirm this from Mainline code:
[ 1.866128] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 55000000
[ 1.873112] round_rate, parent = 330000000
[ 1.877351] round_rate, rate = 330000000
[ 1.881338] ideal = 330000000, rounded = 330000000, div = 6
[ 1.887232] sun4i_dclk_round_rate: div = 6 rate = 55000000
[ 1.887239] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 55000000
[ 1.887243] round_rate, parent = 330000000
[ 1.887259] round_rate, rate = 330000000
[ 1.887264] ideal = 330000000, rounded = 330000000, div = 6
[ 1.887267] sun4i_dclk_round_rate: div = 6 rate = 55000000
[ 1.887270] round_rate, parent = 330000000
[ 1.887286] round_rate, rate = 330000000
[ 1.887292] round_rate, parent = 330000000
[ 1.887307] round_rate, rate = 330000000
[ 1.887320] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[ 1.887324] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
[ 1.887350] rate = 330000000
[ 1.887353] parent_rate = 297000000
[ 1.887355] reg = 0x80c00000
[ 1.887359] _nkm.n = 5, nkm->n.offset = 0x1, nkm->n.shift = 8
[ 1.887362] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
[ 1.887365] _nkm.m = 9, nkm->m.offset = 0x1, nkm->m.shift = 0
[ 1.887712] sun4i_dclk_set_rate div 6
[ 1.887720] sun4i_dclk_recalc_rate: val = 6, rate = 55000000

So, the dsi_div from AW BSP is our dclk_mini_div(and dclk_max_div) and
that can be computed as format/lanes in A64.

Hope this explaining clears the diff, let me know if I miss anything.

[2] https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L781
[3] https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L792

Maxime Ripard

unread,
Feb 1, 2019, 9:31:07 AM2/1/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
I wish it was in your commit log in the first place, instead of having
to exchange multiple mails over this.

However, I don't think that's quite true, and it might be a bug in
Allwinner's implementation (or rather something quite confusing).

You're right that the lcd_rate and pll_rate seem to be generated from
the pixel clock, and it indeed looks like the ratio between the pixel
clock and the TCON dotclock is defined through the number of bits per
lanes.

However, in this case, dsi_rate is actually the same than lcd_rate,
since pll_rate is going to be divided by dsi_div:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791

Since lcd_div is 1, it also means that in this case, dsi_rate ==
dclk_rate.

The DSI module clock however, is always set to 148.5 MHz. Indeed, if
we look at:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804

We can see that the rate in clk_info is used if it's different than
0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
DSI panel, will hardcode it to 148.5 MHz:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164

So, the DSI clock is set to this here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805

The TCON *module* clock (the one in the clock controller) has been set
to lcd_rate (so the pixel clock times the number of bits per lane) here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800

And the PLL has been set to the same rate here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794

Let's take a step back now: that function we were looking at,
lcd_clk_config, is called by lcd_clk_enable, which is in turn called
by disp_lcd_enable here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328

The next function being called is disp_al_lcd_cfg, and that function
will hardcode the TCON dotclock divider to 4, here:
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240

So, in the end, the dotclock divider is always 4, the DSI module clock
is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
the TCON module clock doesn't have a divider, the PLL is set at that
same value but this is redundant.

I'll experiment with this and try to see how it works on the A33.
signature.asc

Jagan Teki

unread,
Feb 1, 2019, 10:42:47 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Here is next version changes for Allwinner A64 MIPI-DSI support

This series grouped the changes like previous version[1] with different
sets to support three different panels types that can fit into the DSI
controller.

set:1, for 4-lane, burst mode support
- patch 0001: 0009, DSI controller changes that support burst mode.

set:2, for A64 DSI support
- patch 0010: tcon dclk divider computation based on A64 BSP.
- patch 0011: 0017, Allwinner A64 DSI controller changes.

set:3, enable 4-lane burst mode panel:
- patch 0018: Overlay patch that enable Feiyang FY07024DI26A30-D
burst mode panel on Pine64-LTS

set:4, enable 4-lane video mode panel:
- patch 0019: msg type MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM support
- patch 0020: Overlay patch that enable Bananapi S070WV20-CT16 ICN6211
panel on Bananapi M64

set:5, enable 2-lane video mode panel:
- patch 0021, 0022: DSI hfp and hbp timings fixes
- patch 0023: Enable Techstar TS8550B panel on Amarula A64-Relic

Changes for v7:
- moved vcc-dsi binding to required filed.
- drop quotes on fallback dphy bindings.
- drop min_rate clock pll-mipi patches.
- introduce dclk divider computation as like A64 BSP.
- add A64 DSI quark patches.
- fixed A64 DSI pipeline.
- add proper commit messages.
- collect Merlijn Wajer Tested-by credits.
Changes for v6:
- dropped unneeded changes, patches
- fixed all burst mode patches as per previous version comments
- rebase on master
- update proper commit message
- dropped unneeded comments
- order the patches that make review easy
Changes for v5:
- collect Rob, Acked-by
- droped "Fix VBP size calculation" patch
- updated vblk timing calculation.
- droped techstar, bananapi dsi panel drivers which may require
bridge or other setup. it's under discussion.
Changes for v4:
- droppoed untested CCU_FEATURE_FIXED_POSTDIV check code in
nkm min, max rate patches
- create two patches for "Add Allwinner A64 MIPI DSI support"
one for has_mod_clk quirk and other one for A64 support
- use existing driver code construct for hblk computation
- dropped "Increase hfp packet overhead" patch [2], though BSP added
this but we have no issues as of now.
(no issues on panel side w/o this change)
- create separate function for vblk computation
- enable vcc-dsi regulator in dsi_runtime_resume
- collect Rob, Acked-by
- update MAINTAINERS file for panel drivers
- cleanup commit messages
- fixed checkpatch warnings/errors

[1] https://patchwork.kernel.org/cover/10779893/

Any inputs?
Jagan.

Jagan Teki (23):
drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction
delay
drm/sun4i: sun6i_mipi_dsi: Support instruction loop selection
drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
drm/sun4i: sun6i_mipi_dsi: Simplify drq to support all modes
drm/sun4i: tcon: Export get tcon0 routine
drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
drm/sun4i: sun6i_mipi_dsi: Setup burst mode
drm/sun4i: sun6i_mipi_dsi: Enable trail_inv and trail_fill controls
drm/sun4i: sun6i_mipi_dsi: Enable HBP, HSA_HSE for burst mode
drm/sun4i: tcon: Compute DCLK dividers based on format, lanes
dt-bindings: sun6i-dsi: Add VCC-DSI supply property
drm/sun4i: sun6i_mipi_dsi: Add support for VCC-DSI voltage regulator
dt-bindings: sun6i-dsi: Add A64 MIPI-DSI compatible
dt-bindings: sun6i-dsi: Add A64 DPHY compatible (w/ A31 fallback)
drm/sun4i: sun6i_mipi_dsi: Add has_mod_clk quirk
drm/sun4i: sun6i_mipi_dsi: Add Allwinner A64 MIPI DSI support
arm64: dts: allwinner: a64: Add MIPI DSI pipeline
[DO NOT MERGE] arm64: allwinner: a64: pine64-lts: Enable Feiyang FY07024DI26A30-D DSI
panel
drm/sun4i: sun6i_mipi_dsi: Add DSI Generic short write 2 param
transfer
[DO NOT MERGE] arm64: dts: allwinner: bananapi-m64: Bananapi S070WV20-CT16 DSI panel
drm/sun4i: sun6i_mipi_dsi: Fix DSI hbp timing value
drm/sun4i: sun6i_mipi_dsi: Fix DSI hfp timing value
arm64: dts: allwinner: a64-amarula-relic: Add Techstar TS8550B
MIPI-DSI panel

.../bindings/display/sunxi/sun6i-dsi.txt | 3 +
.../allwinner/sun50i-a64-amarula-relic.dts | 39 ++++
.../dts/allwinner/sun50i-a64-bananapi-m64.dts | 43 ++++
.../dts/allwinner/sun50i-a64-pine64-lts.dts | 39 ++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 45 ++++
drivers/gpu/drm/sun4i/sun4i_tcon.c | 7 +-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 210 +++++++++++++++---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 9 +
9 files changed, 367 insertions(+), 29 deletions(-)

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:48 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Loop N1 instruction delay varies between burst and non-burst video modes.

1) for burst mode panels it is computed based on the panel pixel clock
along with horizontal sync and porch timings.
2) for non-burst mode panels, it is same as existing (50 - 1)

Reference code is available in BSP (from linux-sunxi
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

dsi_dev[sel]->dsi_inst_loop_num.bits.loop_n1=
(panel->lcd_ht-panel->lcd_x)*(150)/(panel->lcd_dclk_freq*8) - 50;
=> (((mode->htotal - mode->hdisplay) * 150) /
((mode->clock / 1000) * 8)) - 50;

This patch add loop N1 computation for burst mode by simplifying
existing code to support all possible modes.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index e3b34a345546..a5fcee750bee 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -354,6 +354,24 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
SUN6I_DSI_INST_JUMP_CFG_NUM(1));
};

+static u16 sun6i_dsi_setup_inst_delay(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode)
+{
+ struct mipi_dsi_device *device = dsi->device;
+ u32 hsync_porch, dclk;
+ u16 delay;
+
+ hsync_porch = (mode->htotal - mode->hdisplay);
+ dclk = (mode->clock / 1000);
+
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ delay = ((hsync_porch * 150) / (dclk * 8)) - 50;
+ else
+ delay = 50 - 1;
+
+ return delay;
+}
+
static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
@@ -383,7 +401,7 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
- u16 delay = 50 - 1;
+ u16 delay = sun6i_dsi_setup_inst_delay(dsi, mode);

regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:51 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Instruction loop selection would require before writing
loop number registers, so enable idle, LP11 bits on
loop selection register.

Reference code available in BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

(dsi_dev[sel]->dsi_inst_loop_sel.dwval = 2<<(4*DSI_INST_ID_LP11) |
3<<(4*DSI_INST_ID_DLY);

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index a5fcee750bee..813d5523f1c7 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -403,6 +403,9 @@ static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
{
u16 delay = sun6i_dsi_setup_inst_delay(dsi, mode);

+ regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_SEL_REG,
+ DSI_INST_ID_HSC << (4 * DSI_INST_ID_LP11) |
+ DSI_INST_ID_HSD << (4 * DSI_INST_ID_DLY));
regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
SUN6I_DSI_INST_LOOP_NUM_N1(delay));
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:51 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Burst mode display timings are different from conventional video mode.

For burst mode most of the timings hsa, hbp, hfp, vblk are 0 and hblk
is computed as (mode->hdisplay * Bpp)

This patch simply add burst mode timings without touching existing mode
timings.

Reference code taken from BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

dsi_hsa = 0;
dsi_hbp = 0;
dsi_hact = x*dsi_pixel_bits[format]/8;
dsi_hblk = dsi_hact;
dsi_hfp = 0;
dsi_vblk = 0;

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 813d5523f1c7..0f02bcc997a5 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -477,6 +477,12 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,

/* Do all timing calculations up front to allocate buffer space */

+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
+ hbp = hfp = hsa = vblk = 0;
+ hblk = (mode->hdisplay * Bpp);
+ goto alloc_buf;
+ }
+
/*
* A sync period is composed of a blanking packet (4 bytes +
* payload + 2 bytes) and a sync event packet (4 bytes). Its
@@ -515,6 +521,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
*/
vblk = 0;

+alloc_buf:
/* How many bytes do we need to send all payloads? */
bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
buffer = kmalloc(bytes, GFP_KERNEL);
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:54 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Allwinner MIPI DSI drq has enable mode bit and set bits.
1) drq for non-burst, with front porch less than 20 would need to
set both enable mode bit and set bits.
2) drq for non-burst, with front porch greater or equal to 20 would
not require to do any drq bit setup.
3) drq for burst mode, would only need to set enable mode bit.

This patch simplifies existing drq code by grouping into
sun6i_dsi_get_drq and support all video modes.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 39 ++++++++++++++++----------
1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 0f02bcc997a5..16a86d35dc5a 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -354,6 +354,28 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
SUN6I_DSI_INST_JUMP_CFG_NUM(1));
};

+static int sun6i_dsi_get_drq(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode)
+{
+ struct mipi_dsi_device *device = dsi->device;
+
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ return SUN6I_DSI_TCON_DRQ_ENABLE_MODE;
+
+ if ((mode->hsync_start - mode->hdisplay) > 20) {
+ /* Maaaaaagic */
+ u16 drq = (mode->hsync_start - mode->hdisplay) - 20;
+
+ drq *= mipi_dsi_pixel_format_to_bpp(device->format);
+ drq /= 32;
+
+ return (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
+ SUN6I_DSI_TCON_DRQ_SET(drq));
+ }
+
+ return 0;
+}
+
static u16 sun6i_dsi_setup_inst_delay(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
@@ -381,21 +403,8 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
- struct mipi_dsi_device *device = dsi->device;
- u32 val = 0;
-
- if ((mode->hsync_end - mode->hdisplay) > 20) {
- /* Maaaaaagic */
- u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
-
- drq *= mipi_dsi_pixel_format_to_bpp(device->format);
- drq /= 32;
-
- val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
- SUN6I_DSI_TCON_DRQ_SET(drq));
- }
-
- regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG, val);
+ regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG,
+ sun6i_dsi_get_drq(dsi, mode));
}

static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:55 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Sometimes tcon attributes like tcon divider, clock rate etc are needed
in interface drivers like DSI. So for such cases interface driver must
probe the respective tcon and get the attributes.

Since tcon0 probe is already available, via sun4i_get_tcon0 function,
export the same instead of probing tcon explicitly.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 3 ++-
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 0420f5c978b9..3da75a0c5c5d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
* are located in TCON0. This helper returns a pointer to TCON0's
* sun4i_tcon structure, or NULL if not found.
*/
-static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
+struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)
{
struct sun4i_drv *drv = drm->dev_private;
struct sun4i_tcon *tcon;
@@ -235,6 +235,7 @@ static struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm)

return NULL;
}
+EXPORT_SYMBOL(sun4i_get_tcon0);

void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
const struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index b5214d71610f..a52696db14a5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -274,6 +274,7 @@ struct sun4i_tcon {
struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);

+struct sun4i_tcon *sun4i_get_tcon0(struct drm_device *drm);
void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
const struct drm_encoder *encoder,
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:57 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Probe tcon0 during dsi_bind, so-that the tcon attributes like
divider value, clock rate can get whenever it need.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 1 +
2 files changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 16a86d35dc5a..2aeaa19a8d1e 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -24,6 +24,7 @@
#include <drm/drm_panel.h>

#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
#include "sun6i_mipi_dsi.h"

#include <video/mipi_display.h>
@@ -947,6 +948,7 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,
struct drm_device *drm = data;
struct sun4i_drv *drv = drm->dev_private;
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
+ struct sun4i_tcon *tcon0 = sun4i_get_tcon0(drm);
int ret;

if (!dsi->panel)
@@ -954,6 +956,11 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master,

dsi->drv = drv;

+ if (!tcon0)
+ return -EINVAL;
+
+ dsi->tcon = tcon0;
+
drm_encoder_helper_add(&dsi->encoder,
&sun6i_dsi_enc_helper_funcs);
ret = drm_encoder_init(drm,
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index dbbc5b3ecbda..257cca660da0 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -33,6 +33,7 @@ struct sun6i_dsi {

struct device *dev;
struct sun4i_drv *drv;
+ struct sun4i_tcon *tcon;
struct mipi_dsi_device *device;
struct drm_panel *panel;
};
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:42:59 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Burst mode in DSI would require separate setup initialization
with respect to conventional video mode.

Allwinner DSI controller would need below sequence to setup the
burst mode.
1) configure the burst drq.
2) configure the burst line.
3) finally enable mode.

To configure burst drq, controller would require to compute the edge0,
edge1 and fill into burst mode register.

To configure burst line, controller would require to compute the line,
sync values and fill into burst line register.

Enable burst mode, would require to enable burst mode bit in DSI control
register.

Since there is no direct documentation for these computations
the edge and line formulas are taken from BSP code (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

line_num = panel->lcd_ht*dsi_pixel_bits[panel->lcd_dsi_format]/
(8*panel->lcd_dsi_lane);
edge1 = sync_point+(panel->lcd_x+panel->lcd_hbp+20)*
dsi_pixel_bits[panel->lcd_dsi_format] /(8*panel->lcd_dsi_lane);
edge1 = (edge1>line_num)?line_num:edge1;
edge0 = edge1+(panel->lcd_x+40)*tcon_div/8;
edge0 = (edge0>line_num)?(edge0-line_num):1;

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 70 ++++++++++++++++++++++++--
1 file changed, 67 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 2aeaa19a8d1e..46ad142e66e8 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -355,6 +355,41 @@ static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
SUN6I_DSI_INST_JUMP_CFG_NUM(1));
};

+static u32 sun6i_dsi_get_edge1(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode, u32 sync_point)
+{
+ struct mipi_dsi_device *device = dsi->device;
+ unsigned int bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+ u32 hact_sync_bp;
+
+ /* Horizontal timings duration excluding front porch */
+ hact_sync_bp = (mode->hdisplay + mode->htotal - mode->hsync_start);
+
+ return (sync_point + ((hact_sync_bp + 20) * bpp / (8 * device->lanes)));
+}
+
+static u32 sun6i_dsi_get_edge0(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode, u32 edge1)
+{
+ struct sun4i_tcon *tcon = dsi->tcon;
+ unsigned long dclk_rate, dclk_parent_rate, tcon0_div;
+
+ dclk_rate = clk_get_rate(tcon->dclk);
+ dclk_parent_rate = clk_get_rate(clk_get_parent(tcon->dclk));
+ tcon0_div = dclk_parent_rate / dclk_rate;
+
+ return (edge1 + (mode->hdisplay + 40) * tcon0_div / 8);
+}
+
+static u32 sun6i_dsi_get_line_num(struct sun6i_dsi *dsi,
+ struct drm_display_mode *mode)
+{
+ struct mipi_dsi_device *device = dsi->device;
+ unsigned int bpp = mipi_dsi_pixel_format_to_bpp(device->format);
+
+ return (mode->htotal * bpp / (8 * device->lanes));
+}
+
static int sun6i_dsi_get_drq(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
@@ -404,8 +439,32 @@ static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
struct drm_display_mode *mode)
{
- regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG,
- sun6i_dsi_get_drq(dsi, mode));
+ struct mipi_dsi_device *device = dsi->device;
+ u32 sync_point = 40;
+ u32 line_num = sun6i_dsi_get_line_num(dsi, mode);
+ u32 edge1 = sun6i_dsi_get_edge1(dsi, mode, sync_point);
+ u32 edge0 = sun6i_dsi_get_edge0(dsi, mode, edge1);
+ u32 val;
+
+ if (edge1 > line_num)
+ edge1 = line_num;
+
+ if (edge0 > line_num)
+ edge0 -= line_num;
+ else
+ edge0 = 1;
+
+ regmap_write(dsi->regs, SUN6I_DSI_BURST_DRQ_REG,
+ SUN6I_DSI_BURST_DRQ_EDGE1(edge1) |
+ SUN6I_DSI_BURST_DRQ_EDGE0(edge0));
+ regmap_write(dsi->regs, SUN6I_DSI_BURST_LINE_REG,
+ SUN6I_DSI_BURST_LINE_NUM(line_num) |
+ SUN6I_DSI_BURST_LINE_SYNC_POINT(sync_point));
+
+ /* enable burst mode */
+ regmap_read(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, &val);
+ val |= SUN6I_DSI_BASIC_CTL_VIDEO_BURST;
+ regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);
}

static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
@@ -667,7 +726,12 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION |
SUN6I_DSI_BASIC_CTL1_VIDEO_MODE);

- sun6i_dsi_setup_burst(dsi, mode);
+ regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG,
+ sun6i_dsi_get_drq(dsi, mode));
+
+ if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+ sun6i_dsi_setup_burst(dsi, mode);
+
sun6i_dsi_setup_inst_loop(dsi, mode);
sun6i_dsi_setup_format(dsi, mode);
sun6i_dsi_setup_timings(dsi, mode);
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:01 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The burst mode panels with 4-lane would require to enable trail bits
in DSI basic control register.

So, enable 2byte trail and trail_env for 4-lane burst mode devices.

Allwinner A64 BSP should also relie on same setup for enabling trail
bit in DSI controller.

Reference code avialable in BSP (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

if (panel->lcd_dsi_lane == 4)
{
dsi_dev[sel]->dsi_basic_ctl.bits.trail_inv = 0xc;
dsi_dev[sel]->dsi_basic_ctl.bits.trail_fill = 1;
}

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 46ad142e66e8..a2ad9fa7f8d5 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -33,6 +33,8 @@
#define SUN6I_DSI_CTL_EN BIT(0)

#define SUN6I_DSI_BASIC_CTL_REG 0x00c
+#define SUN6I_DSI_BASIC_CTL_TRAIL_INV(n) (((n) & 0xf) << 4)
+#define SUN6I_DSI_BASIC_CTL_TRAIL_FILL BIT(3)
#define SUN6I_DSI_BASIC_CTL_HBP_DIS BIT(2)
#define SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS BIT(1)
#define SUN6I_DSI_BASIC_CTL_VIDEO_BURST BIT(0)
@@ -464,6 +466,10 @@ static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
/* enable burst mode */
regmap_read(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, &val);
val |= SUN6I_DSI_BASIC_CTL_VIDEO_BURST;
+ if (device->lanes == 4) {
+ val |= SUN6I_DSI_BASIC_CTL_TRAIL_INV(0xc);
+ val |= SUN6I_DSI_BASIC_CTL_TRAIL_FILL;
+ }
regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);
}

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:02 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Horizontal back porch, sync active and sync end bits are
needed to disable for burst mode panel operations.

So, disable them via dsi base control register.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index a2ad9fa7f8d5..3d7c03161954 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -549,12 +549,17 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
u16 hbp, hfp, hsa, hblk, vblk;
size_t bytes;
u8 *buffer;
+ u32 val = 0;

/* Do all timing calculations up front to allocate buffer space */

if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
hbp = hfp = hsa = vblk = 0;
hblk = (mode->hdisplay * Bpp);
+
+ regmap_read(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, &val);
+ val |= SUN6I_DSI_BASIC_CTL_HBP_DIS;
+ val |= SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS;
goto alloc_buf;
}

@@ -603,7 +608,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
if (WARN_ON(!buffer))
return;

- regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, 0);
+ regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, val);

regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG,
sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_START,
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:04 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
TCON dotclock compute the desired DCLK register divider based on panel
pixel clock along with input DCLK or DSI clock dividers from tcon driver.

The current code allowing an input DCLK dividers ranging from 4 to 127,
but the existing dclock logic is unable to compute the desired output
DCLK divider value for new panels instead it ended-up producing unknown
divider values which no longer exists.

So, add the computation logic 'format/lanes' to dclk min and max dividers
and indeed it produced the desired DCLK divider even for the new panels.

This computation logic align with Allwinner A64 BSP, hoping that would work
even for A33.

Tested this on 3 different panels, and below are the desired divider values
with respect to pixel clock frequency.

- 55MHz pixel clock with 4-lane panel, and the desired DSI clock divider
is 6 with the output parent clock rate of 330MHz.
- 30MHz pixel clock with 4-lane panel, and the desired DSI clock divider
is 6 with parent clock rate of 180MHz.
- 27.5Mhz pixel clock with 2-lane pane, and the desired DSI clock divider
is 12 with the output parent clock rate of 330MHz.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 3da75a0c5c5d..4d5a158d9a25 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -342,8 +342,8 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
u32 block_space, start_delay;
u32 tcon_div;

- tcon->dclk_min_div = 4;
- tcon->dclk_max_div = 127;
+ tcon->dclk_min_div = bpp / lanes;
+ tcon->dclk_max_div = bpp / lanes;

sun4i_tcon0_mode_set_common(tcon, mode);

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:05 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Allwinner MIPI DSI controllers are supplied with SoC DSI
power rails via VCC-DSI pin.

Some board still work without supplying this but give more
faith on datasheet and hardware schematics and document this
supply property in required property list.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Reviewed-by: Rob Herring <ro...@kernel.org>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
index 6a6cf5de08b0..1cc40663b7a2 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
@@ -21,6 +21,7 @@ Required properties:
- phys: phandle to the D-PHY
- phy-names: must be "dphy"
- resets: phandle to the reset controller driving the encoder
+ - vcc-dsi-supply: the VCC-DSI power supply of the DSI encoder

- ports: A ports node with endpoint definitions as defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:07 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Allwinner MIPI DSI controllers are supplied with SoC DSI power rails
via VCC-DSI pin.

Add support for this supply pin by adding voltage regulator handling
code to MIPI DSI driver.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 14 ++++++++++++++
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 3 +++
2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 3d7c03161954..9be414131460 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1107,6 +1107,12 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
return PTR_ERR(base);
}

+ dsi->regulator = devm_regulator_get(dev, "vcc-dsi");
+ if (IS_ERR(dsi->regulator)) {
+ dev_err(dev, "Couldn't get VCC-DSI supply\n");
+ return PTR_ERR(dsi->regulator);
+ }
+
dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
&sun6i_dsi_regmap_config);
if (IS_ERR(dsi->regs)) {
@@ -1183,6 +1189,13 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
{
struct sun6i_dsi *dsi = dev_get_drvdata(dev);
+ int err;
+
+ err = regulator_enable(dsi->regulator);
+ if (err) {
+ dev_err(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err);
+ return err;
+ }

reset_control_deassert(dsi->reset);
clk_prepare_enable(dsi->mod_clk);
@@ -1215,6 +1228,7 @@ static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)

clk_disable_unprepare(dsi->mod_clk);
reset_control_assert(dsi->reset);
+ regulator_disable(dsi->regulator);

return 0;
}
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 257cca660da0..06cce0d0d3ad 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,6 +13,8 @@
#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>

+#include <linux/regulator/consumer.h>
+
struct sun6i_dphy {
struct clk *bus_clk;
struct clk *mod_clk;
@@ -28,6 +30,7 @@ struct sun6i_dsi {
struct clk *bus_clk;
struct clk *mod_clk;
struct regmap *regs;
+ struct regulator *regulator;
struct reset_control *reset;
struct sun6i_dphy *dphy;

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:09 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The MIPI DSI controller in Allwinner A64 is similar to A33.

But unlike A33, A64 doesn't have DSI_SCLK gating so it is valid
to with separate compatible for A64 on the same driver.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Reviewed-by: Rob Herring <ro...@kernel.org>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
index 1cc40663b7a2..9877398be69a 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
@@ -12,6 +12,7 @@ The DSI Encoder generates the DSI signal from the TCON's.
Required properties:
- compatible: value must be one of:
* allwinner,sun6i-a31-mipi-dsi
+ * allwinner,sun50i-a64-mipi-dsi
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
- clocks: phandles to the clocks feeding the DSI encoder
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:11 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The MIPI DSI PHY controller on Allwinner A64 is similar
on the one on A31.

Add A64 compatible and append A31 compatible as fallback.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Reviewed-by: Rob Herring <ro...@kernel.org>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
index 9877398be69a..d0ce51fea103 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun6i-dsi.txt
@@ -38,6 +38,7 @@ D-PHY
Required properties:
- compatible: value must be one of:
* allwinner,sun6i-a31-mipi-dphy
+ * allwinner,sun50i-a64-mipi-dphy, allwinner,sun6i-a31-mipi-dphy
- reg: base address and size of memory-mapped region
- clocks: phandles to the clocks feeding the DSI encoder
* bus: the DSI interface clock
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:12 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
As per the user manual, look like mod clock is not mandatory
for all Allwinner MIPI DSI controllers, it is connected to
CLK_DSI_SCLK for A31 and not available in A64.

So add has_mod_clk quirk and process the clk accordingly.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 38 ++++++++++++++++++--------
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 5 ++++
2 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 9be414131460..de7d9dcb049f 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -10,6 +10,7 @@
#include <linux/component.h>
#include <linux/crc-ccitt.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
@@ -1099,6 +1100,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
dsi->dev = dev;
dsi->host.ops = &sun6i_dsi_host_ops;
dsi->host.dev = dev;
+ dsi->variant = of_device_get_match_data(dev);

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
@@ -1126,17 +1128,20 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
return PTR_ERR(dsi->reset);
}

- dsi->mod_clk = devm_clk_get(dev, "mod");
- if (IS_ERR(dsi->mod_clk)) {
- dev_err(dev, "Couldn't get the DSI mod clock\n");
- return PTR_ERR(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk) {
+ dsi->mod_clk = devm_clk_get(dev, "mod");
+ if (IS_ERR(dsi->mod_clk)) {
+ dev_err(dev, "Couldn't get the DSI mod clock\n");
+ return PTR_ERR(dsi->mod_clk);
+ }
}

/*
* In order to operate properly, that clock seems to be always
* set to 297MHz.
*/
- clk_set_rate_exclusive(dsi->mod_clk, 297000000);
+ if (dsi->variant->has_mod_clk)
+ clk_set_rate_exclusive(dsi->mod_clk, 297000000);

dphy_node = of_parse_phandle(dev->of_node, "phys", 0);
ret = sun6i_dphy_probe(dsi, dphy_node);
@@ -1168,7 +1173,8 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
pm_runtime_disable(dev);
sun6i_dphy_remove(dsi);
err_unprotect_clk:
- clk_rate_exclusive_put(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk)
+ clk_rate_exclusive_put(dsi->mod_clk);
return ret;
}

@@ -1181,7 +1187,8 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
mipi_dsi_host_unregister(&dsi->host);
pm_runtime_disable(dev);
sun6i_dphy_remove(dsi);
- clk_rate_exclusive_put(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk)
+ clk_rate_exclusive_put(dsi->mod_clk);

return 0;
}
@@ -1198,7 +1205,8 @@ static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
}

reset_control_deassert(dsi->reset);
- clk_prepare_enable(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk)
+ clk_prepare_enable(dsi->mod_clk);

/*
* Enable the DSI block.
@@ -1226,7 +1234,8 @@ static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)
{
struct sun6i_dsi *dsi = dev_get_drvdata(dev);

- clk_disable_unprepare(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk)
+ clk_disable_unprepare(dsi->mod_clk);
reset_control_assert(dsi->reset);
regulator_disable(dsi->regulator);

@@ -1239,9 +1248,16 @@ static const struct dev_pm_ops sun6i_dsi_pm_ops = {
NULL)
};

+static const struct sun6i_dsi_variant sun6i_a31_mipi_dsi = {
+ .has_mod_clk = true,
+};
+
static const struct of_device_id sun6i_dsi_of_table[] = {
- { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
- { }
+ {
+ .compatible = "allwinner,sun6i-a31-mipi-dsi",
+ .data = &sun6i_a31_mipi_dsi,
+ },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 06cce0d0d3ad..3c532e83958d 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -22,6 +22,10 @@ struct sun6i_dphy {
struct reset_control *reset;
};

+struct sun6i_dsi_variant {
+ bool has_mod_clk;
+};
+
struct sun6i_dsi {
struct drm_connector connector;
struct drm_encoder encoder;
@@ -39,6 +43,7 @@ struct sun6i_dsi {
struct sun4i_tcon *tcon;
struct mipi_dsi_device *device;
struct drm_panel *panel;
+ const struct sun6i_dsi_variant *variant;
};

static inline struct sun6i_dsi *host_to_sun6i_dsi(struct mipi_dsi_host *host)
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:14 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
The MIPI DSI controller in Allwinner A64 is similar to A33.

But unlike A33, A64 doesn't have DSI_SCLK gating so add compatible
for Allwinner A64 with uninitialized has_mod_clk driver.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index de7d9dcb049f..a0697d78b915 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1252,11 +1252,18 @@ static const struct sun6i_dsi_variant sun6i_a31_mipi_dsi = {
.has_mod_clk = true,
};

+static const struct sun6i_dsi_variant sun50i_a64_mipi_dsi = {
+};
+
static const struct of_device_id sun6i_dsi_of_table[] = {
{
.compatible = "allwinner,sun6i-a31-mipi-dsi",
.data = &sun6i_a31_mipi_dsi,
},
+ {
+ .compatible = "allwinner,sun50i-a64-mipi-dsi",
+ .data = &sun50i_a64_mipi_dsi,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:15 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Add MIPI DSI pipeline for Allwinner A64.

- dsi node, with A64 compatible since it doesn't support
DSI_SCLK gating unlike A33
- dphy node, with A64 compatible with A33 fallback since
DPHY on A64 and A33 is similar
- finally, attach the dsi_in to tcon0 for complete MIPI DSI

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 6e5a608f56f2..f221c50e7fd4 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -359,6 +359,12 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
+
+ tcon0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon0>;
+ allwinner,tcon-channel = <1>;
+ };
};
};
};
@@ -936,6 +942,45 @@
status = "disabled";
};

+ dsi: dsi@1ca0000 {
+ compatible = "allwinner,sun50i-a64-mipi-dsi";
+ reg = <0x01ca0000 0x1000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>;
+ clock-names = "bus";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ dsi_in_tcon0: endpoint {
+ remote-endpoint = <&tcon0_out_dsi>;
+ };
+ };
+ };
+ };
+
+ dphy: d-phy@1ca1000 {
+ compatible = "allwinner,sun50i-a64-mipi-dphy",
+ "allwinner,sun6i-a31-mipi-dphy";
+ reg = <0x01ca1000 0x1000>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_DSI_DPHY>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ status = "disabled";
+ #phy-cells = <0>;
+ };
+
csi: csi@1cb0000 {
compatible = "allwinner,sun50i-a64-csi";
reg = <0x01cb0000 0x1000>;
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:17 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Feiyang FY07024DI26A30-D MIPI_DSI panel is desiged to attach with
DSI connector on pine64 boards, enable the same for pine64 LTS.

DSI panel connected via board DSI port with,
- DC1SW as AVDD supply
- DLDO2 as DVDD supply
- DLDO1 as VCC-DSI supply
- PD24 gpio for reset pin
- PH10 gpio for backlight enable pin

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
.../dts/allwinner/sun50i-a64-pine64-lts.dts | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
index 72d6961dc312..341b1c035604 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
@@ -5,9 +5,48 @@
*/

#include "sun50i-a64-sopine-baseboard.dts"
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "Pine64 LTS";
compatible = "pine64,pine64-lts", "allwinner,sun50i-r18",
"allwinner,sun50i-a64";
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&r_pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 512>;
+ default-brightness-level = <8>;
+ enable-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PH10 */
+ };
+};
+
+&de {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ vcc-dsi-supply = <&reg_dldo1>; /* VCC3V3-DSI */
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "feiyang,fy07024di26a30d";
+ reg = <0>;
+ avdd-supply = <&reg_dc1sw>; /* VCC-LCD */
+ dvdd-supply = <&reg_dldo2>; /* VCC-MIPI */
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD24 */
+ backlight = <&backlight>;
+ };
+};
+
+&r_pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_pwm_pin>;
+ status = "okay";
};
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:19 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Short transfer write support for DCS and Generic transfer types
share similar way to process command sequence in DSI block so
add generic write 2 param transfer type macro so-that the panels
which are requesting similar transfer type may process properly.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index a0697d78b915..09569938c20d 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -984,6 +984,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
switch (msg->type) {
case MIPI_DSI_DCS_SHORT_WRITE:
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+ case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
ret = sun6i_dsi_dcs_write_short(dsi, msg);
break;

--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:20 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
This patch add support for Bananapi S070WV20-CT16 DSI panel to
BPI-M64 board.

DSI panel connected via board DSI port with,
- DLDO1 as VDD supply
- PD6 gpio for reset pin
- PD5 gpio for backlight enable pin
- PD7 gpio for backlight vdd supply

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
.../dts/allwinner/sun50i-a64-bananapi-m64.dts | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index c99f66271287..14ecc57c72cf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -45,6 +45,7 @@
#include "sun50i-a64.dtsi"

#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "BananaPi-M64";
@@ -56,6 +57,15 @@
serial1 = &uart1;
};

+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&r_pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 512>;
+ default-brightness-level = <2>;
+ enable-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PD5 */
+ power-supply = <&reg_vdd_backlight>;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -126,6 +136,15 @@
};
};

+ reg_vdd_backlight: vdd-backlight {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-backlight";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pio 3 7 GPIO_ACTIVE_HIGH>; /* LCD-PWR-EN: PD7 */
+ enable-active-high;
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
@@ -169,6 +188,24 @@
status = "okay";
};

+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "bananapi,s070wv20-ct16-icn6211";
+ reg = <0>;
+ reset-gpios = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD6 */
+ vdd-supply = <&reg_dldo1>;
+ backlight = <&backlight>;
+ };
+};
+
&ehci0 {
status = "okay";
};
@@ -261,6 +298,12 @@
status = "okay";
};

+&r_pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_pwm_pin>;
+ status = "okay";
+};
+
&r_rsb {

Jagan Teki

unread,
Feb 1, 2019, 10:43:22 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Current driver is calculating hbp maximum value by subtracting
hsync_start with hdisplay which is front porch value, but the
hbp refers to back porch.

Back porch value is calculating by subtracting htotal with
hsync_end as per drm_mode timings, and BSP code from BPI-M64-bsp
is eventually following the same.

BPI-M64-bsp is computing hbp as
(in drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)
dsi_hbp = (hbp-hspw)*dsi_pixel_bits[format]/8 - (4+2);
=> (panel->lcd_hbp - timmings->hor_sync_time)
=> (timmings->hor_back_porch + timmings->hor_sync_time -
timmings->hor_sync_time)
=> timmings->hor_back_porch
=> mode->htotal - mode->hsync_end

So, update the MIPI-DSI hbp value accordingly.

Tested on 2-lane, 4-lane DSI LCD panels.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 09569938c20d..780b1906c661 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -579,7 +579,7 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
*/
#define HBP_PACKET_OVERHEAD 6
hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
- (mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
+ (mode->htotal - mode->hsync_end) * Bpp - HBP_PACKET_OVERHEAD);

/*
* The frontporch is set using a blanking packet (4 bytes +
--
2.18.0.321.gffc6fa0e3

Jagan Teki

unread,
Feb 1, 2019, 10:43:26 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Amarula A64-Relic board by default bound with Techstar TS8550B
MIPI-DSI panel, add support for it.

DSI panel connected via board DSI port with,
- DLDO2 as VCC supply
- DLDO2 as IOVCC supply
- DLDO1 as VCC-DSI supply
- PD24 gpio for reset pin
- PD23 gpio for backlight enable pin

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
---
.../allwinner/sun50i-a64-amarula-relic.dts | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
index df0de0772d6b..a5a0a650b589 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
@@ -9,6 +9,7 @@
#include "sun50i-a64.dtsi"

#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>

/ {
model = "Amarula A64-Relic";
@@ -18,6 +19,14 @@
serial0 = &uart0;
};

+ backlight: backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+ brightness-levels = <1 2 4 8 16 32 64 128 512>;
+ default-brightness-level = <2>;
+ enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* LCD-BL-EN: PD23 */
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -83,6 +92,30 @@
};
};

+&de {
+ status = "okay";
+};
+
+&dphy {
+ status = "okay";
+};
+
+&dsi {
+ vcc-dsi-supply = <&reg_dldo1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ panel@0 {
+ compatible = "techstar,ts8550b", "sitronix,st7701";
+ reg = <0>;
+ VCC-supply = <&reg_dldo2>;
+ IOVCC-supply = <&reg_dldo2>;
+ reset-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* LCD-RST: PD24 */
+ backlight = <&backlight>;
+ };
+};
+
&ehci0 {
status = "okay";
};
@@ -160,6 +193,12 @@
status = "okay";
};

+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pin>;

Jagan Teki

unread,
Feb 1, 2019, 10:43:26 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com, Jagan Teki
Current driver is calculating hfp maximum value by subtracting
htotal with hsync_end which is front back value, but the
hpp refers to front porch.

Front porch value is calculating by subtracting hsync_start with
hdisplay as per drm_mode timings, and BSP code from BPI-M64-bsp
is eventually following the same.

BPI-M64-bsp is computing hfp as (from linux-sunxi/
drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c)

dsi_hbp = (hbp-hspw)*dsi_pixel_bits[format]/8 - (4+2);
dsi_hact = x * dsi_pixel_bits[format]/8;
dsi_hblk = (ht-hspw)*dsi_pixel_bits[format]/8-(4+4+2);
dsi_hfp = dsi_hblk - (4+dsi_hact+2) - (4+dsi_hbp+2);

Example,
u32 fmt = dsi_pixel_bits[format]/8;
=> ((ht-hspw)*fmt - 10) - (6 + x * fmt) - (6 + (hbp-hspw)*fmt - 6)
=> (ht - hspw - x - (hbp - hspw)) * fmt - 16
=> (ht - x - hbp) * fmt - 16
=> (ht - x - (timmings->hor_total_time - timmings->hor_front_porch - x)
* fmt - 16
=> (timmings->hor_total_time - x - timmings->hor_total_time +
timmings->hor_front_porch + x) * fmt - 16
=> timmings->hor_front_porch * fmt - 16

So, update the DSI hfp timing accordingly.

Tested on 2-lane, 4-lane MIPI-DSI LCD panels.

Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
Tested-by: Merlijn Wajer <mer...@wizzup.org>
---
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 780b1906c661..3fbe2132eb6a 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -587,7 +587,8 @@ static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
*/
#define HFP_PACKET_OVERHEAD 6
hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
- (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
+ (mode->hsync_start - mode->hdisplay) * Bpp -
+ HFP_PACKET_OVERHEAD);

/*
* hblk seems to be the line + porches length.
--
2.18.0.321.gffc6fa0e3

Maxime Ripard

unread,
Feb 1, 2019, 10:49:03 AM2/1/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linu...@vger.kernel.org, dri-...@lists.freedesktop.org, devic...@vger.kernel.org, Michael Trimarchi, linux-...@amarulasolutions.com, linux...@googlegroups.com
On Fri, Feb 01, 2019 at 09:12:09PM +0530, Jagan Teki wrote:
> Here is next version changes for Allwinner A64 MIPI-DSI support
>
> This series grouped the changes like previous version[1] with different
> sets to support three different panels types that can fit into the DSI
> controller.
>
> set:1, for 4-lane, burst mode support
> - patch 0001: 0009, DSI controller changes that support burst mode.
>
> set:2, for A64 DSI support
> - patch 0010: tcon dclk divider computation based on A64 BSP.
> - patch 0011: 0017, Allwinner A64 DSI controller changes.
>
> set:3, enable 4-lane burst mode panel:
> - patch 0018: Overlay patch that enable Feiyang FY07024DI26A30-D
> burst mode panel on Pine64-LTS
>
> set:4, enable 4-lane video mode panel:
> - patch 0019: msg type MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM support
> - patch 0020: Overlay patch that enable Bananapi S070WV20-CT16 ICN6211
> panel on Bananapi M64
>
> set:5, enable 2-lane video mode panel:
> - patch 0021, 0022: DSI hfp and hbp timings fixes
> - patch 0023: Enable Techstar TS8550B panel on Amarula A64-Relic

You do realise that pushing through a series while the previous
version's discussion hasn't settled yet will not get you anywhere,
right?

Jagan Teki

unread,
Feb 1, 2019, 10:51:56 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
Except the clock, I made few changes with your previous comments. Yes
we can still under clock discussion page, no issues on that. just to
group the remaining patches to finalize if any issues on those.

Jagan Teki

unread,
Feb 1, 2019, 11:34:08 AM2/1/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
On Fri, Feb 1, 2019 at 8:01 PM Maxime Ripard <maxime...@bootlin.com> wrote:
>
> On Tue, Jan 29, 2019 at 11:01:31PM +0530, Jagan Teki wrote:
> > On Tue, Jan 29, 2019 at 8:43 PM Maxime Ripard <maxime...@bootlin.com> wrote:
> > >
> > > On Mon, Jan 28, 2019 at 03:06:10PM +0530, Jagan Teki wrote:
> > > > On Sat, Jan 26, 2019 at 2:54 AM Maxime Ripard <maxime...@bootlin.com> wrote:
> > > > >
> > > > > On Fri, Jan 25, 2019 at 01:28:49AM +0530, Jagan Teki wrote:
> > > > > > Minimum PLL used for MIPI is 500MHz, as per manual, but
> > > > > > lowering the min rate by 300MHz can result proper working
> > > > > > nkms divider with the help of desired dclock rate from
> > > > > > panel driver.
> > > > > >
> > > > > > Signed-off-by: Jagan Teki <ja...@amarulasolutions.com>
> > > > > > Acked-by: Stephen Boyd <sb...@kernel.org>
> > > > >
> > > > > Going 200MHz below the minimum doesn't seem really reasonable. What
> > > > > is the issue that you are trying to fix here?
> > > > >
> > > > > It looks like it's picking bad dividers, but if that's the case, this
> > > > > isn't the proper fix.
> > > >
> > > > As I stated in earlier patches, the whole idea is pick the desired
> > > > dclk divider based dclk rate. So the dotclock, sun4i_dclk_round_rate
> > > > is unable to get the proper dclk divider at the end, so it eventually
> > > > picking up wrong divider value and fired vblank timeout.
> > > >
> > > > So, we come-up with optimal and working min_rate 300MHz in pll-mipi to
> > > > get the desired clock something like below.
> > > > [ 2.415773] [drm] No driver support for vblank timestamp query.
> > > > [ 2.424116] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [ 2.424172] ideal = 220000000, rounded = 0
> > > > [ 2.424176] ideal = 275000000, rounded = 0
> > > > [ 2.424194] ccu_nkm_round_rate: rate = 330000000
> > > > [ 2.424197] ideal = 330000000, rounded = 330000000
> > > > [ 2.424201] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [ 2.424205] sun4i_dclk_round_rate: min_div = 4 max_div = 127, rate = 55000000
> > > > [ 2.424209] ideal = 220000000, rounded = 0
> > > > [ 2.424213] ideal = 275000000, rounded = 0
> > > > [ 2.424230] ccu_nkm_round_rate: rate = 330000000
> > > > [ 2.424233] ideal = 330000000, rounded = 330000000
> > > > [ 2.424236] sun4i_dclk_round_rate: div = 6 rate = 55000000
> > > > [ 2.424253] ccu_nkm_round_rate: rate = 330000000
> > > > [ 2.424270] ccu_nkm_round_rate: rate = 330000000
> > > > [ 2.424278] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [ 2.424281] sun4i_dclk_recalc_rate: val = 1, rate = 330000000
> > > > [ 2.424306] ccu_nkm_set_rate: rate = 330000000, parent_rate = 297000000
> > > > [ 2.424309] ccu_nkm_set_rate: _nkm.n = 5
> > > > [ 2.424311] ccu_nkm_set_rate: _nkm.k = 2
> > > > [ 2.424313] ccu_nkm_set_rate: _nkm.m = 9
> > > > [ 2.424661] sun4i_dclk_set_rate div 6
> > > > [ 2.424668] sun4i_dclk_recalc_rate: val = 6, rate = 55000000
> > > >
> > > > But look like this wouldn't valid for all other dclock rates, say BPI
> > > > panel has 30MHz clock that would failed with this logic.
> > > >
> > > > On the other side Allwinner BSP calculating dclk divider based on the
> > > > SoC's. for A33 [1] it is fixed dclk divider of 4 and for A64 is is
> > > > calculated based on the bpp/lanes.
> > >
> > > It looks like the A64 has the same divider of 4:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
> > >
> > > I think you're confusing it with the ratio between the pixel clock and
> > > the dotclock, called dsi_div:
> > > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L198
> >
> > Ahh.. I thought this initially but as far as DSI clock computation is
> > concern, the L12 tcon_div is local variable which is used for edge0
> > computation in burst mode and not for the dsi clock computation. Since
> > the BSP is unable to get the tcon_div during edge0 computation, they
> > defined it locally I think.
> >
> > You can see the lcd_clk_config() code [2], where we can see DSI clock
> > computation using dsi_div value.
> >
> > Here is dump after the in Line 792 which is after computation[3]
> > [ 10.800737] lcd_clk_config: dsi_div = 6, tcon_div = 4, lcd_div = 1
> > [ 10.800743] lcd_clk_config: lcd_dclk_freq = 55, dclk_rate = 55000000
> > [ 10.800749] lcd_clk_config: lcd_rate = 330000000, pll_rate = 330000000
> >
> > The above dump the lcd_rate 330MHz is computed with panel clock, 55MHz
> > into dsi_div 6. So this can be our actual divider values dclk_min_div,
> > dclk_max_div in sun4i_dclk_round_rate (from
> > drivers/gpu/drm/sun4i/sun4i_dotclock.c)
>
> I wish it was in your commit log in the first place, instead of having
> to exchange multiple mails over this.
>
> However, I don't think that's quite true, and it might be a bug in
> Allwinner's implementation (or rather something quite confusing).
>
> You're right that the lcd_rate and pll_rate seem to be generated from
> the pixel clock, and it indeed looks like the ratio between the pixel
> clock and the TCON dotclock is defined through the number of bits per
> lanes.
>
> However, in this case, dsi_rate is actually the same than lcd_rate,
> since pll_rate is going to be divided by dsi_div:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
>
> Since lcd_div is 1, it also means that in this case, dsi_rate ==
> dclk_rate.

Yes, but the lcd_rate and dsi_rate are not same, since dsi_rate is
again computed as dsi_div with pll_rate.

lcd_rate = dclk_rate * 6;
pll_rate = lcd_rate * 1;
dsi_rate = pll_rate / 6;

[ 14.719981] tcon_div = 4, lcd_div = 1, dsi_div = 6, dsi_rate = 148500000
[ 14.722666] dsi_div = 6, lcd_div = 1
[ 14.722695] [DISP]disp_module_init finish
[ 14.727699] lcd_rate = 180000000, pll_rate = 180000000
[ 14.730269] dsi_rate = 30000000

> The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> we look at:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
>
> We can see that the rate in clk_info is used if it's different than
> 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> DSI panel, will hardcode it to 148.5 MHz:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> So, the DSI clock is set to this here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
>
> The TCON *module* clock (the one in the clock controller) has been set
> to lcd_rate (so the pixel clock times the number of bits per lane) here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
>
> And the PLL has been set to the same rate here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
>
> Let's take a step back now: that function we were looking at,
> lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> by disp_lcd_enable here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
>
> The next function being called is disp_al_lcd_cfg, and that function
> will hardcode the TCON dotclock divider to 4, here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240

Haa.. this is reason I have TCON_DCLK register value is 4 in BSP
# devmem 0x01c0c044
0xF0000004

> So, in the end, the dotclock divider is always 4, the DSI module clock
> is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
> the TCON module clock doesn't have a divider, the PLL is set at that
> same value but this is redundant.

330 or 180MHz. if we have pixel clock 30MHz with 6 div value it's 180MHz.

>
> I'll experiment with this and try to see how it works on the A33.

OK, thanks. will try digging further on this from my side as well.

Jagan Teki

unread,
Feb 11, 2019, 9:08:11 AM2/11/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
Hi Maxime,
> The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> we look at:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
>
> We can see that the rate in clk_info is used if it's different than
> 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> DSI panel, will hardcode it to 148.5 MHz:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> So, the DSI clock is set to this here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805
>
> The TCON *module* clock (the one in the clock controller) has been set
> to lcd_rate (so the pixel clock times the number of bits per lane) here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
>
> And the PLL has been set to the same rate here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
>
> Let's take a step back now: that function we were looking at,
> lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> by disp_lcd_enable here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
>
> The next function being called is disp_al_lcd_cfg, and that function
> will hardcode the TCON dotclock divider to 4, here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
>
> So, in the end, the dotclock divider is always 4, the DSI module clock
> is set to 148.5 MHz, and the TCON module clock is set to 330MHz. Since
> the TCON module clock doesn't have a divider, the PLL is set at that
> same value but this is redundant.
>
> I'll experiment with this and try to see how it works on the A33.

How is it with A33?

Power Pan

unread,
Feb 12, 2019, 2:28:44 AM2/12/19
to linux-sunxi
I have problem on MIPI driver display like this, any clue ?

bad mipi.jpg




在 2019年2月11日星期一 UTC+8下午10:08:11,Jagan Teki写道:

Maxime Ripard

unread,
Feb 12, 2019, 4:30:37 AM2/12/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
The conclusions are the one I sent in my last series
signature.asc

Jagan Teki

unread,
Feb 12, 2019, 4:39:03 AM2/12/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
In this series?
[PATCH v3 0/8] drm/sun4i: dsi: Add burst mode support

Jagan Teki

unread,
Feb 12, 2019, 4:46:16 AM2/12/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
On Fri, Feb 1, 2019 at 9:12 PM Jagan Teki <ja...@amarulasolutions.com> wrote:
>
> Here is next version changes for Allwinner A64 MIPI-DSI support
>
> This series grouped the changes like previous version[1] with different
> sets to support three different panels types that can fit into the DSI
> controller.
>
> set:1, for 4-lane, burst mode support
> - patch 0001: 0009, DSI controller changes that support burst mode.
>
> set:2, for A64 DSI support
> - patch 0010: tcon dclk divider computation based on A64 BSP.
> - patch 0011: 0017, Allwinner A64 DSI controller changes.
>
> set:3, enable 4-lane burst mode panel:
> - patch 0018: Overlay patch that enable Feiyang FY07024DI26A30-D
> burst mode panel on Pine64-LTS
>
> set:4, enable 4-lane video mode panel:
> - patch 0019: msg type MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM support
> - patch 0020: Overlay patch that enable Bananapi S070WV20-CT16 ICN6211
> panel on Bananapi M64
>
> set:5, enable 2-lane video mode panel:
> - patch 0021, 0022: DSI hfp and hbp timings fixes
> - patch 0023: Enable Techstar TS8550B panel on Amarula A64-Relic
>
> Changes for v7:
> - moved vcc-dsi binding to required filed.
> - drop quotes on fallback dphy bindings.
> - drop min_rate clock pll-mipi patches.
> - introduce dclk divider computation as like A64 BSP.
> - add A64 DSI quark patches.
> - fixed A64 DSI pipeline.
> - add proper commit messages.
> - collect Merlijn Wajer Tested-by credits.
> Changes for v6:
> - dropped unneeded changes, patches
> - fixed all burst mode patches as per previous version comments
> - rebase on master
> - update proper commit message
> - dropped unneeded comments
> - order the patches that make review easy
> Changes for v5:
> - collect Rob, Acked-by
> - droped "Fix VBP size calculation" patch
> - updated vblk timing calculation.
> - droped techstar, bananapi dsi panel drivers which may require
> bridge or other setup. it's under discussion.
> Changes for v4:
> - droppoed untested CCU_FEATURE_FIXED_POSTDIV check code in
> nkm min, max rate patches
> - create two patches for "Add Allwinner A64 MIPI DSI support"
> one for has_mod_clk quirk and other one for A64 support
> - use existing driver code construct for hblk computation
> - dropped "Increase hfp packet overhead" patch [2], though BSP added
> this but we have no issues as of now.
> (no issues on panel side w/o this change)
> - create separate function for vblk computation
> - enable vcc-dsi regulator in dsi_runtime_resume
> - collect Rob, Acked-by
> - update MAINTAINERS file for panel drivers
> - cleanup commit messages
> - fixed checkpatch warnings/errors
>
> [1] https://patchwork.kernel.org/cover/10779893/
>
> Any inputs?
> Jagan.
>
> Jagan Teki (23):
> drm/sun4i: sun6i_mipi_dsi: Compute burst mode loop N1 instruction
> delay
> drm/sun4i: sun6i_mipi_dsi: Support instruction loop selection
> drm/sun4i: sun6i_mipi_dsi: Setup burst mode timings
> drm/sun4i: sun6i_mipi_dsi: Simplify drq to support all modes
> drm/sun4i: tcon: Export get tcon0 routine
> drm/sun4i: sun6i_mipi_dsi: Probe tcon0 during dsi_bind
> drm/sun4i: sun6i_mipi_dsi: Setup burst mode
> drm/sun4i: sun6i_mipi_dsi: Enable trail_inv and trail_fill controls
> drm/sun4i: sun6i_mipi_dsi: Enable HBP, HSA_HSE for burst mode

Can you pick these burst changes which are generic to all SoCs. and
reset will send once we decide the tcon clock.

Maxime Ripard

unread,
Feb 13, 2019, 4:03:14 AM2/13/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
These patches don't implement what we discussed last week, and as I
told you already, most of them really need some work on the commit log
and their explanations.
signature.asc

Jagan Teki

unread,
Feb 13, 2019, 4:19:35 AM2/13/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
If I'm not wrong, we discussed about tcon_dclk (PLL_MIPI) last week
[1] and these burst changes between 01/23 to 09/23 which are generic
changes to DSI and not related to clock. Apart from that I made few
changes on commit logs between the versions (which I was mentioned on
the cover-letter patch). If any issues issues on commit message,
please let me know so-that I can rework.

[1] https://patchwork.kernel.org/patch/10780041/

Jagan Teki

unread,
Feb 14, 2019, 11:41:58 AM2/14/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-...@amarulasolutions.com, linux-sunxi
Look like the same discussion rounding since from months. In fact I
have grouped all changes by 'sets of patches' in this series which I
was thinking of having more feasibility to review and merge, but seems
like it ended-up fusing which patches are more prior and which are
fixes. So, let me send it by breaking into different series based on
the issues and generic changes.

Jagan Teki

unread,
May 24, 2019, 6:07:56 AM5/24/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
Let me explain, something more.

According to bsp there are clk_info.tcon_div which I will explain below.
clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
is 6 for 24bpp and 4 lanes devices.

PLL rate here depends on dsi_div (not tcon_div)

Code here
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784

is computing the actual set rate, which depends on dsi_rate.

lcd_rate = dclk_rate * clk_info.dsi_div;
dsi_rate = pll_rate / clk_info.dsi_div;

Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
for above link you mentioned.

Here are the evidence with some prints.

https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a

>
> Let's take a step back now: that function we were looking at,
> lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> by disp_lcd_enable here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
>
> The next function being called is disp_al_lcd_cfg, and that function
> will hardcode the TCON dotclock divider to 4, here:
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240

tcon_div from BSP point-of-view of there are two variants
00) clk_info.tcon_div which is 4 and same is set the divider position
in SUN4I_TCON0_DCLK_REG (like above link refer)
01) tcon_div which is 4 and used for edge timings computation
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12

The real reason for 01) is again 4 is they set the divider to 4 in 00)
which is technically wrong because the dividers which used during
dotclock in above (dsi_div) should be used here as well. Since there
is no dynamic way of doing this BSP hard-coding these values.

Patches 5,6,7 on this series doing this
https://patchwork.freedesktop.org/series/60847/

Hope this explanation helps?

Maxime Ripard

unread,
Jun 5, 2019, 2:49:41 AM6/5/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
Hi,

I've reordered the mail a bit to work on chunks

On Fri, May 24, 2019 at 03:37:42PM +0530, Jagan Teki wrote:
> > I wish it was in your commit log in the first place, instead of having
> > to exchange multiple mails over this.
> >
> > However, I don't think that's quite true, and it might be a bug in
> > Allwinner's implementation (or rather something quite confusing).
> >
> > You're right that the lcd_rate and pll_rate seem to be generated from
> > the pixel clock, and it indeed looks like the ratio between the pixel
> > clock and the TCON dotclock is defined through the number of bits per
> > lanes.
> >
> > However, in this case, dsi_rate is actually the same than lcd_rate,
> > since pll_rate is going to be divided by dsi_div:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L791
> >
> > Since lcd_div is 1, it also means that in this case, dsi_rate ==
> > dclk_rate.
> >
> > The DSI module clock however, is always set to 148.5 MHz. Indeed, if
> > we look at:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L804
> >
> > We can see that the rate in clk_info is used if it's different than
> > 0. This is filled by disp_al_lcd_get_clk_info, which, in the case of a
> > DSI panel, will hardcode it to 148.5 MHz:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L164
>
> Let me explain, something more.
>
> According to bsp there are clk_info.tcon_div which I will explain below.
> clk_info.dsi_div which is dynamic and it depends on bpp/lanes, so it
> is 6 for 24bpp and 4 lanes devices.
>
> PLL rate here depends on dsi_div (not tcon_div)
>
> Code here
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L784
>
> is computing the actual set rate, which depends on dsi_rate.
>
> lcd_rate = dclk_rate * clk_info.dsi_div;
> dsi_rate = pll_rate / clk_info.dsi_div;
>
> Say if the dclk_rate 148MHz then the dsi_rate is 888MHz which set rate
> for above link you mentioned.
>
> Here are the evidence with some prints.
>
> https://gist.github.com/openedev/9bae2d87d2fcc06b999fe48c998b7043
> https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a

Ok, so we agree up to this point, and the prints confirm that the
analysis above is the right one.
Your patch doesn't address that, so let's leave that one alone.

> > The TCON *module* clock (the one in the clock controller) has been set
> > to lcd_rate (so the pixel clock times the number of bits per lane) here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L800
> >
> > And the PLL has been set to the same rate here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L794
> >
> > Let's take a step back now: that function we were looking at,
> > lcd_clk_config, is called by lcd_clk_enable, which is in turn called
> > by disp_lcd_enable here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L1328
> >
> > The next function being called is disp_al_lcd_cfg, and that function
> > will hardcode the TCON dotclock divider to 4, here:
> > https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/disp_al.c#L240
>
> tcon_div from BSP point-of-view of there are two variants
> 00) clk_info.tcon_div which is 4 and same is set the divider position
> in SUN4I_TCON0_DCLK_REG (like above link refer)
> 01) tcon_div which is 4 and used for edge timings computation
> https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/lowlevel_sun50iw1/de_dsi.c#L12
>
> The real reason for 01) is again 4 is they set the divider to 4 in 00)
> which is technically wrong because the dividers which used during
> dotclock in above (dsi_div) should be used here as well. Since there
> is no dynamic way of doing this BSP hard-coding these values.
>
> Patches 5,6,7 on this series doing this
> https://patchwork.freedesktop.org/series/60847/
>
> Hope this explanation helps?

It doesn't.

The clock tree is this one:

PLL(s) -> TCON module clock -> TCON dotclock.

The links I mentioned above show that the clock set to lcd_rate is the
TCON module clocks (and it should be the one taking the bpp and lanes
into account), while the TCON dotclock uses a fixed divider of 4.

In your patches, you're using the bpp / lanes divider on the TCON
dotclock, ie, the wrong clock.

Again, I'm not saying that my analysis of the source code is correct
here. But you haven't said anything to prove it's wrong either.
signature.asc

Jagan Teki

unread,
Jun 5, 2019, 3:33:32 AM6/5/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
Basically this is final pll set rate when sun4i_dotclock.c called the
desired rate with ccu_nkm.c so it ended the final rate with parent as
Line 8 of
https://gist.github.com/openedev/700de2e3701b2bf3ad1aa0f0fa862c9a
Sorry, I can argue much other-than giving some code snips, according to [1]

00) Line 785, 786 with dclk_rate 148000000

lcd_rate = dclk_rate * clk_info.dsi_div;
pll_rate = lcd_rate * clk_info.lcd_div;

Since dsi_div is 6 (bpp/lanes), lcd_div 1

lcd_rate = 888000000, pll_rate = 888000000

01) Line 801, 804 are final rates computed as per clock driver (say
ccu_nkm in mainline)

lcd_rate_set=891000000

As per your comments if it would be 4 then the desired numbers are
would be 592000000 not 888000000.

This is what I'm trying to say in all mails, and same as verified with
2-lanes devices as well where the dsi_div is 12 so the final rate is
290MHz * 12

>
> In your patches, you're using the bpp / lanes divider on the TCON
> dotclock, ie, the wrong clock.
>
> Again, I'm not saying that my analysis of the source code is correct
> here. But you haven't said anything to prove it's wrong either.

Don't understand what proves are remaining, I have explained each line
from BSP and saying pll rate is depends on dsi_div which is bpp/lanes
not wrt tcon_div on BSP (which is set to default 4) and which indeed
verified in A33, R40. all the code using bpp/lanes.

Please let me know if you need any more information to look?

[1] https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L805

Maxime Ripard

unread,
Jun 14, 2019, 10:24:13 AM6/14/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
If that's important to the driver, it should be set explicitly then,
and not work by accident.
In the code you sent, you're forcing a divider on the internal TCON
clock, while that one is fixed in the BSP.

There's indeed the bpp / lanes divider, but it's used in the *parent*
clock of the one you're changing.

And the dsi0_clk clock you pointed out in the code snippet is yet
another clock, the MIPI DSI module clock.

The analysis you have is probably correct, you're just not
implementing it properly in your patch.
signature.asc

Jagan Teki

unread,
Jun 20, 2019, 2:27:59 PM6/20/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
Correct, look like I refereed wrong reference in the above mail. sorry
for the noise.

Actually I'm trying to explain about pll_rate here which indeed
depends on dsi.div
https://github.com/BPI-SINOVOIP/BPI-M64-bsp/blob/master/linux-sunxi/drivers/video/sunxi/disp2/disp/de/disp_lcd.c#L786

lcd_rate = dclk_rate * clk_info.dsi_div;
pll_rate = lcd_rate * clk_info.lcd_div;

Say

1) For 148MHz dclk_rate with dsi_div is 6 (24/4) lcd_div is 1 which
resulting pll_rate is 888MHz.

2) For 30MHz dclk_rate with 4 lane and 24 RGB the resulting pll_rate is 180MHz

3) For 27.5MHz dclk_rate with 2 lane and 24 RGB the resulting pll_rate is 330MHz

Here is the few more logs in code, for case 2)

[ 1.920441] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
[ 1.920505] ideal = 180000000, rounded = 178200000
[ 1.920509] sun4i_dclk_round_rate: div = 6 rate = 29700000
[ 1.920514] sun4i_dclk_round_rate: min_div = 6 max_div = 6, rate = 30000000
[ 1.920532] ideal = 180000000, rounded = 178200000
[ 1.920535] sun4i_dclk_round_rate: div = 6 rate = 29700000
[ 1.920572] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
[ 1.920576] sun4i_dclk_recalc_rate: val = 1, rate = 178200000
[ 1.920597] rate = 178200000
[ 1.920599] parent_rate = 297000000
[ 1.920602] reg = 0x90c00000
[ 1.920605] _nkm.n = 3, nkm->n.offset = 0x1, nkm->n.shift = 8
[ 1.920609] _nkm.k = 2, nkm->k.offset = 0x1, nkm->k.shift = 4
[ 1.920612] _nkm.m = 10, nkm->m.offset = 0x1, nkm->m.shift = 0
[ 1.920958] sun4i_dclk_set_rate div 6
[ 1.920966] sun4i_dclk_recalc_rate: val = 6, rate = 29700000

and clk_summary:

pll-video0 1 1 1 297000000
0 0 50000
hdmi 0 0 0 297000000
0 0 50000
tcon1 0 0 0 297000000
0 0 50000
pll-mipi 1 1 1 178200000
0 0 50000
tcon0 2 2 1 178200000
0 0 50000
tcon-pixel-clock 1 1 1 29700000
0 0 50000
pll-video0-2x 0 0 0 594000000
0 0 50000

Maxime Ripard

unread,
Jun 25, 2019, 10:49:36 AM6/25/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
This discussion is going nowhere. I'm telling you that your patch
doesn't apply the divider you want on the proper clock, and you're
replying that indeed, you're applying it on the wrong clock.

It might work by accident in your case, but the board I have here
clearly indicates otherwise, so there's two possible way out here:

- Either you apply that divider to the TCON *module* clock, and not
the dclk

- Or you point to somewhere in the allwinner code where the bpp /
lanes divider is used for the dclk divider.


Maxim
signature.asc

Jagan Teki

unread,
Jun 25, 2019, 11:30:50 AM6/25/19
to Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
I don't know how to proceed further on this, as you say it might work
in accident but I have tested this in A33, A64 and R40 with 4
different DSI panels and one DSI-RGB bridge. All of them do use
PLL_MIPI (pll_rate) and it indeed depends on bpp/lanes

4-lane, 24-bit: Novatek NT35596 panel
4-lane, 24-bit: Feiyang, FY07024di26a30d panel
4-lane, 24-bit: Bananapi-s070wv20 panel
2-lane, 24-bit: Techstar,ts8550b panel

and

4-lane, 24-bit, ICN6211 DSI-to-RGB bridge panel

All above listed panels and bridges are working as per BSP and do
follow bpp/lanes and for DIVIDER 4 no panel is working.

The panels/bridges I have has tested in BSP and as you mentioned in
another mail, your panel is not tested in BSP - this is the only
difference. I did much reverse-engineering on PLL_MIPI clocking in BSP
so I'm afraid what can I do next on this, If you want to look further
on BSP I would suggest to verify on pll_rate side. If you feel
anything I'm missing please let me know.

Jagan.

Maxime Ripard

unread,
Jul 3, 2019, 7:49:39 AM7/3/19
to Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, Michael Trimarchi, linux-amarula, linux-sunxi
Look. I'm not saying that there's no issue, I'm saying that your
patch, applied to the clock you're applying it to, doesn't make sense
and isn't what the BSP does.

You can keep on arguing that your patch is perfect as is, but the fact
that there's regressions proves otherwise.

> The panels/bridges I have has tested in BSP and as you mentioned in
> another mail, your panel is not tested in BSP - this is the only
> difference. I did much reverse-engineering on PLL_MIPI clocking in BSP
> so I'm afraid what can I do next on this, If you want to look further
> on BSP I would suggest to verify on pll_rate side. If you feel
> anything I'm missing please let me know.

I already told you how we can make some progress in the mail you
quoted, but you chose to ignore that.

Until there's been some progress on either points mentionned above,
I'm just going to stop answering on this topic.

Maxime
signature.asc

Michael Nazzareno Trimarchi

unread,
Jul 5, 2019, 1:52:40 PM7/5/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Maxime
> > > > [ 1.920532] ideal = 1800ls and one DSI-RGB bridge. All of them do use
tcon-pixel clock is the rate that you want to achive on display side and
if you have 4 lanes 32bit or lanes and different bit number that you need
to have a clock that is able to put outside bits and speed equal to
pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
and you have 32bits and 4 lanes you need to have a clock of
40 * 32 / 4 in no-burst mode. I think that this is done but most of the display.
Now in burst mode I don't know how should work the calculation of the
clock for the
require bandwidth and even I understand your comment I would like to have your
clock tree after you boot on the display side and if it is possible I
want to assemble a kit
like you have.

>
> You can keep on arguing that your patch is perfect as is, but the fact
> that there's regressions proves otherwise.
>

Well when you push your code you said that you have tested on more
then one display.
Can I know where are the others?

> > The panels/bridges I have has tested in BSP and as you mentioned in

> > another mail, your panel is not tested in BSP - this is the only
> > difference. I did much reverse-engineering on PLL_MIPI clocking in BSP
> > so I'm afraid what can I do next on this, If you want to look further
> > on BSP I would suggest to verify on pll_rate side. If you feel
> > anything I'm missing please let me know.
>
> I already told you how we can make some progress in the mail you
> quoted, but you chose to ignore that.
>

Yes, the idea is to make progress. Thank you about your helping

Michael

> Until there's been some progress on either points mentionned above,
> I'm just going to stop answering on this topic.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com



--
| Michael Nazzareno Trimarchi Amarula Solutions BV |
| COO - Founder Cruquiuskade 47 |
| +31(0)851119172 Amsterdam 1018 AM NL |
| [`as] http://www.amarulasolutions.com |

Maxime Ripard

unread,
Jul 11, 2019, 8:23:10 AM7/11/19
to Michael Nazzareno Trimarchi, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
So this is what the issue is then?

This one does make sense, and you should just change the rate in the
call to clk_set_rate in sun4i_tcon0_mode_set_cpu.

I'm still wondering why that hasn't been brought up in either the
discussion or the commit log before though.

> Now in burst mode I don't know how should work the calculation of
> the clock for the require bandwidth and even I understand your
> comment I would like to have your clock tree after you boot on the
> display side and if it is possible I want to assemble a kit like you
> have.

The setup is probably going to be a bit difficult to reproduce, it's a
prototype that I have that can't really be found anywhere. Jagan asked
me on IRC for the reference, and he found the part, but it's unclear
to me if it can be easily adapted to a common board.

However, I'm not even sure we need this. I'll test the next version
and let you know if it works.
signature.asc

Michael Nazzareno Trimarchi

unread,
Jul 11, 2019, 1:43:31 PM7/11/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Maxime
Something like this?

drivers/gpu/drm/sun4i/sun4i_tcon.c | 20 +++++++++++---------
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 2 --
2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 64c43ee6bd92..42560d5c327c 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -263,10 +263,11 @@ static int sun4i_tcon_get_clk_delay(const struct
drm_display_mode *mode,
}

static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
- const struct drm_display_mode *mode)
+ const struct drm_display_mode *mode,
+ u32 tcon_mul)
{
/* Configure the dot clock */
- clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+ clk_set_rate(tcon->dclk, mode->crtc_clock * tcon_mul * 1000);

/* Set the resolution */
regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
@@ -335,12 +336,13 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
u8 lanes = device->lanes;
u32 block_space, start_delay;
- u32 tcon_div;
+ u32 tcon_div, tcon_mul;

- tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
- tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+ tcon->dclk_min_div = 4;
+ tcon->dclk_max_div = 127;

- sun4i_tcon0_mode_set_common(tcon, mode);
+ tcon_mul = bpp / lanes;
+ sun4i_tcon0_mode_set_common(tcon, mode, tcon_mul);

/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -366,7 +368,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
*/
regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
tcon_div &= GENMASK(6, 0);
- block_space = mode->htotal * bpp / (tcon_div * lanes);
+ block_space = mode->htotal * tcon_div * tcon_mul;
block_space -= mode->hdisplay + 40;

regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
@@ -408,7 +410,7 @@ static void sun4i_tcon0_mode_set_lvds(struct
sun4i_tcon *tcon,

tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
- sun4i_tcon0_mode_set_common(tcon, mode);
+ sun4i_tcon0_mode_set_common(tcon, mode, 1);

/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
@@ -487,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
sun4i_tcon *tcon,

tcon->dclk_min_div = 6;
tcon->dclk_max_div = 127;
- sun4i_tcon0_mode_set_common(tcon, mode);
+ sun4i_tcon0_mode_set_common(tcon, mode, 1);

/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, connector);
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 5c3ad5be0690..a07090579f84 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,8 +13,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>

-#define SUN6I_DSI_TCON_DIV 4
-
struct sun6i_dsi {
struct drm_connector connector;
struct drm_encoder encoder;


> > Now in burst mode I don't know how should work the calculation of
> > the clock for the require bandwidth and even I understand your
> > comment I would like to have your clock tree after you boot on the
> > display side and if it is possible I want to assemble a kit like you
> > have.
>
> The setup is probably going to be a bit difficult to reproduce, it's a
> prototype that I have that can't really be found anywhere. Jagan asked
> me on IRC for the reference, and he found the part, but it's unclear
> to me if it can be easily adapted to a common board.
>
> However, I'm not even sure we need this. I'll test the next version
> and let you know if it works.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com



Michael Nazzareno Trimarchi

unread,
Jul 11, 2019, 3:35:10 PM7/11/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi
Maybe wrong clock ;) but is this your idea?

Michael

Maxime Ripard

unread,
Jul 20, 2019, 2:58:35 AM7/20/19
to Michael Nazzareno Trimarchi, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
I had more something like this in mind:
http://code.bulix.org/nlp5a4-803511

You really don't need to change the divider range (or this is another
issue that the one you mentionned).
signature.asc

Jagan Teki

unread,
Jul 20, 2019, 3:16:41 AM7/20/19
to Maxime Ripard, Michael Nazzareno Trimarchi, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Worth to look at it. was it working on your panel? meanwhile I will check it.

We have updated with below change [1], seems working on but is
actually checking the each divider as before start with 4... till 127.

This new approach, is start looking the best divider from 4.. based on
the idea vs rounded it will ended up best divider like [2]

https://gist.github.com/openedev/7e2c33248b372d29be9979e06d483673
https://gist.github.com/openedev/c72dfffc0ca59e7ec1edcd7ad360cdd1

Jagan.

Michael Nazzareno Trimarchi

unread,
Jul 20, 2019, 3:20:37 AM7/20/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi
I sent another patch to jagan and I'm fully agree that the proper change need to show the reason and not change constraints as we discuss

We are on same line

Thank you

Jagan Teki

unread,
Jul 20, 2019, 3:35:12 AM7/20/19
to Maxime Ripard, Michael Nazzareno Trimarchi, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
I made quick check on two possibilities.

1) with Maxime change
https://gist.github.com/openedev/3b0b3d35ced6d89f5be0831f1cc9d840
https://gist.github.com/openedev/dd6a9e528cde80ef0508cb54723f505d

2) with Maxime change along with min 4, max 127 divider values.
The outcome similar like 1)

This look it will depends on divider, need to check further on this page.

Jagan.

Maxime Ripard

unread,
Jul 20, 2019, 5:32:08 AM7/20/19
to Jagan Teki, Michael Nazzareno Trimarchi, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
I haven't tested it.

> We have updated with below change [1], seems working on but is
> actually checking the each divider as before start with 4... till 127.
>
> This new approach, is start looking the best divider from 4.. based on
> the idea vs rounded it will ended up best divider like [2]

But why?

I mean, it's not like it's the first time I'm asking this...

If the issue is what Micheal described, then the divider has nothing
to do with it. We've had that discussion over and over again.

So you need to come with some argument and proof that the divider of
that clock need to change. Otherwise, stop trying to make that happen:
it won't.
signature.asc

Michael Nazzareno Trimarchi

unread,
Jul 20, 2019, 5:43:03 AM7/20/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi

On Sat, Jul 20, 2019 at 11:32 AM Maxime Ripard
Sorry to quick copy and paste but my idea is somenthing like:

---
drivers/gpu/drm/sun4i/sun4i_dotclock.c | 5 ++++-
drivers/gpu/drm/sun4i/sun4i_tcon.c | 9 ++++++---
drivers/gpu/drm/sun4i/sun4i_tcon.h | 1 +
drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 2 --
4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index 417ade3d2565..b8be67cbb037 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -74,12 +74,15 @@ static long sun4i_dclk_round_rate(struct clk_hw
*hw, unsigned long rate,
struct sun4i_tcon *tcon = dclk->tcon;
unsigned long best_parent = 0;
u8 best_div = 1;
+ u64 ideal = (u64)rate * tcon->dclk_mul;
int i;

for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
- u64 ideal = (u64)rate * i;
unsigned long rounded;

+ if (!tcon->dclk_mul)
+ ideal = (u64)rate * i;
+
/*
* ideal has overflowed the max value that can be stored in an
* unsigned long, and every clk operation we might do on a
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 64c43ee6bd92..3301952bcf32 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -337,8 +337,9 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
u32 block_space, start_delay;
u32 tcon_div;

- tcon->dclk_min_div = SUN6I_DSI_TCON_DIV;
- tcon->dclk_max_div = SUN6I_DSI_TCON_DIV;
+ tcon->dclk_min_div = 4;
+ tcon->dclk_max_div = 127;
+ tcon->dclk_mul = bpp / lanes;

sun4i_tcon0_mode_set_common(tcon, mode);

@@ -366,7 +367,7 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
*/
regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div);
tcon_div &= GENMASK(6, 0);
- block_space = mode->htotal * bpp / (tcon_div * lanes);
+ block_space = mode->htotal * tcon_div * tcon->dclk_mul;
block_space -= mode->hdisplay + 40;

regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG,
@@ -408,6 +409,7 @@ static void sun4i_tcon0_mode_set_lvds(struct
sun4i_tcon *tcon,

tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7;
+ tcon->dclk_mul = 0;
sun4i_tcon0_mode_set_common(tcon, mode);

/* Set dithering if needed */
@@ -487,6 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct
sun4i_tcon *tcon,

tcon->dclk_min_div = 6;
tcon->dclk_max_div = 127;
+ tcon->dclk_mul = 0;
sun4i_tcon0_mode_set_common(tcon, mode);

/* Set dithering if needed */
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h
b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index f9f1fe80b206..44b69533778e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -248,6 +248,7 @@ struct sun4i_tcon {
struct clk *dclk;
u8 dclk_max_div;
u8 dclk_min_div;
+ u8 dclk_mul;

/* Reset control */
struct reset_control *lcd_rst;
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index 5c3ad5be0690..a07090579f84 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -13,8 +13,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>

-#define SUN6I_DSI_TCON_DIV 4
-
struct sun6i_dsi {
struct drm_connector connector;
struct drm_encoder encoder;
--
2.17.1


Michael

> So you need to come with some argument and proof that the divider of
> that clock need to change. Otherwise, stop trying to make that happen:
> it won't.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com



Jagan Teki

unread,
Jul 22, 2019, 6:21:19 AM7/22/19
to Maxime Ripard, Michael Nazzareno Trimarchi, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Maxime,
This is what Michael is mentioned in above mail
"tcon-pixel clock is the rate that you want to achive on display side and
if you have 4 lanes 32bit or lanes and different bit number that you need
to have a clock that is able to put outside bits and speed equal to
pixel-clock * bits / lanes. so If you want a pixel-clock of 40 mhz
and you have 32bits and 4 lanes you need to have a clock of
40 * 32 / 4 in no-burst mode. "

He is trying to manage the bpp/lanes into dclk_mul (in last mail) and
it can multiply with pixel clock which is rate argument in
sun4i_dclk_round_rate.

The solution I have mentioned in dclk_min, max is bpp/lanes also
multiple rate in dotclock sun4i_dclk_round_rate.

In both cases the overall pll_rate depends on dividers, the one that I
have on this patch is based on BSP and the Michael one is more generic
way so-that it can not to touch other functionalities and looping
dividers to find the best one.

If dclk_min/max is bpp/lanes then dotclock directly using divider 6
(assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
associated.

if dclk_mul is bpp/lanes, on Michael new change, the dividers start
with 4 and end with 127 but the constant ideal rate which rate *
bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
as 6 only, ie what I'm mentioned on the above mail.

Jagan.

Michael Nazzareno Trimarchi

unread,
Jul 22, 2019, 6:25:17 AM7/22/19
to Jagan Teki, Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Jagan
tcon-pixel clock and tcon are mutual connected. The code is done in a way
that optimal clock need to be search. Now the patch that I propose is more
connected to the description I gave.

I need some comment from Maxime, what he prefers or we need to search for
a different one. I don't had time to check Maxime proposal because I'm working
on other projects.

Michael

> Jagan.

Jagan Teki

unread,
Jul 22, 2019, 6:39:03 AM7/22/19
to Michael Nazzareno Trimarchi, Maxime Ripard, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
True, ie what I'm trying to say in above mail. My idea on the above
mail is to give more information on the both the solutions (one on the
this patch and another you mentioned on above mail) are depends on
divider value for computing desired pll_rate.

>
> I need some comment from Maxime, what he prefers or we need to search for
> a different one. I don't had time to check Maxime proposal because I'm working
> on other projects.

I already provide my logs on Maxime change.if you want you can have a look.

Maxime Ripard

unread,
Jul 24, 2019, 5:05:26 AM7/24/19
to Jagan Teki, Michael Nazzareno Trimarchi, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Yeah, so we need to change the clock rate.

> He is trying to manage the bpp/lanes into dclk_mul (in last mail)
> and it can multiply with pixel clock which is rate argument in
> sun4i_dclk_round_rate.
>
> The solution I have mentioned in dclk_min, max is bpp/lanes also
> multiple rate in dotclock sun4i_dclk_round_rate.
>
> In both cases the overall pll_rate depends on dividers, the one that I
> have on this patch is based on BSP and the Michael one is more generic
> way so-that it can not to touch other functionalities and looping
> dividers to find the best one.
>
> If dclk_min/max is bpp/lanes then dotclock directly using divider 6
> (assuming 24-bit and 4 lanes) and return the pll_rate and divider 6
> associated.
>
> if dclk_mul is bpp/lanes, on Michael new change, the dividers start
> with 4 and end with 127 but the constant ideal rate which rate *
> bpp/lanes but the loop from sun4i_dclk_round_rate computed the divider
> as 6 only, ie what I'm mentioned on the above mail.

We've been over this a couple of times already.

The clock is generated like this:

PLL -> TCON Module Clock -> TCON DCLK

You want the TCON DCLK to be at the pixel clock rate * bpp /
lanes. Fine, that makes sense.

Except that the patch you've sent, instead of changing the rate
itself, changes the ratio between the module clock and DCLK.

And this is where the issue lies. First, from a logical viewpoint, it
doesn't make sense. If you want to change the clock rate, then just do
it. Don't hack around the multipliers trying to fall back to something
that works for you.

Then, the ratio itself needs to be set to 4. This is the part that
we've discussed way too many times already, but in the Allwinner BSP,
that ratio is hardcoded to 4, and we've had panels that need it at
that value.

So, what you want to do is to have:

TCON DCLK = pixel clock * bpp / lanes
TCON Module Clock = DCLK * 4
PLL = Module Clock * Module Clock Divider (which I believe is 1 in most cases)

So you want to increase the PLL. Fortunately for use, this is exactly
what a call to clk_set_rate will end up doing.
signature.asc

Michael Nazzareno Trimarchi

unread,
Jul 29, 2019, 2:59:18 AM7/29/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi

On Wed, Jul 24, 2019 at 11:05 AM Maxime Ripard
pll-mipi 1 1 1 178200000
0 0 50000
tcon0 2 2 1 178200000
0 0 50000
tcon-pixel-clock 1 1 1 29700000
0 0 50000

This is an english problem from my side:
tcon-pixel-clock is DCLK
tcon0 must be tcon-pixel-clock * bpp / lanes because the logic need to
put a bit every cycle.

One solution can be:
- set_rate_exclusive to tcon0 and calculate as display pixel clock *
bpp / lanes
- calculate the tcon-pixel-clock using all divider

Problem is that the function that calculate tcon-pixel-clock does not
have any constrain on the ideal value. What you are
suggesting is not correct in my opinion or I'm not following your
suggesstion. What I know is that if we have a pixel-clock
of dvi display of 50Mhz and we have 4 lanes 32bit we need a clock in
the logic of 400Mhz (this is the ideal throughtput).
So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.

Michael


>
> So you want to increase the PLL. Fortunately for use, this is exactly
> what a call to clk_set_rate will end up doing.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com



Michael Nazzareno Trimarchi

unread,
Aug 2, 2019, 4:38:56 AM8/2/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Maxime
index 94f24c5e2dc5..ffb7906054e5 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -338,8 +338,9 @@ static void sun4i_tcon0_mode_set_cpu(struct
sun4i_tcon *tcon,
u32 block_space, start_delay;
u32 tcon_div;

- tcon->dclk_min_div = bpp/lanes;
- tcon->dclk_max_div = bpp/lanes;
+ tcon->dclk_min_div = 4;
+ tcon->dclk_max_div = 127;
+ clk_set_rate_exclusive(tcon->sclk0, mode->crtc_clock * 1000 * bpp / lanes);

sun4i_tcon0_mode_set_common(tcon, mode);

Something like this on top of jagan proposal

Michael

Maxime Ripard

unread,
Aug 13, 2019, 2:05:08 AM8/13/19
to Michael Nazzareno Trimarchi, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Is this before or after your patches?

> This is an english problem from my side:
> tcon-pixel-clock is DCLK
> tcon0 must be tcon-pixel-clock * bpp / lanes, because the logic need to
> put a bit every cycle.

Again, I'm not saying this is wrong, but each time I've looked at it
the BSP was using a 4 divider between the tcon module clock and the
dotclock.

So, please prove me wrong here.

> One solution can be:
> - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> bpp / lanes

I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
good idea to use it, but it shouldn't really change anything to the
discussion.

> - calculate the tcon-pixel-clock using all divider

I'm not sure what you mean by that.

> Problem is that the function that calculate tcon-pixel-clock does not
> have any constrain on the ideal value.

It does have constraints, but you're right that it will not try to
find an exact match and bail out if it can't do it, but will find the
closest match.

> What you are suggesting is not correct in my opinion or I'm not
> following your suggesstion.

Then prove me wrong.

> What I know is that if we have a pixel-clock of dvi display of 50Mhz
> and we have 4 lanes 32bit we need a clock in the logic of 400Mhz
> (this is the ideal throughtput).
> So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.

There's one thing to keep in mind though. The TCON dotclock in the
MIPI-DSI case isn't directly tied to the Bit Clock, it's simply an
internal clock in the pipeline to feed the FIFO of the MIPI-DSI
controller. The MIPI-DSI controller itself will generate that clock,
and only that one will have those constraints.

Michael Nazzareno Trimarchi

unread,
Aug 15, 2019, 8:26:11 AM8/15/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Maxime
This is just an example of clock tree to be clear to everyone how they
are connected

> > This is an english problem from my side:
> > tcon-pixel-clock is DCLK
> > tcon0 must be tcon-pixel-clock * bpp / lanes, because the logic need to
> > put a bit every cycle.
>
> Again, I'm not saying this is wrong, but each time I've looked at it
> the BSP was using a 4 divider between the tcon module clock and the
> dotclock.
>

We have tested on 4-5 displays. Well I don't care on bsp but I care
about if it works
and if other SoC has similar approach on clock calculation.

> So, please prove me wrong here.
>

Having only 10 pages of documentation is a bit difficult.

> > One solution can be:
> > - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> > bpp / lanes
>
> I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
> good idea to use it, but it shouldn't really change anything to the
> discussion.

Well, this will just do a minimal change on source code and put the constrains
to the tcon0

>
> > - calculate the tcon-pixel-clock using all divider
>
> I'm not sure what you mean by that.
>
> > Problem is that the function that calculate tcon-pixel-clock does not
> > have any constrain on the ideal value.
>
> It does have constraints, but you're right that it will not try to
> find an exact match and bail out if it can't do it, but will find the
> closest match.
>

We need to find the closest divider that match the pixel clock and be close
to the ideal tcon0 rate.


> > What you are suggesting is not correct in my opinion or I'm not
> > following your suggesstion.
>
> Then prove me wrong.
>
> > What I know is that if we have a pixel-clock of dvi display of 50Mhz
> > and we have 4 lanes 32bit we need a clock in the logic of 400Mhz
> > (this is the ideal throughtput).
> > So tcon-pixel-clock is 50mhz and tcon0 is 400Mhz.
>
> There's one thing to keep in mind though. The TCON dotclock in the
> MIPI-DSI case isn't directly tied to the Bit Clock, it's simply an
> internal clock in the pipeline to feed the FIFO of the MIPI-DSI
> controller. The MIPI-DSI controller itself will generate that clock,
> and only that one will have those constraints.
>

I have done the same thinking but because it works for us seems that
somehow is used
to internal logic too

Michael

> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com



Maxime Ripard

unread,
Aug 28, 2019, 9:03:47 AM8/28/19
to Michael Nazzareno Trimarchi, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi,
Well, it's also breaking another panel.

> > So, please prove me wrong here.
>
> Having only 10 pages of documentation is a bit difficult.

The BSP source code will be a fine example too.

> > > One solution can be:
> > > - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> > > bpp / lanes
> >
> > I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
> > good idea to use it, but it shouldn't really change anything to the
> > discussion.
>
> Well, this will just do a minimal change on source code and put the constrains
> to the tcon0

I agree, but again, this has nothing to do with the current discussion.
signature.asc

Michael Nazzareno Trimarchi

unread,
Aug 28, 2019, 9:10:03 AM8/28/19
to Maxime Ripard, Jagan Teki, David Airlie, Daniel Vetter, Chen-Yu Tsai, Michael Turquette, Rob Herring, Mark Rutland, linux-arm-kernel, linux-kernel, linux-clk, dri-devel, devicetree, linux-amarula, linux-sunxi
Hi Maxime
Agree but I need to have the panel. Do you know if we have users of this panel?
I don't want to break the users off course. Can I have your clk_tree
dbg of your devices
the panel datasheet?

> > > So, please prove me wrong here.
> >
> > Having only 10 pages of documentation is a bit difficult.
>
> The BSP source code will be a fine example too.
>

Do you have any contact in allwinner?

Let's be this last email, I don't want to bother the people more.
After I get the panel
info and datasheet I will come back if I found a solution that does not break it

Michael

> > > > One solution can be:
> > > > - set_rate_exclusive to tcon0 and calculate as display pixel clock *
> > > > bpp / lanes
> > >
> > > I'm not sure what set_rate_exclusive has to do with it. I mean, it's a
> > > good idea to use it, but it shouldn't really change anything to the
> > > discussion.
> >
> > Well, this will just do a minimal change on source code and put the constrains
> > to the tcon0
>
> I agree, but again, this has nothing to do with the current discussion.
>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com



Reply all
Reply to author
Forward
0 new messages