diff --git a/sys/dev/drm/bridges/tda19988/tda19988.c b/sys/dev/drm/bridges/tda19988/tda19988.c index a6420af9e822..49015a496feb 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) @@ -108,8 +111,10 @@ __FBSDID("$FreeBSD$"); #define TDA_REFLINE_LSB MKREG(0x00, 0xa4) #define TDA_NPIX_MSB MKREG(0x00, 0xa5) #define TDA_NPIX_LSB MKREG(0x00, 0xa6) +#define NPIX_MAX ((1 << 13) - 1) #define TDA_NLINE_MSB MKREG(0x00, 0xa7) #define TDA_NLINE_LSB MKREG(0x00, 0xa8) +#define NLINE_MAX ((1 << 11) - 1) #define TDA_VS_LINE_STRT_1_MSB MKREG(0x00, 0xa9) #define TDA_VS_LINE_STRT_1_LSB MKREG(0x00, 0xaa) #define TDA_VS_PIX_STRT_1_MSB MKREG(0x00, 0xab) @@ -266,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 @@ -441,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(void *context, uint8_t *buf, unsigned int block, size_t len) @@ -841,26 +699,180 @@ static enum drm_mode_status tda19988_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_mode *mode) { + struct tda19988_softc *sc; + int clock_max; + + sc = container_of(bridge, struct tda19988_softc, bridge); + + clock_max = sc->sc_version == TDA19988 ? 165000 : 150000; + if (mode->clock > clock_max) + return (MODE_CLOCK_HIGH); + + if (mode->htotal > NPIX_MAX) + return (MODE_BAD_HVALUE); + + if (mode->vtotal > NLINE_MAX) + return (MODE_BAD_VVALUE); return (MODE_OK); } static void tda19988_bridge_mode_set(struct drm_bridge *bridge, - const struct drm_display_mode *orig_mode, - const struct drm_display_mode *mode) + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) { struct tda19988_softc *sc; + 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; sc = container_of(bridge, struct tda19988_softc, bridge); - memcpy(&sc->mode, mode, sizeof(struct drm_display_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 (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW) + ref_pix += adjusted_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 = imin(imax(fls(160000 / (mode->crtc_clock + 1)) - 1, 0), 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 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); + + tda19988_reg_write(sc, TDA_BUFFER_OUT, 0x8); } static void @@ -870,25 +882,12 @@ 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); + 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 = { diff --git a/sys/dev/drm/komeda/komeda_drv.c b/sys/dev/drm/komeda/komeda_drv.c index b7fcf26d81fc..339f630a0869 100644 --- a/sys/dev/drm/komeda/komeda_drv.c +++ b/sys/dev/drm/komeda/komeda_drv.c @@ -303,10 +303,6 @@ komeda_drm_irq_hook(void *arg) sc->drm_dev.mode_config.max_width = 4096; sc->drm_dev.mode_config.max_height = 4096; - /* Temporary hack. */ - sc->drm_dev.mode_config.max_width = 1920; - sc->drm_dev.mode_config.max_height = 1200; - sc->drm_dev.mode_config.funcs = &komeda_drm_mode_config_funcs; sc->drm_dev.mode_config.helper_private = &komeda_drm_mode_config_helpers;