From 1bed8376a85f9bd4075ea00d123a769d6255c63a Mon Sep 17 00:00:00 2001
From: Ruslan Bukin
Date: Mon, 9 Jan 2023 17:09:19 +0000
Subject: [PATCH 1/4] Add support for DPMS: disable video ports on
bridge_disable in TDA19988 driver. Also disable pixel clock and pipeline
components in Komeda driver. This puts devices into lower power mode and
blanks the screen.
---
sys/dev/drm/bridges/tda19988/tda19988.c | 15 +++++++++++
sys/dev/drm/komeda/komeda_pipeline.c | 33 +++++++++++++++++++++++++
sys/dev/drm/komeda/komeda_pipeline.h | 1 +
sys/dev/drm/komeda/komeda_plane.c | 29 +++++++++++-----------
sys/dev/drm/komeda/komeda_plane.h | 1 +
sys/dev/drm/komeda/komeda_regs.h | 5 ++++
6 files changed, 70 insertions(+), 14 deletions(-)
diff --git a/sys/dev/drm/bridges/tda19988/tda19988.c b/sys/dev/drm/bridges/tda19988/tda19988.c
index 3620266a90b7..232f1e315e78 100644
--- a/sys/dev/drm/bridges/tda19988/tda19988.c
+++ b/sys/dev/drm/bridges/tda19988/tda19988.c
@@ -78,6 +78,9 @@ __FBSDID("$FreeBSD$");
#define CTRL_INTR_EN_GLO_MASK 0x04
#define TDA_INT_FLAGS_2 MKREG(0x00, 0x11)
#define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
+#define TDA_ENA_VP_0 MKREG(0x00, 0x18)
+#define TDA_ENA_VP_1 MKREG(0x00, 0x19)
+#define TDA_ENA_VP_2 MKREG(0x00, 0x1a)
#define TDA_VIP_CNTRL_0 MKREG(0x00, 0x20)
#define TDA_VIP_CNTRL_1 MKREG(0x00, 0x21)
@@ -879,7 +882,14 @@ tda19988_bridge_mode_set(struct drm_bridge *bridge,
static void
tda19988_bridge_disable(struct drm_bridge *bridge)
{
+ struct tda19988_softc *sc;
+
+ sc = container_of(bridge, struct tda19988_softc, bridge);
+ /* Disable Video Ports */
+ tda19988_reg_write(sc, TDA_ENA_VP_0, 0);
+ tda19988_reg_write(sc, TDA_ENA_VP_1, 0);
+ tda19988_reg_write(sc, TDA_ENA_VP_2, 0);
}
static void
@@ -908,6 +918,11 @@ tda19988_bridge_enable(struct drm_bridge *bridge)
sc->mode.vsync_end);
tda19988_init_encoder(sc);
+
+ /* Enable Video Ports */
+ tda19988_reg_write(sc, TDA_ENA_VP_0, 0xff);
+ tda19988_reg_write(sc, TDA_ENA_VP_1, 0xff);
+ tda19988_reg_write(sc, TDA_ENA_VP_2, 0xff);
}
static const struct drm_bridge_funcs tda19988_bridge_funcs = {
diff --git a/sys/dev/drm/komeda/komeda_pipeline.c b/sys/dev/drm/komeda/komeda_pipeline.c
index f55b330f6d6c..63fac009e9e2 100644
--- a/sys/dev/drm/komeda/komeda_pipeline.c
+++ b/sys/dev/drm/komeda/komeda_pipeline.c
@@ -78,6 +78,27 @@ __FBSDID("$FreeBSD$");
#define dprintf(fmt, ...)
+int
+komeda_pipeline_set_mode(struct komeda_drm_softc *sc, int mode)
+{
+ int timeout;
+ uint32_t reg;
+
+ timeout = 10000;
+
+ DPU_WR4(sc, GCU_CONTROL, mode);
+ do {
+ reg = DPU_RD4(sc, GCU_CONTROL);
+ if ((reg & CONTROL_MODE_M) == mode)
+ break;
+ } while (timeout--);
+
+ if (timeout <= 0)
+ return (-1);
+
+ return (0);
+}
+
/*
* VBLANK functions
*/
@@ -220,6 +241,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc,
sc = pipeline->sc;
dprintf("%s\n", __func__);
+ clk_enable(pipeline->pxclk);
dou_configure(sc, adj);
dou_ds_timing_setup(sc, adj);
@@ -232,10 +254,15 @@ static void
komeda_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
+ struct komeda_drm_softc *sc;
+ struct komeda_pipeline *pipeline;
uint32_t irqflags;
dprintf("%s\n", __func__);
+ pipeline = container_of(crtc, struct komeda_pipeline, crtc);
+ sc = pipeline->sc;
+
/* Disable VBLANK events */
drm_crtc_vblank_off(crtc);
@@ -247,6 +274,12 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
}
spin_unlock_irqrestore(&crtc->dev->event_lock, irqflags);
+
+ komeda_pipeline_set_mode(sc, CONTROL_MODE_INACTIVE);
+
+ dou_ds_control(sc, false);
+
+ clk_disable(pipeline->pxclk);
}
static void
diff --git a/sys/dev/drm/komeda/komeda_pipeline.h b/sys/dev/drm/komeda/komeda_pipeline.h
index 82971dfdcb06..c6e6f8d63622 100644
--- a/sys/dev/drm/komeda/komeda_pipeline.h
+++ b/sys/dev/drm/komeda/komeda_pipeline.h
@@ -50,5 +50,6 @@ struct komeda_pipeline {
int
komeda_pipeline_create_pipeline(struct komeda_drm_softc *sc, phandle_t node,
struct komeda_pipeline *pipeline);
+int komeda_pipeline_set_mode(struct komeda_drm_softc *sc, int mode);
#endif /* !_DEV_DRM_KOMEDA_KOMEDA_PIPELINE_H_ */
diff --git a/sys/dev/drm/komeda/komeda_plane.c b/sys/dev/drm/komeda/komeda_plane.c
index 8b502cf6b51c..9de6dc59f277 100644
--- a/sys/dev/drm/komeda/komeda_plane.c
+++ b/sys/dev/drm/komeda/komeda_plane.c
@@ -182,6 +182,19 @@ komeda_plane_atomic_disable(struct drm_plane *plane,
dprintf("%s\n", __func__);
}
+void
+dou_ds_control(struct komeda_drm_softc *sc, bool enable)
+{
+ int reg;
+
+ if (enable)
+ reg = BS_CONTROL_EN | BS_CONTROL_VM;
+ else
+ reg = 0;
+
+ DPU_WR4(sc, BS_CONTROL, reg);
+}
+
void
dou_ds_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m)
{
@@ -220,8 +233,7 @@ dou_ds_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m)
DPU_WR4(sc, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
DPU_WR4(sc, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
- reg = BS_CONTROL_EN | BS_CONTROL_VM;
- DPU_WR4(sc, BS_CONTROL, reg);
+ dou_ds_control(sc, true);
}
void
@@ -288,19 +300,8 @@ lpu_intr(struct komeda_drm_softc *sc)
static int
gcu_configure(struct komeda_drm_softc *sc)
{
- uint32_t reg;
- int timeout;
-
- timeout = 10000;
-
- DPU_WR4(sc, GCU_CONTROL, CONTROL_MODE_DO0_ACTIVE);
- do {
- reg = DPU_RD4(sc, GCU_CONTROL);
- if ((reg & CONTROL_MODE_M) == CONTROL_MODE_DO0_ACTIVE)
- break;
- } while (timeout--);
- if (timeout <= 0) {
+ if (komeda_pipeline_set_mode(sc, CONTROL_MODE_DO0_ACTIVE) != 0) {
printf("%s: Failed to set DO0 active\n", __func__);
return (-1);
}
diff --git a/sys/dev/drm/komeda/komeda_plane.h b/sys/dev/drm/komeda/komeda_plane.h
index 20837e7233c6..918f76fa0664 100644
--- a/sys/dev/drm/komeda/komeda_plane.h
+++ b/sys/dev/drm/komeda/komeda_plane.h
@@ -51,6 +51,7 @@ void lpu_intr(struct komeda_drm_softc *sc);
void cu_intr(struct komeda_drm_softc *sc);
void dou_configure(struct komeda_drm_softc *sc, struct drm_display_mode *m);
void dou_ds_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m);
+void dou_ds_control(struct komeda_drm_softc *sc, bool enable);
void cu_configure(struct komeda_drm_softc *sc, struct drm_display_mode *m,
struct drm_plane_state *state, int id);
diff --git a/sys/dev/drm/komeda/komeda_regs.h b/sys/dev/drm/komeda/komeda_regs.h
index 533ba3102fbc..cf2c0815f125 100644
--- a/sys/dev/drm/komeda/komeda_regs.h
+++ b/sys/dev/drm/komeda/komeda_regs.h
@@ -55,7 +55,12 @@
#define CONTROL_SRST (1 << 16)
#define CONTROL_MODE_S 0
#define CONTROL_MODE_M (0x7 << CONTROL_MODE_S)
+#define CONTROL_MODE_INACTIVE (0x0 << CONTROL_MODE_S)
+#define CONTROL_MODE_TBU_CONNECT (0x1 << CONTROL_MODE_S)
+#define CONTROL_MODE_TBU_DISCONNECT (0x2 << CONTROL_MODE_S)
#define CONTROL_MODE_DO0_ACTIVE (0x3 << CONTROL_MODE_S)
+#define CONTROL_MODE_DO1_ACTIVE (0x4 << CONTROL_MODE_S)
+#define CONTROL_MODE_DO01_ACTIVE (0x5 << CONTROL_MODE_S)
#define GCU_CONFIG_VALID0 0x00D4
#define CONFIG_VALID0_CVAL (1 << 0)
#define GCU_CONFIGURATION_ID0 0x0100
From 1113382ea989555b3c9a8edeb1f703e2286b997e Mon Sep 17 00:00:00 2001
From: Ruslan Bukin
Date: Mon, 9 Jan 2023 17:52:00 +0000
Subject: [PATCH 2/4] Don't copy drm mode to driver's software context, instead
configure display mode straight from bridge_mode_set() as it should be.
---
sys/dev/drm/bridges/tda19988/tda19988.c | 324 ++++++++++++------------
1 file changed, 156 insertions(+), 168 deletions(-)
diff --git a/sys/dev/drm/bridges/tda19988/tda19988.c b/sys/dev/drm/bridges/tda19988/tda19988.c
index 232f1e315e78..aaff00305a42 100644
--- a/sys/dev/drm/bridges/tda19988/tda19988.c
+++ b/sys/dev/drm/bridges/tda19988/tda19988.c
@@ -271,7 +271,6 @@ struct tda19988_softc {
struct drm_encoder encoder;
struct drm_connector connector __subobject_use_container_bounds;
struct drm_bridge bridge __subobject_use_container_bounds;
- struct drm_display_mode mode;
};
static int
@@ -446,152 +445,6 @@ tda19988_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
-static void
-tda19988_init_encoder(struct tda19988_softc *sc)
-{
- const struct drm_display_mode *mode;
- uint16_t ref_pix, ref_line, n_pix, n_line;
- uint16_t hs_pix_start, hs_pix_stop;
- uint16_t vs1_pix_start, vs1_pix_stop;
- uint16_t vs1_line_start, vs1_line_end;
- uint16_t vs2_pix_start, vs2_pix_stop;
- uint16_t vs2_line_start, vs2_line_end;
- uint16_t vwin1_line_start, vwin1_line_end;
- uint16_t vwin2_line_start, vwin2_line_end;
- uint16_t de_start, de_stop;
- uint8_t reg, div;
-
- mode = &sc->mode;
-
- n_pix = mode->htotal;
- n_line = mode->vtotal;
-
- hs_pix_stop = mode->hsync_end - mode->hdisplay;
- hs_pix_start = mode->hsync_start - mode->hdisplay;
-
- de_stop = mode->htotal;
- de_start = mode->htotal - mode->hdisplay;
- ref_pix = hs_pix_start + 3;
-
- if (mode->flags & DRM_MODE_FLAG_HSKEW)
- ref_pix += mode->hskew;
-
- if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
- ref_line = 1 + mode->vsync_start - mode->vdisplay;
- vwin1_line_start = mode->vtotal - mode->vdisplay - 1;
- vwin1_line_end = vwin1_line_start + mode->vdisplay;
-
- vs1_pix_start = vs1_pix_stop = hs_pix_start;
- vs1_line_start = mode->vsync_start - mode->vdisplay;
- vs1_line_end = vs1_line_start + mode->vsync_end - mode->vsync_start;
-
- vwin2_line_start = vwin2_line_end = 0;
- vs2_pix_start = vs2_pix_stop = 0;
- vs2_line_start = vs2_line_end = 0;
- } else {
- ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
- vwin1_line_start = (mode->vtotal - mode->vdisplay)/2;
- vwin1_line_end = vwin1_line_start + mode->vdisplay/2;
-
- vs1_pix_start = vs1_pix_stop = hs_pix_start;
- vs1_line_start = (mode->vsync_start - mode->vdisplay)/2;
- vs1_line_end = vs1_line_start + (mode->vsync_end - mode->vsync_start)/2;
-
- vwin2_line_start = vwin1_line_start + mode->vtotal/2;
- vwin2_line_end = vwin2_line_start + mode->vdisplay/2;
-
- vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2;
- vs2_line_start = vs1_line_start + mode->vtotal/2 ;
- vs2_line_end = vs2_line_start + (mode->vsync_end - mode->vsync_start)/2;
- }
-
- div = 148500 / mode->crtc_clock;
- if (div != 0) {
- div--;
- if (div > 3)
- div = 3;
- }
-
- /* set HDMI HDCP mode off */
- tda19988_reg_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
- tda19988_reg_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI);
- tda19988_reg_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE);
-
- /* no pre-filter or interpolator */
- tda19988_reg_write(sc, TDA_HVF_CNTRL_0,
- HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE);
- tda19988_reg_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
- tda19988_reg_write(sc, TDA_VIP_CNTRL_4,
- VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE);
-
- tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
- tda19988_reg_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP);
- tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
- tda19988_reg_write(sc, TDA_SERIALIZER, 0);
- tda19988_reg_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL);
-
- tda19988_reg_write(sc, TDA_RPT_CNTRL, 0);
- tda19988_reg_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
- SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
-
- tda19988_reg_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
- PLL_SERIAL_2_SRL_PR(0));
-
- tda19988_reg_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP);
-
- tda19988_reg_write(sc, TDA_ANA_GENERAL, 0x09);
-
- tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
-
- /*
- * Sync on rising HSYNC/VSYNC
- */
- reg = VIP_CNTRL_3_SYNC_HS;
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
- reg |= VIP_CNTRL_3_H_TGL;
- if (mode->flags & DRM_MODE_FLAG_NVSYNC)
- reg |= VIP_CNTRL_3_V_TGL;
- tda19988_reg_write(sc, TDA_VIP_CNTRL_3, reg);
-
- reg = TBG_CNTRL_1_TGL_EN;
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
- reg |= TBG_CNTRL_1_H_TGL;
- if (mode->flags & DRM_MODE_FLAG_NVSYNC)
- reg |= TBG_CNTRL_1_V_TGL;
- tda19988_reg_write(sc, TDA_TBG_CNTRL_1, reg);
-
- /* Program timing */
- tda19988_reg_write(sc, TDA_VIDFORMAT, 0x00);
-
- tda19988_reg_write2(sc, TDA_REFPIX_MSB, ref_pix);
- tda19988_reg_write2(sc, TDA_REFLINE_MSB, ref_line);
- tda19988_reg_write2(sc, TDA_NPIX_MSB, n_pix);
- tda19988_reg_write2(sc, TDA_NLINE_MSB, n_line);
-
- tda19988_reg_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start);
- tda19988_reg_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start);
- tda19988_reg_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end);
- tda19988_reg_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop);
- tda19988_reg_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start);
- tda19988_reg_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start);
- tda19988_reg_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end);
- tda19988_reg_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop);
- tda19988_reg_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start);
- tda19988_reg_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop);
- tda19988_reg_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start);
- tda19988_reg_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end);
- tda19988_reg_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start);
- tda19988_reg_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end);
- tda19988_reg_write2(sc, TDA_DE_START_MSB, de_start);
- tda19988_reg_write2(sc, TDA_DE_STOP_MSB, de_stop);
-
- if (sc->sc_version == TDA19988)
- tda19988_reg_write(sc, TDA_ENABLE_SPACE, 0x00);
-
- /* must be last register set */
- tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
-}
-
static int
tda19988_read_edid_block(struct tda19988_softc *sc, uint8_t *buf, int block)
{
@@ -872,11 +725,166 @@ tda19988_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *orig_mode,
const struct drm_display_mode *mode)
{
+ uint16_t ref_pix, ref_line, n_pix, n_line;
+ uint16_t hs_pix_start, hs_pix_stop;
+ uint16_t vs1_pix_start, vs1_pix_stop;
+ uint16_t vs1_line_start, vs1_line_end;
+ uint16_t vs2_pix_start, vs2_pix_stop;
+ uint16_t vs2_line_start, vs2_line_end;
+ uint16_t vwin1_line_start, vwin1_line_end;
+ uint16_t vwin2_line_start, vwin2_line_end;
+ uint16_t de_start, de_stop;
+ uint8_t reg, div;
struct tda19988_softc *sc;
sc = container_of(bridge, struct tda19988_softc, bridge);
- memcpy(&sc->mode, mode, sizeof(struct drm_display_mode));
+ if (bootverbose)
+ device_printf(sc->dev, "Mode information:\n"
+ "hdisplay: %d\n"
+ "vdisplay: %d\n"
+ "htotal: %d\n"
+ "vtotal: %d\n"
+ "hsync_start: %d\n"
+ "hsync_end: %d\n"
+ "vsync_start: %d\n"
+ "vsync_end: %d\n",
+ mode->hdisplay,
+ mode->vdisplay,
+ mode->htotal,
+ mode->vtotal,
+ mode->hsync_start,
+ mode->hsync_end,
+ mode->vsync_start,
+ mode->vsync_end);
+
+ n_pix = mode->htotal;
+ n_line = mode->vtotal;
+
+ hs_pix_stop = mode->hsync_end - mode->hdisplay;
+ hs_pix_start = mode->hsync_start - mode->hdisplay;
+
+ de_stop = mode->htotal;
+ de_start = mode->htotal - mode->hdisplay;
+ ref_pix = hs_pix_start + 3;
+
+ if (mode->flags & DRM_MODE_FLAG_HSKEW)
+ ref_pix += mode->hskew;
+
+ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
+ ref_line = 1 + mode->vsync_start - mode->vdisplay;
+ vwin1_line_start = mode->vtotal - mode->vdisplay - 1;
+ vwin1_line_end = vwin1_line_start + mode->vdisplay;
+
+ vs1_pix_start = vs1_pix_stop = hs_pix_start;
+ vs1_line_start = mode->vsync_start - mode->vdisplay;
+ vs1_line_end = vs1_line_start + mode->vsync_end - mode->vsync_start;
+
+ vwin2_line_start = vwin2_line_end = 0;
+ vs2_pix_start = vs2_pix_stop = 0;
+ vs2_line_start = vs2_line_end = 0;
+ } else {
+ ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
+ vwin1_line_start = (mode->vtotal - mode->vdisplay)/2;
+ vwin1_line_end = vwin1_line_start + mode->vdisplay/2;
+
+ vs1_pix_start = vs1_pix_stop = hs_pix_start;
+ vs1_line_start = (mode->vsync_start - mode->vdisplay)/2;
+ vs1_line_end = vs1_line_start + (mode->vsync_end - mode->vsync_start)/2;
+
+ vwin2_line_start = vwin1_line_start + mode->vtotal/2;
+ vwin2_line_end = vwin2_line_start + mode->vdisplay/2;
+
+ vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2;
+ vs2_line_start = vs1_line_start + mode->vtotal/2 ;
+ vs2_line_end = vs2_line_start + (mode->vsync_end - mode->vsync_start)/2;
+ }
+
+ div = 148500 / mode->crtc_clock;
+ if (div != 0) {
+ div--;
+ if (div > 3)
+ div = 3;
+ }
+
+ /* set HDMI HDCP mode off */
+ tda19988_reg_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+ tda19988_reg_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI);
+ tda19988_reg_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE);
+
+ /* no pre-filter or interpolator */
+ tda19988_reg_write(sc, TDA_HVF_CNTRL_0,
+ HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE);
+ tda19988_reg_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
+ tda19988_reg_write(sc, TDA_VIP_CNTRL_4,
+ VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE);
+
+ tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
+ tda19988_reg_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP);
+ tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
+ tda19988_reg_write(sc, TDA_SERIALIZER, 0);
+ tda19988_reg_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL);
+
+ tda19988_reg_write(sc, TDA_RPT_CNTRL, 0);
+ tda19988_reg_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
+ SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
+
+ tda19988_reg_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
+ PLL_SERIAL_2_SRL_PR(0));
+
+ tda19988_reg_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP);
+
+ tda19988_reg_write(sc, TDA_ANA_GENERAL, 0x09);
+
+ tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
+
+ /*
+ * Sync on rising HSYNC/VSYNC
+ */
+ reg = VIP_CNTRL_3_SYNC_HS;
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ reg |= VIP_CNTRL_3_H_TGL;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ reg |= VIP_CNTRL_3_V_TGL;
+ tda19988_reg_write(sc, TDA_VIP_CNTRL_3, reg);
+
+ reg = TBG_CNTRL_1_TGL_EN;
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ reg |= TBG_CNTRL_1_H_TGL;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ reg |= TBG_CNTRL_1_V_TGL;
+ tda19988_reg_write(sc, TDA_TBG_CNTRL_1, reg);
+
+ /* Program timing */
+ tda19988_reg_write(sc, TDA_VIDFORMAT, 0x00);
+
+ tda19988_reg_write2(sc, TDA_REFPIX_MSB, ref_pix);
+ tda19988_reg_write2(sc, TDA_REFLINE_MSB, ref_line);
+ tda19988_reg_write2(sc, TDA_NPIX_MSB, n_pix);
+ tda19988_reg_write2(sc, TDA_NLINE_MSB, n_line);
+
+ tda19988_reg_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start);
+ tda19988_reg_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start);
+ tda19988_reg_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end);
+ tda19988_reg_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop);
+ tda19988_reg_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start);
+ tda19988_reg_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start);
+ tda19988_reg_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end);
+ tda19988_reg_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop);
+ tda19988_reg_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start);
+ tda19988_reg_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop);
+ tda19988_reg_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start);
+ tda19988_reg_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end);
+ tda19988_reg_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start);
+ tda19988_reg_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end);
+ tda19988_reg_write2(sc, TDA_DE_START_MSB, de_start);
+ tda19988_reg_write2(sc, TDA_DE_STOP_MSB, de_stop);
+
+ if (sc->sc_version == TDA19988)
+ tda19988_reg_write(sc, TDA_ENABLE_SPACE, 0x00);
+
+ /* must be last register set */
+ tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
}
static void
@@ -899,26 +907,6 @@ tda19988_bridge_enable(struct drm_bridge *bridge)
sc = container_of(bridge, struct tda19988_softc, bridge);
- dprintf(sc->dev, "Mode information:\n"
- "hdisplay: %d\n"
- "vdisplay: %d\n"
- "htotal: %d\n"
- "vtotal: %d\n"
- "hsync_start: %d\n"
- "hsync_end: %d\n"
- "vsync_start: %d\n"
- "vsync_end: %d\n",
- sc->mode.hdisplay,
- sc->mode.vdisplay,
- sc->mode.htotal,
- sc->mode.vtotal,
- sc->mode.hsync_start,
- sc->mode.hsync_end,
- sc->mode.vsync_start,
- sc->mode.vsync_end);
-
- tda19988_init_encoder(sc);
-
/* Enable Video Ports */
tda19988_reg_write(sc, TDA_ENA_VP_0, 0xff);
tda19988_reg_write(sc, TDA_ENA_VP_1, 0xff);
From 2c89d26834cc5729a6266a61e32ca7e1e278fa22 Mon Sep 17 00:00:00 2001
From: Ruslan Bukin
Date: Mon, 9 Jan 2023 19:15:58 +0000
Subject: [PATCH 3/4] o Rename dou_ds_ (display subsystem) to dou_bs_ (backend
subsystem); o Move dou_bs_control() call.
---
sys/dev/drm/komeda/komeda_pipeline.c | 5 +++--
sys/dev/drm/komeda/komeda_plane.c | 6 ++----
sys/dev/drm/komeda/komeda_plane.h | 4 ++--
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/sys/dev/drm/komeda/komeda_pipeline.c b/sys/dev/drm/komeda/komeda_pipeline.c
index 63fac009e9e2..ac499e98029d 100644
--- a/sys/dev/drm/komeda/komeda_pipeline.c
+++ b/sys/dev/drm/komeda/komeda_pipeline.c
@@ -244,7 +244,8 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc,
clk_enable(pipeline->pxclk);
dou_configure(sc, adj);
- dou_ds_timing_setup(sc, adj);
+ dou_bs_timing_setup(sc, adj);
+ dou_bs_control(sc, true);
/* Enable VBLANK events */
drm_crtc_vblank_on(crtc);
@@ -277,7 +278,7 @@ komeda_crtc_atomic_disable(struct drm_crtc *crtc,
komeda_pipeline_set_mode(sc, CONTROL_MODE_INACTIVE);
- dou_ds_control(sc, false);
+ dou_bs_control(sc, false);
clk_disable(pipeline->pxclk);
}
diff --git a/sys/dev/drm/komeda/komeda_plane.c b/sys/dev/drm/komeda/komeda_plane.c
index 9de6dc59f277..da66caef25dd 100644
--- a/sys/dev/drm/komeda/komeda_plane.c
+++ b/sys/dev/drm/komeda/komeda_plane.c
@@ -183,7 +183,7 @@ komeda_plane_atomic_disable(struct drm_plane *plane,
}
void
-dou_ds_control(struct komeda_drm_softc *sc, bool enable)
+dou_bs_control(struct komeda_drm_softc *sc, bool enable)
{
int reg;
@@ -196,7 +196,7 @@ dou_ds_control(struct komeda_drm_softc *sc, bool enable)
}
void
-dou_ds_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m)
+dou_bs_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m)
{
uint32_t hactive, hfront_porch, hback_porch, hsync_len;
uint32_t vactive, vfront_porch, vback_porch, vsync_len;
@@ -232,8 +232,6 @@ dou_ds_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m)
DPU_WR4(sc, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1);
DPU_WR4(sc, BS_PREFETCH_LINE, D71_DEFAULT_PREPRETCH_LINE);
-
- dou_ds_control(sc, true);
}
void
diff --git a/sys/dev/drm/komeda/komeda_plane.h b/sys/dev/drm/komeda/komeda_plane.h
index 918f76fa0664..d1f855c81ad8 100644
--- a/sys/dev/drm/komeda/komeda_plane.h
+++ b/sys/dev/drm/komeda/komeda_plane.h
@@ -50,8 +50,8 @@ void dou_intr(struct komeda_drm_softc *sc);
void lpu_intr(struct komeda_drm_softc *sc);
void cu_intr(struct komeda_drm_softc *sc);
void dou_configure(struct komeda_drm_softc *sc, struct drm_display_mode *m);
-void dou_ds_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m);
-void dou_ds_control(struct komeda_drm_softc *sc, bool enable);
+void dou_bs_timing_setup(struct komeda_drm_softc *sc, struct drm_display_mode *m);
+void dou_bs_control(struct komeda_drm_softc *sc, bool enable);
void cu_configure(struct komeda_drm_softc *sc, struct drm_display_mode *m,
struct drm_plane_state *state, int id);
From 248b820e3092df64bc6855e5fb8d3b5cc8b6c6e0 Mon Sep 17 00:00:00 2001
From: Ruslan Bukin
Date: Fri, 20 Jan 2023 15:20:58 +0000
Subject: [PATCH 4/4] kill HDMI clock in tda19988_bridge_disable
---
sys/dev/drm/bridges/tda19988/tda19988.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sys/dev/drm/bridges/tda19988/tda19988.c b/sys/dev/drm/bridges/tda19988/tda19988.c
index aaff00305a42..aba88a5a6ed9 100644
--- a/sys/dev/drm/bridges/tda19988/tda19988.c
+++ b/sys/dev/drm/bridges/tda19988/tda19988.c
@@ -898,6 +898,8 @@ tda19988_bridge_disable(struct drm_bridge *bridge)
tda19988_reg_write(sc, TDA_ENA_VP_0, 0);
tda19988_reg_write(sc, TDA_ENA_VP_1, 0);
tda19988_reg_write(sc, TDA_ENA_VP_2, 0);
+
+ tda19988_reg_write(sc, TDA_BUFFER_OUT, 0x8);
}
static void
@@ -911,6 +913,8 @@ tda19988_bridge_enable(struct drm_bridge *bridge)
tda19988_reg_write(sc, TDA_ENA_VP_0, 0xff);
tda19988_reg_write(sc, TDA_ENA_VP_1, 0xff);
tda19988_reg_write(sc, TDA_ENA_VP_2, 0xff);
+
+ tda19988_reg_write(sc, TDA_BUFFER_OUT, 0);
}
static const struct drm_bridge_funcs tda19988_bridge_funcs = {