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 = {