Skip to content

Commit 891d1fb

Browse files
jrtc27bukinr
authored andcommitted
tda19988: Properly implement mode_set/bridge_enable/bridge_disable flow
Otherwise, when SDDM tries to put the display to sleep, we don't disable the output and end up outputting a garbled picture, where the amount of garbling increases with system activity. Co-authored-by: Ruslan Bukin <[email protected]>
1 parent 195b1cd commit 891d1fb

File tree

1 file changed

+157
-169
lines changed

1 file changed

+157
-169
lines changed

sys/dev/drm/bridges/tda19988/tda19988.c

Lines changed: 157 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ __FBSDID("$FreeBSD$");
7878
#define CTRL_INTR_EN_GLO_MASK 0x04
7979
#define TDA_INT_FLAGS_2 MKREG(0x00, 0x11)
8080
#define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
81+
#define TDA_ENA_VP_0 MKREG(0x00, 0x18)
82+
#define TDA_ENA_VP_1 MKREG(0x00, 0x19)
83+
#define TDA_ENA_VP_2 MKREG(0x00, 0x1a)
8184

8285
#define TDA_VIP_CNTRL_0 MKREG(0x00, 0x20)
8386
#define TDA_VIP_CNTRL_1 MKREG(0x00, 0x21)
@@ -268,7 +271,6 @@ struct tda19988_softc {
268271
struct drm_encoder encoder;
269272
struct drm_connector connector __subobject_use_container_bounds;
270273
struct drm_bridge bridge __subobject_use_container_bounds;
271-
struct drm_display_mode mode;
272274
};
273275

274276
static int
@@ -443,152 +445,6 @@ tda19988_probe(device_t dev)
443445
return (BUS_PROBE_DEFAULT);
444446
}
445447

446-
static void
447-
tda19988_init_encoder(struct tda19988_softc *sc)
448-
{
449-
const struct drm_display_mode *mode;
450-
uint16_t ref_pix, ref_line, n_pix, n_line;
451-
uint16_t hs_pix_start, hs_pix_stop;
452-
uint16_t vs1_pix_start, vs1_pix_stop;
453-
uint16_t vs1_line_start, vs1_line_end;
454-
uint16_t vs2_pix_start, vs2_pix_stop;
455-
uint16_t vs2_line_start, vs2_line_end;
456-
uint16_t vwin1_line_start, vwin1_line_end;
457-
uint16_t vwin2_line_start, vwin2_line_end;
458-
uint16_t de_start, de_stop;
459-
uint8_t reg, div;
460-
461-
mode = &sc->mode;
462-
463-
n_pix = mode->htotal;
464-
n_line = mode->vtotal;
465-
466-
hs_pix_stop = mode->hsync_end - mode->hdisplay;
467-
hs_pix_start = mode->hsync_start - mode->hdisplay;
468-
469-
de_stop = mode->htotal;
470-
de_start = mode->htotal - mode->hdisplay;
471-
ref_pix = hs_pix_start + 3;
472-
473-
if (mode->flags & DRM_MODE_FLAG_HSKEW)
474-
ref_pix += mode->hskew;
475-
476-
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
477-
ref_line = 1 + mode->vsync_start - mode->vdisplay;
478-
vwin1_line_start = mode->vtotal - mode->vdisplay - 1;
479-
vwin1_line_end = vwin1_line_start + mode->vdisplay;
480-
481-
vs1_pix_start = vs1_pix_stop = hs_pix_start;
482-
vs1_line_start = mode->vsync_start - mode->vdisplay;
483-
vs1_line_end = vs1_line_start + mode->vsync_end - mode->vsync_start;
484-
485-
vwin2_line_start = vwin2_line_end = 0;
486-
vs2_pix_start = vs2_pix_stop = 0;
487-
vs2_line_start = vs2_line_end = 0;
488-
} else {
489-
ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
490-
vwin1_line_start = (mode->vtotal - mode->vdisplay)/2;
491-
vwin1_line_end = vwin1_line_start + mode->vdisplay/2;
492-
493-
vs1_pix_start = vs1_pix_stop = hs_pix_start;
494-
vs1_line_start = (mode->vsync_start - mode->vdisplay)/2;
495-
vs1_line_end = vs1_line_start + (mode->vsync_end - mode->vsync_start)/2;
496-
497-
vwin2_line_start = vwin1_line_start + mode->vtotal/2;
498-
vwin2_line_end = vwin2_line_start + mode->vdisplay/2;
499-
500-
vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2;
501-
vs2_line_start = vs1_line_start + mode->vtotal/2 ;
502-
vs2_line_end = vs2_line_start + (mode->vsync_end - mode->vsync_start)/2;
503-
}
504-
505-
div = 148500 / mode->crtc_clock;
506-
if (div != 0) {
507-
div--;
508-
if (div > 3)
509-
div = 3;
510-
}
511-
512-
/* set HDMI HDCP mode off */
513-
tda19988_reg_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
514-
tda19988_reg_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI);
515-
tda19988_reg_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE);
516-
517-
/* no pre-filter or interpolator */
518-
tda19988_reg_write(sc, TDA_HVF_CNTRL_0,
519-
HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE);
520-
tda19988_reg_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
521-
tda19988_reg_write(sc, TDA_VIP_CNTRL_4,
522-
VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE);
523-
524-
tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
525-
tda19988_reg_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP);
526-
tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
527-
tda19988_reg_write(sc, TDA_SERIALIZER, 0);
528-
tda19988_reg_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL);
529-
530-
tda19988_reg_write(sc, TDA_RPT_CNTRL, 0);
531-
tda19988_reg_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
532-
SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
533-
534-
tda19988_reg_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
535-
PLL_SERIAL_2_SRL_PR(0));
536-
537-
tda19988_reg_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP);
538-
539-
tda19988_reg_write(sc, TDA_ANA_GENERAL, 0x09);
540-
541-
tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
542-
543-
/*
544-
* Sync on rising HSYNC/VSYNC
545-
*/
546-
reg = VIP_CNTRL_3_SYNC_HS;
547-
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
548-
reg |= VIP_CNTRL_3_H_TGL;
549-
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
550-
reg |= VIP_CNTRL_3_V_TGL;
551-
tda19988_reg_write(sc, TDA_VIP_CNTRL_3, reg);
552-
553-
reg = TBG_CNTRL_1_TGL_EN;
554-
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
555-
reg |= TBG_CNTRL_1_H_TGL;
556-
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
557-
reg |= TBG_CNTRL_1_V_TGL;
558-
tda19988_reg_write(sc, TDA_TBG_CNTRL_1, reg);
559-
560-
/* Program timing */
561-
tda19988_reg_write(sc, TDA_VIDFORMAT, 0x00);
562-
563-
tda19988_reg_write2(sc, TDA_REFPIX_MSB, ref_pix);
564-
tda19988_reg_write2(sc, TDA_REFLINE_MSB, ref_line);
565-
tda19988_reg_write2(sc, TDA_NPIX_MSB, n_pix);
566-
tda19988_reg_write2(sc, TDA_NLINE_MSB, n_line);
567-
568-
tda19988_reg_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start);
569-
tda19988_reg_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start);
570-
tda19988_reg_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end);
571-
tda19988_reg_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop);
572-
tda19988_reg_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start);
573-
tda19988_reg_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start);
574-
tda19988_reg_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end);
575-
tda19988_reg_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop);
576-
tda19988_reg_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start);
577-
tda19988_reg_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop);
578-
tda19988_reg_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start);
579-
tda19988_reg_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end);
580-
tda19988_reg_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start);
581-
tda19988_reg_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end);
582-
tda19988_reg_write2(sc, TDA_DE_START_MSB, de_start);
583-
tda19988_reg_write2(sc, TDA_DE_STOP_MSB, de_stop);
584-
585-
if (sc->sc_version == TDA19988)
586-
tda19988_reg_write(sc, TDA_ENABLE_SPACE, 0x00);
587-
588-
/* must be last register set */
589-
tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
590-
}
591-
592448
static int
593449
tda19988_read_edid_block(void *context, uint8_t *buf, unsigned int block,
594450
size_t len)
@@ -863,20 +719,165 @@ tda19988_bridge_mode_valid(struct drm_bridge *bridge,
863719

864720
static void
865721
tda19988_bridge_mode_set(struct drm_bridge *bridge,
866-
const struct drm_display_mode *orig_mode,
867-
const struct drm_display_mode *mode)
722+
const struct drm_display_mode *mode,
723+
const struct drm_display_mode *adjusted_mode)
868724
{
869725
struct tda19988_softc *sc;
726+
uint16_t ref_pix, ref_line, n_pix, n_line;
727+
uint16_t hs_pix_start, hs_pix_stop;
728+
uint16_t vs1_pix_start, vs1_pix_stop;
729+
uint16_t vs1_line_start, vs1_line_end;
730+
uint16_t vs2_pix_start, vs2_pix_stop;
731+
uint16_t vs2_line_start, vs2_line_end;
732+
uint16_t vwin1_line_start, vwin1_line_end;
733+
uint16_t vwin2_line_start, vwin2_line_end;
734+
uint16_t de_start, de_stop;
735+
uint8_t reg, div;
870736

871737
sc = container_of(bridge, struct tda19988_softc, bridge);
872738

873-
memcpy(&sc->mode, mode, sizeof(struct drm_display_mode));
739+
n_pix = mode->htotal;
740+
n_line = mode->vtotal;
741+
742+
hs_pix_stop = mode->hsync_end - mode->hdisplay;
743+
hs_pix_start = mode->hsync_start - mode->hdisplay;
744+
745+
de_stop = mode->htotal;
746+
de_start = mode->htotal - mode->hdisplay;
747+
ref_pix = hs_pix_start + 3;
748+
749+
if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW)
750+
ref_pix += adjusted_mode->hskew;
751+
752+
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
753+
ref_line = 1 + mode->vsync_start - mode->vdisplay;
754+
vwin1_line_start = mode->vtotal - mode->vdisplay - 1;
755+
vwin1_line_end = vwin1_line_start + mode->vdisplay;
756+
757+
vs1_pix_start = vs1_pix_stop = hs_pix_start;
758+
vs1_line_start = mode->vsync_start - mode->vdisplay;
759+
vs1_line_end = vs1_line_start + mode->vsync_end - mode->vsync_start;
760+
761+
vwin2_line_start = vwin2_line_end = 0;
762+
vs2_pix_start = vs2_pix_stop = 0;
763+
vs2_line_start = vs2_line_end = 0;
764+
} else {
765+
ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
766+
vwin1_line_start = (mode->vtotal - mode->vdisplay)/2;
767+
vwin1_line_end = vwin1_line_start + mode->vdisplay/2;
768+
769+
vs1_pix_start = vs1_pix_stop = hs_pix_start;
770+
vs1_line_start = (mode->vsync_start - mode->vdisplay)/2;
771+
vs1_line_end = vs1_line_start + (mode->vsync_end - mode->vsync_start)/2;
772+
773+
vwin2_line_start = vwin1_line_start + mode->vtotal/2;
774+
vwin2_line_end = vwin2_line_start + mode->vdisplay/2;
775+
776+
vs2_pix_start = vs2_pix_stop = hs_pix_start + mode->htotal/2;
777+
vs2_line_start = vs1_line_start + mode->vtotal/2 ;
778+
vs2_line_end = vs2_line_start + (mode->vsync_end - mode->vsync_start)/2;
779+
}
780+
781+
div = 148500 / mode->crtc_clock;
782+
if (div != 0) {
783+
div--;
784+
if (div > 3)
785+
div = 3;
786+
}
787+
788+
/* set HDMI HDCP mode off */
789+
tda19988_reg_set(sc, TDA_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
790+
tda19988_reg_clear(sc, TDA_HDCP_TX33, HDCP_TX33_HDMI);
791+
tda19988_reg_write(sc, TDA_ENC_CNTRL, ENC_CNTRL_DVI_MODE);
792+
793+
/* no pre-filter or interpolator */
794+
tda19988_reg_write(sc, TDA_HVF_CNTRL_0,
795+
HVF_CNTRL_0_INTPOL_BYPASS | HVF_CNTRL_0_PREFIL_NONE);
796+
tda19988_reg_write(sc, TDA_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
797+
tda19988_reg_write(sc, TDA_VIP_CNTRL_4,
798+
VIP_CNTRL_4_BLANKIT_NDE | VIP_CNTRL_4_BLC_NONE);
799+
800+
tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
801+
tda19988_reg_clear(sc, TDA_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IP);
802+
tda19988_reg_clear(sc, TDA_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
803+
tda19988_reg_write(sc, TDA_SERIALIZER, 0);
804+
tda19988_reg_write(sc, TDA_HVF_CNTRL_1, HVF_CNTRL_1_VQR_FULL);
805+
806+
tda19988_reg_write(sc, TDA_RPT_CNTRL, 0);
807+
tda19988_reg_write(sc, TDA_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
808+
SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
809+
810+
tda19988_reg_write(sc, TDA_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
811+
PLL_SERIAL_2_SRL_PR(0));
812+
813+
tda19988_reg_set(sc, TDA_MAT_CONTRL, MAT_CONTRL_MAT_BP);
814+
815+
tda19988_reg_write(sc, TDA_ANA_GENERAL, 0x09);
816+
817+
tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
818+
819+
/*
820+
* Sync on rising HSYNC/VSYNC
821+
*/
822+
reg = VIP_CNTRL_3_SYNC_HS;
823+
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
824+
reg |= VIP_CNTRL_3_H_TGL;
825+
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
826+
reg |= VIP_CNTRL_3_V_TGL;
827+
tda19988_reg_write(sc, TDA_VIP_CNTRL_3, reg);
828+
829+
reg = TBG_CNTRL_1_TGL_EN;
830+
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
831+
reg |= TBG_CNTRL_1_H_TGL;
832+
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
833+
reg |= TBG_CNTRL_1_V_TGL;
834+
tda19988_reg_write(sc, TDA_TBG_CNTRL_1, reg);
835+
836+
/* Program timing */
837+
tda19988_reg_write(sc, TDA_VIDFORMAT, 0x00);
838+
839+
tda19988_reg_write2(sc, TDA_REFPIX_MSB, ref_pix);
840+
tda19988_reg_write2(sc, TDA_REFLINE_MSB, ref_line);
841+
tda19988_reg_write2(sc, TDA_NPIX_MSB, n_pix);
842+
tda19988_reg_write2(sc, TDA_NLINE_MSB, n_line);
843+
844+
tda19988_reg_write2(sc, TDA_VS_LINE_STRT_1_MSB, vs1_line_start);
845+
tda19988_reg_write2(sc, TDA_VS_PIX_STRT_1_MSB, vs1_pix_start);
846+
tda19988_reg_write2(sc, TDA_VS_LINE_END_1_MSB, vs1_line_end);
847+
tda19988_reg_write2(sc, TDA_VS_PIX_END_1_MSB, vs1_pix_stop);
848+
tda19988_reg_write2(sc, TDA_VS_LINE_STRT_2_MSB, vs2_line_start);
849+
tda19988_reg_write2(sc, TDA_VS_PIX_STRT_2_MSB, vs2_pix_start);
850+
tda19988_reg_write2(sc, TDA_VS_LINE_END_2_MSB, vs2_line_end);
851+
tda19988_reg_write2(sc, TDA_VS_PIX_END_2_MSB, vs2_pix_stop);
852+
tda19988_reg_write2(sc, TDA_HS_PIX_START_MSB, hs_pix_start);
853+
tda19988_reg_write2(sc, TDA_HS_PIX_STOP_MSB, hs_pix_stop);
854+
tda19988_reg_write2(sc, TDA_VWIN_START_1_MSB, vwin1_line_start);
855+
tda19988_reg_write2(sc, TDA_VWIN_END_1_MSB, vwin1_line_end);
856+
tda19988_reg_write2(sc, TDA_VWIN_START_2_MSB, vwin2_line_start);
857+
tda19988_reg_write2(sc, TDA_VWIN_END_2_MSB, vwin2_line_end);
858+
tda19988_reg_write2(sc, TDA_DE_START_MSB, de_start);
859+
tda19988_reg_write2(sc, TDA_DE_STOP_MSB, de_stop);
860+
861+
if (sc->sc_version == TDA19988)
862+
tda19988_reg_write(sc, TDA_ENABLE_SPACE, 0x00);
863+
864+
/* must be last register set */
865+
tda19988_reg_clear(sc, TDA_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
874866
}
875867

876868
static void
877869
tda19988_bridge_disable(struct drm_bridge *bridge)
878870
{
871+
struct tda19988_softc *sc;
879872

873+
sc = container_of(bridge, struct tda19988_softc, bridge);
874+
875+
/* Disable Video Ports */
876+
tda19988_reg_write(sc, TDA_ENA_VP_0, 0);
877+
tda19988_reg_write(sc, TDA_ENA_VP_1, 0);
878+
tda19988_reg_write(sc, TDA_ENA_VP_2, 0);
879+
880+
tda19988_reg_write(sc, TDA_BUFFER_OUT, 0x8);
880881
}
881882

882883
static void
@@ -886,25 +887,12 @@ tda19988_bridge_enable(struct drm_bridge *bridge)
886887

887888
sc = container_of(bridge, struct tda19988_softc, bridge);
888889

889-
dprintf(sc->dev, "Mode information:\n"
890-
"hdisplay: %d\n"
891-
"vdisplay: %d\n"
892-
"htotal: %d\n"
893-
"vtotal: %d\n"
894-
"hsync_start: %d\n"
895-
"hsync_end: %d\n"
896-
"vsync_start: %d\n"
897-
"vsync_end: %d\n",
898-
sc->mode.hdisplay,
899-
sc->mode.vdisplay,
900-
sc->mode.htotal,
901-
sc->mode.vtotal,
902-
sc->mode.hsync_start,
903-
sc->mode.hsync_end,
904-
sc->mode.vsync_start,
905-
sc->mode.vsync_end);
906-
907-
tda19988_init_encoder(sc);
890+
/* Enable Video Ports */
891+
tda19988_reg_write(sc, TDA_ENA_VP_0, 0xff);
892+
tda19988_reg_write(sc, TDA_ENA_VP_1, 0xff);
893+
tda19988_reg_write(sc, TDA_ENA_VP_2, 0xff);
894+
895+
tda19988_reg_write(sc, TDA_BUFFER_OUT, 0);
908896
}
909897

910898
static const struct drm_bridge_funcs tda19988_bridge_funcs = {

0 commit comments

Comments
 (0)