* [RFC PATCH 01/12] drm: Add a new mode flag: DRM_MODE_FLAG_PREFER_ONE_SHOT
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2015-05-11 1:38 ` Mark Zhang
[not found] ` <1431308311-4470-2-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-05-11 1:38 ` [RFC PATCH 02/12] drm: panel: Add one-shot flag to Sharp lq101r1sx01 driver Mark Zhang
` (10 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Normally this flag is set by panel driver so that crtc can enable
the "one-shot" mode(not scan frames continuously).
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
include/uapi/drm/drm_mode.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index dbeba949462a..5447a338e893 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -72,6 +72,7 @@
#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14)
#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14)
#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
+#define DRM_MODE_FLAG_PREFER_ONE_SHOT (1<<19)
/* DPMS flags */
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 02/12] drm: panel: Add one-shot flag to Sharp lq101r1sx01 driver
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-05-11 1:38 ` [RFC PATCH 01/12] drm: Add a new mode flag: DRM_MODE_FLAG_PREFER_ONE_SHOT Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 03/12] drm: panel: Turn on TE(Tearing Effect) on Sharp lq101r1sx01 Mark Zhang
` (9 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Sharp lq101r1sx01 has internal framebuffer so it doesn't
require crtc sending frames to it continuously.
So set the one-shot flag in the driver.
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 3cce3ca19601..19a67d2598c0 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -283,6 +283,7 @@ static const struct drm_display_mode default_mode = {
.vsync_start = 1600 + 4,
.vsync_end = 1600 + 4 + 8,
.vtotal = 1600 + 4 + 8 + 32,
+ .flags = DRM_MODE_FLAG_PREFER_ONE_SHOT,
.vrefresh = 60,
};
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 03/12] drm: panel: Turn on TE(Tearing Effect) on Sharp lq101r1sx01
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-05-11 1:38 ` [RFC PATCH 01/12] drm: Add a new mode flag: DRM_MODE_FLAG_PREFER_ONE_SHOT Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 02/12] drm: panel: Add one-shot flag to Sharp lq101r1sx01 driver Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 04/12] drm: Add DRM mode flag TE polarity Mark Zhang
` (8 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 19a67d2598c0..b69f88cd15b2 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -238,6 +238,13 @@ static int sharp_panel_prepare(struct drm_panel *panel)
goto poweroff;
}
+ err = mipi_dsi_dcs_set_tear_on(sharp->link1,
+ MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (err < 0) {
+ dev_err(panel->dev, "failed to turn on TE: %d\n", err);
+ goto poweroff;
+ }
+
err = mipi_dsi_dcs_set_display_on(sharp->link1);
if (err < 0) {
dev_err(panel->dev, "failed to set display on: %d\n", err);
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 04/12] drm: Add DRM mode flag TE polarity
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (2 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 03/12] drm: panel: Turn on TE(Tearing Effect) on Sharp lq101r1sx01 Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 05/12] dt: panel: Add property "te-polarity" Mark Zhang
` (7 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Add 2 DRM mode flag: TE polarity high/low.
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
include/uapi/drm/drm_mode.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5447a338e893..b577cdfb76df 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -73,6 +73,8 @@
#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14)
#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
#define DRM_MODE_FLAG_PREFER_ONE_SHOT (1<<19)
+#define DRM_MODE_FLAG_TE_POLARITY_HIGH (1<<20)
+#define DRM_MODE_FLAG_TE_POLARITY_LOW (1<<21)
/* DPMS flags */
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 05/12] dt: panel: Add property "te-polarity"
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (3 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 04/12] drm: Add DRM mode flag TE polarity Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 06/12] drm: panel: Parse "te-polarity" in Sharp lq101r1sx01 driver Mark Zhang
` (6 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
te-polarity indicates the polarity of panel's TE(Tearing Effect) signal.
Normally the TE pin is connected to the host SoC. The display
controller will send a new frame to panel when the TE signal is
triggered.
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt | 2 ++
arch/arm/boot/dts/tegra114-dalmore.dts | 2 ++
2 files changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt b/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt
index f522bb8e47e1..680ebec9a927 100644
--- a/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt
+++ b/Documentation/devicetree/bindings/panel/sharp,lq101r1sx01.txt
@@ -23,6 +23,7 @@ Required properties (for DSI-LINK1 only):
- link2: phandle to the DSI peripheral on the secondary link. Note that the
presence of this property marks the containing node as DSI-LINK1.
- power-supply: phandle of the regulator that provides the supply voltage
+- te-polarity: indicates the TE(Tearing Effect) polarity. 0: Low, 1: High.
Optional properties (for DSI-LINK1 only):
- backlight: phandle of the backlight device attached to the panel
@@ -38,6 +39,7 @@ Example:
power-supply = <...>;
backlight = <...>;
+ te-polarity = <0>;
};
};
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index 8b7aa0dcdc6e..fdb1cc4063a9 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -47,6 +47,8 @@
power-supply = <&avdd_lcd_reg>;
backlight = <&backlight>;
+
+ te-polarity = <0>; /* TE_POLARITY_LOW */
};
};
};
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 06/12] drm: panel: Parse "te-polarity" in Sharp lq101r1sx01 driver
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (4 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 05/12] dt: panel: Add property "te-polarity" Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 07/12] drm/tegra: Set NC(Non-contiguous) mode to dc for one-shot Mark Zhang
` (5 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index b69f88cd15b2..654575607864 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -27,6 +27,7 @@ struct sharp_panel {
struct backlight_device *backlight;
struct regulator *supply;
+ u32 te_polarity;
bool prepared;
bool enabled;
@@ -280,7 +281,7 @@ static int sharp_panel_enable(struct drm_panel *panel)
return 0;
}
-static const struct drm_display_mode default_mode = {
+static struct drm_display_mode default_mode = {
.clock = 278000,
.hdisplay = 2560,
.hsync_start = 2560 + 128,
@@ -297,6 +298,12 @@ static const struct drm_display_mode default_mode = {
static int sharp_panel_get_modes(struct drm_panel *panel)
{
struct drm_display_mode *mode;
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+
+ if (sharp->te_polarity)
+ default_mode.flags |= DRM_MODE_FLAG_TE_POLARITY_HIGH;
+ else
+ default_mode.flags |= DRM_MODE_FLAG_TE_POLARITY_LOW;
mode = drm_mode_duplicate(panel->drm, &default_mode);
if (!mode) {
@@ -341,6 +348,14 @@ static int sharp_panel_add(struct sharp_panel *sharp)
if (IS_ERR(sharp->supply))
return PTR_ERR(sharp->supply);
+ err = of_property_read_u32(sharp->link1->dev.of_node,
+ "te-polarity", &sharp->te_polarity);
+ if (err < 0) {
+ dev_err(&sharp->link1->dev,
+ "Read te-polarity failed: %d\n", err);
+ return err;
+ }
+
np = of_parse_phandle(sharp->link1->dev.of_node, "backlight", 0);
if (np) {
sharp->backlight = of_find_backlight_by_node(np);
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 07/12] drm/tegra: Set NC(Non-contiguous) mode to dc for one-shot
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (5 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 06/12] drm: panel: Parse "te-polarity" in Sharp lq101r1sx01 driver Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 08/12] drm/panel: Add panel func: idle/busy Mark Zhang
` (4 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
If dc is about to work in one-shot mode, we need to set dc's scan
mode to NC(Non-contiguous).
There are 2 things which can make dc send frame again:
- TE signal is received
- Driver sets the NC_HOST_TRIG_ENABLE
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/tegra/dc.c | 43 +++++++++++++++++++++++++++++--------------
drivers/gpu/drm/tegra/dc.h | 5 +++++
2 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index a287e4fec865..b88c29322c6f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1248,10 +1248,26 @@ static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc)
tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
}
- value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
- value &= ~DISP_CTRL_MODE_MASK;
- value |= DISP_CTRL_MODE_C_DISPLAY;
- tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+ if (mode->flags & DRM_MODE_FLAG_PREFER_ONE_SHOT) {
+ /* enable MSF & set MSF polarity */
+ value = MSF_ENABLE | MSF_LSPI;
+ if (mode->flags & DRM_MODE_FLAG_TE_POLARITY_HIGH)
+ value |= MSF_POLARITY_HIGH;
+ else
+ value |= MSF_POLARITY_LOW;
+ tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND_OPTION0);
+
+ /* set non-continuous mode */
+ value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+ value &= ~DISP_CTRL_MODE_MASK;
+ value |= DISP_CTRL_MODE_NC_DISPLAY;
+ tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+ } else {
+ value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+ value &= ~DISP_CTRL_MODE_MASK;
+ value |= DISP_CTRL_MODE_C_DISPLAY;
+ tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+ }
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
value |= PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
@@ -1319,16 +1335,11 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
- if (status & FRAME_END_INT) {
- /*
- dev_dbg(dc->dev, "%s(): frame end\n", __func__);
- */
- }
+ if (status & FRAME_END_INT)
+ dev_info(dc->dev, "%s(): frame end\n", __func__);
if (status & VBLANK_INT) {
- /*
- dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
- */
+ dev_info(dc->dev, "%s(): vertical blank\n", __func__);
drm_crtc_handle_vblank(&dc->base);
tegra_dc_finish_page_flip(dc);
}
@@ -1339,6 +1350,9 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
*/
}
+ if (status & MSF_INT)
+ dev_info(dc->dev, "MSF_INT received.\n");
+
return IRQ_HANDLED;
}
@@ -1732,10 +1746,11 @@ static int tegra_dc_init(struct host1x_client *client)
WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
- value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+ value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT |
+ WIN_C_UF_INT | MSF_INT;
tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
- value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+ value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | MSF_INT;
tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
if (dc->soc->supports_border_color)
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 55792daabbb5..4a2d0fec5853 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -27,6 +27,10 @@
#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
#define SYNCPT_VSYNC_ENABLE (1 << 8)
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
+#define MSF_ENABLE (1 << 1)
+#define MSF_LSPI (0 << 2)
+#define MSF_POLARITY_HIGH (0 << 0)
+#define MSF_POLARITY_LOW (1 << 0)
#define DC_CMD_DISPLAY_COMMAND 0x032
#define DISP_CTRL_MODE_STOP (0 << 5)
#define DISP_CTRL_MODE_C_DISPLAY (1 << 5)
@@ -53,6 +57,7 @@
#define WIN_A_UF_INT (1 << 8)
#define WIN_B_UF_INT (1 << 9)
#define WIN_C_UF_INT (1 << 10)
+#define MSF_INT (1 << 12)
#define WIN_A_OF_INT (1 << 14)
#define WIN_B_OF_INT (1 << 15)
#define WIN_C_OF_INT (1 << 16)
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 08/12] drm/panel: Add panel func: idle/busy
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (6 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 07/12] drm/tegra: Set NC(Non-contiguous) mode to dc for one-shot Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 09/12] drm: dsi: Add "enter idle" & "exit idle" dcs functions Mark Zhang
` (3 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
The "idle" function of a drm panel is used to tell panel
there are no more frames coming in and it should remain the
last frame it gets.
Normally this only makes sense for smart panels which has
internal framebuffer.
The "busy" function is opposite to "idle".
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
include/drm/drm_panel.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 13ff44b28893..0025cd020c40 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -66,6 +66,8 @@ struct display_timing;
* the panel. This is the job of the .unprepare() function.
*/
struct drm_panel_funcs {
+ int (*idle)(struct drm_panel *panel);
+ int (*busy)(struct drm_panel *panel);
int (*disable)(struct drm_panel *panel);
int (*unprepare)(struct drm_panel *panel);
int (*prepare)(struct drm_panel *panel);
@@ -85,6 +87,22 @@ struct drm_panel {
struct list_head list;
};
+static inline int drm_panel_idle(struct drm_panel *panel)
+{
+ if (panel && panel->funcs && panel->funcs->idle)
+ return panel->funcs->idle(panel);
+
+ return panel ? -ENOSYS : -EINVAL;
+}
+
+static inline int drm_panel_busy(struct drm_panel *panel)
+{
+ if (panel && panel->funcs && panel->funcs->busy)
+ return panel->funcs->busy(panel);
+
+ return panel ? -ENOSYS : -EINVAL;
+}
+
static inline int drm_panel_unprepare(struct drm_panel *panel)
{
if (panel && panel->funcs && panel->funcs->unprepare)
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 09/12] drm: dsi: Add "enter idle" & "exit idle" dcs functions
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (7 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 08/12] drm/panel: Add panel func: idle/busy Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 10/12] drm: panel: Add idle/busy in Sharp lq101r1sx01 driver Mark Zhang
` (2 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/drm_mipi_dsi.c | 36 ++++++++++++++++++++++++++++++++++++
include/drm/drm_mipi_dsi.h | 2 ++
2 files changed, 38 insertions(+)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 2d5ca8eec13a..9bc6ff75eb8f 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -862,6 +862,42 @@ int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
}
EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
+/**
+ * mipi_dsi_dcs_enter_idle_mode()
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_enter_idle_mode(struct mipi_dsi_device *dsi)
+{
+ ssize_t err;
+
+ err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_IDLE_MODE, NULL, 0);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_enter_idle_mode);
+
+/**
+ * mipi_dsi_dcs_exit_idle_mode()
+ * @dsi: DSI peripheral device
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_exit_idle_mode(struct mipi_dsi_device *dsi)
+{
+ ssize_t err;
+
+ err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_IDLE_MODE, NULL, 0);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_exit_idle_mode);
+
static int mipi_dsi_drv_probe(struct device *dev)
{
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
index f1d8d0dbb4f1..d949a8ef389f 100644
--- a/include/drm/drm_mipi_dsi.h
+++ b/include/drm/drm_mipi_dsi.h
@@ -214,6 +214,8 @@ int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
enum mipi_dsi_dcs_tear_mode mode);
int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);
+int mipi_dsi_dcs_enter_idle_mode(struct mipi_dsi_device *dsi);
+int mipi_dsi_dcs_exit_idle_mode(struct mipi_dsi_device *dsi);
/**
* struct mipi_dsi_driver - DSI driver
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 10/12] drm: panel: Add idle/busy in Sharp lq101r1sx01 driver
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (8 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 09/12] drm: dsi: Add "enter idle" & "exit idle" dcs functions Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 11/12] drm/tegra: Suspend dc/dsi/panel in one-shot mode Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 12/12] JUST FOR TEST: Add one-shot trigger to update display Mark Zhang
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c | 26 +++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
index 654575607864..a0a7c80f23d6 100644
--- a/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -90,6 +90,18 @@ static __maybe_unused int sharp_panel_read(struct sharp_panel *sharp,
return err;
}
+static int sharp_panel_idle(struct drm_panel *panel)
+{
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+ int err = 0;
+
+ err = mipi_dsi_dcs_enter_idle_mode(sharp->link1);
+ if (err < 0)
+ dev_err(panel->dev, "failed to enter idle: %d\n", err);
+
+ return err;
+}
+
static int sharp_panel_disable(struct drm_panel *panel)
{
struct sharp_panel *sharp = to_sharp_panel(panel);
@@ -168,6 +180,18 @@ static int sharp_setup_symmetrical_split(struct mipi_dsi_device *left,
return 0;
}
+static int sharp_panel_busy(struct drm_panel *panel)
+{
+ struct sharp_panel *sharp = to_sharp_panel(panel);
+ int err = 0;
+
+ err = mipi_dsi_dcs_exit_idle_mode(sharp->link1);
+ if (err < 0)
+ dev_err(panel->dev, "failed to exit idle: %d\n", err);
+
+ return err;
+}
+
static int sharp_panel_prepare(struct drm_panel *panel)
{
struct sharp_panel *sharp = to_sharp_panel(panel);
@@ -324,6 +348,8 @@ static int sharp_panel_get_modes(struct drm_panel *panel)
}
static const struct drm_panel_funcs sharp_panel_funcs = {
+ .idle = sharp_panel_idle,
+ .busy = sharp_panel_busy,
.disable = sharp_panel_disable,
.unprepare = sharp_panel_unprepare,
.prepare = sharp_panel_prepare,
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 11/12] drm/tegra: Suspend dc/dsi/panel in one-shot mode
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (9 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 10/12] drm: panel: Add idle/busy in Sharp lq101r1sx01 driver Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
2015-05-11 1:38 ` [RFC PATCH 12/12] JUST FOR TEST: Add one-shot trigger to update display Mark Zhang
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/tegra/dc.c | 34 ++++++++++++++++++++++++
drivers/gpu/drm/tegra/drm.h | 3 +++
drivers/gpu/drm/tegra/dsi.c | 63 +++++++++++++++++++++++++++++++++++++++++----
3 files changed, 95 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index b88c29322c6f..b8231e2e3c92 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1330,6 +1330,7 @@ static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
static irqreturn_t tegra_dc_irq(int irq, void *data)
{
struct tegra_dc *dc = data;
+ struct drm_display_mode *mode = &dc->base.state->adjusted_mode;
unsigned long status;
status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
@@ -1342,6 +1343,9 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
dev_info(dc->dev, "%s(): vertical blank\n", __func__);
drm_crtc_handle_vblank(&dc->base);
tegra_dc_finish_page_flip(dc);
+
+ if (mode->flags & DRM_MODE_FLAG_PREFER_ONE_SHOT)
+ schedule_work(&dc->one_shot_work);
}
if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
@@ -1895,6 +1899,35 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
return 0;
}
+static void tegra_dc_one_shot_work(struct work_struct *work)
+{
+ struct tegra_dc *dc;
+ struct drm_connector *connector;
+ struct drm_device *drm;
+
+ dc = container_of(work, struct tegra_dc, one_shot_work);
+ drm = dc->base.dev;
+
+ dev_info(dc->dev, "one-shot: Suspend encoder & connector.\n");
+ drm_modeset_lock_all(drm);
+ list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+ if (connector->funcs->dpms)
+ connector->funcs->dpms(connector,
+ DRM_MODE_DPMS_SUSPEND);
+ }
+ drm_modeset_unlock_all(drm);
+
+ dev_info(dc->dev, "one-shot: Suspend dc.\n");
+ /* Stop dc since dc doesn't have dpms functions */
+ tegra_dc_stop(dc);
+ clk_disable_unprepare(dc->clk);
+
+ /*
+ * TODO: Powergate dc. This requires we re-init all stuffs
+ * next time we want to trigger the one-shot.
+ */
+}
+
static int tegra_dc_probe(struct platform_device *pdev)
{
unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
@@ -1913,6 +1946,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
spin_lock_init(&dc->lock);
INIT_LIST_HEAD(&dc->list);
+ INIT_WORK(&dc->one_shot_work, tegra_dc_one_shot_work);
dc->dev = &pdev->dev;
dc->soc = id->data;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 659b2fcc986d..00daf427c831 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -12,6 +12,7 @@
#include <uapi/drm/tegra_drm.h>
#include <linux/host1x.h>
+#include <linux/workqueue.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
@@ -130,6 +131,8 @@ struct tegra_dc {
/* page-flip handling */
struct drm_pending_vblank_event *event;
+ struct work_struct one_shot_work;
+
const struct tegra_dc_soc_info *soc;
struct iommu_domain *domain;
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index ed970f622903..7e00279982b7 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -726,10 +726,6 @@ static void tegra_dsi_soft_reset(struct tegra_dsi *dsi)
tegra_dsi_soft_reset(dsi->slave);
}
-static void tegra_dsi_connector_dpms(struct drm_connector *connector, int mode)
-{
-}
-
static void tegra_dsi_connector_reset(struct drm_connector *connector)
{
struct tegra_dsi_state *state;
@@ -756,7 +752,7 @@ tegra_dsi_connector_duplicate_state(struct drm_connector *connector)
}
static const struct drm_connector_funcs tegra_dsi_connector_funcs = {
- .dpms = tegra_dsi_connector_dpms,
+ .dpms = drm_helper_connector_dpms,
.reset = tegra_dsi_connector_reset,
.detect = tegra_output_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -784,6 +780,63 @@ static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
static void tegra_dsi_encoder_dpms(struct drm_encoder *encoder, int mode)
{
+ struct tegra_output *output = encoder_to_output(encoder);
+ struct drm_crtc *crtc = encoder->crtc;
+ struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
+ struct tegra_dsi *dsi = to_dsi(output);
+ struct tegra_dsi_state *state;
+ u32 value;
+ int err;
+
+ if (mode == DRM_MODE_DPMS_SUSPEND) {
+ tegra_dsi_video_disable(dsi);
+
+ if (dc) {
+ value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+ value &= ~DSI_ENABLE;
+ tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+ tegra_dc_commit(dc);
+ }
+
+ err = tegra_dsi_wait_idle(dsi, 100);
+ if (err < 0)
+ dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
+
+ tegra_dsi_soft_reset(dsi);
+
+ if (output->panel)
+ drm_panel_idle(output->panel);
+
+ tegra_dsi_disable(dsi);
+ }
+
+ if (mode == DRM_MODE_DPMS_STANDBY) {
+ state = tegra_dsi_get_state(dsi);
+
+ tegra_dsi_set_timeout(dsi, state->bclk, state->vrefresh);
+
+ /*
+ * The D-PHY timing fields are expressed in byte-clock cycles, so
+ * multiply the period by 8.
+ */
+ tegra_dsi_set_phy_timing(dsi, state->period * 8, &state->timing);
+
+ if (output->panel)
+ drm_panel_busy(output->panel);
+
+ tegra_dsi_configure(dsi, dc->pipe, &crtc->mode);
+
+ /* enable display controller */
+ value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
+ value |= DSI_ENABLE;
+ tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
+
+ tegra_dc_commit(dc);
+
+ /* enable DSI controller */
+ tegra_dsi_enable(dsi);
+ }
}
static void tegra_dsi_encoder_prepare(struct drm_encoder *encoder)
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC PATCH 12/12] JUST FOR TEST: Add one-shot trigger to update display
[not found] ` <1431308311-4470-1-git-send-email-markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
` (10 preceding siblings ...)
2015-05-11 1:38 ` [RFC PATCH 11/12] drm/tegra: Suspend dc/dsi/panel in one-shot mode Mark Zhang
@ 2015-05-11 1:38 ` Mark Zhang
11 siblings, 0 replies; 18+ messages in thread
From: Mark Zhang @ 2015-05-11 1:38 UTC (permalink / raw)
To: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
This HACK adds a workqueue to refresh the display periodically.
This is used just for testing.
Signed-off-by: Mark Zhang <markz-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
drivers/gpu/drm/tegra/dc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/tegra/drm.h | 1 +
2 files changed, 48 insertions(+)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index b8231e2e3c92..48bddc795995 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1262,6 +1262,8 @@ static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc)
value &= ~DISP_CTRL_MODE_MASK;
value |= DISP_CTRL_MODE_NC_DISPLAY;
tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+ schedule_work(&dc->one_shot_trigger);
} else {
value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
value &= ~DISP_CTRL_MODE_MASK;
@@ -1928,6 +1930,50 @@ static void tegra_dc_one_shot_work(struct work_struct *work)
*/
}
+static void tegra_dc_one_shot_trigger(struct work_struct *work)
+{
+ struct tegra_dc *dc;
+ struct drm_connector *connector;
+ struct drm_device *drm;
+ unsigned long update_mask = GENERAL_ACT_REQ | NC_HOST_TRIG;
+ static int first_trigger = 1;
+ int err;
+ unsigned long value;
+
+ dc = container_of(work, struct tegra_dc, one_shot_trigger);
+ drm = dc->base.dev;
+ msleep(5000);
+
+ if (first_trigger) {
+ tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+ first_trigger = 0;
+ schedule_work(&dc->one_shot_trigger);
+ return;
+ }
+
+ dev_info(dc->dev, "one-shot: Wakeup dsi/panel.\n");
+ err = clk_prepare_enable(dc->clk);
+ if (err < 0)
+ dev_err(dc->dev, "failed to enable clock: %d\n", err);
+
+ value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
+ value &= ~DISP_CTRL_MODE_MASK;
+ value |= DISP_CTRL_MODE_NC_DISPLAY;
+ tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
+
+ drm_modeset_lock_all(drm);
+ list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
+ if (connector->funcs->dpms)
+ connector->funcs->dpms(connector,
+ DRM_MODE_DPMS_STANDBY);
+ }
+ drm_modeset_unlock_all(drm);
+
+ /* Trigger the one-shot */
+ tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL);
+ schedule_work(&dc->one_shot_trigger);
+}
+
static int tegra_dc_probe(struct platform_device *pdev)
{
unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
@@ -1947,6 +1993,7 @@ static int tegra_dc_probe(struct platform_device *pdev)
spin_lock_init(&dc->lock);
INIT_LIST_HEAD(&dc->list);
INIT_WORK(&dc->one_shot_work, tegra_dc_one_shot_work);
+ INIT_WORK(&dc->one_shot_trigger, tegra_dc_one_shot_trigger);
dc->dev = &pdev->dev;
dc->soc = id->data;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 00daf427c831..5d606cacb098 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -132,6 +132,7 @@ struct tegra_dc {
struct drm_pending_vblank_event *event;
struct work_struct one_shot_work;
+ struct work_struct one_shot_trigger;
const struct tegra_dc_soc_info *soc;
--
2.1.4
^ permalink raw reply related [flat|nested] 18+ messages in thread