xref: /linux/drivers/gpu/drm/mgag200/mgag200_bmc.c (revision 219b45d023ed0902b05c5902a4f31c2c38bcf68c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/delay.h>
4 
5 #include <drm/drm_atomic_helper.h>
6 #include <drm/drm_edid.h>
7 #include <drm/drm_managed.h>
8 #include <drm/drm_probe_helper.h>
9 
10 #include "mgag200_drv.h"
11 
12 void mgag200_bmc_stop_scanout(struct mga_device *mdev)
13 {
14 	u8 tmp;
15 	int iter_max;
16 
17 	/*
18 	 * 1 - The first step is to inform the BMC of an upcoming mode
19 	 * change. We are putting the misc<0> to output.
20 	 */
21 
22 	WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
23 	tmp = RREG8(DAC_DATA);
24 	tmp |= 0x10;
25 	WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
26 
27 	/* we are putting a 1 on the misc<0> line */
28 	WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
29 	tmp = RREG8(DAC_DATA);
30 	tmp |= 0x10;
31 	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
32 
33 	/*
34 	 * 2- Second step to mask any further scan request. This is
35 	 * done by asserting the remfreqmsk bit (XSPAREREG<7>)
36 	 */
37 
38 	WREG8(DAC_INDEX, MGA1064_SPAREREG);
39 	tmp = RREG8(DAC_DATA);
40 	tmp |= 0x80;
41 	WREG_DAC(MGA1064_SPAREREG, tmp);
42 
43 	/*
44 	 * 3a- The third step is to verify if there is an active scan.
45 	 * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
46 	 */
47 	iter_max = 300;
48 	while (!(tmp & 0x1) && iter_max) {
49 		WREG8(DAC_INDEX, MGA1064_SPAREREG);
50 		tmp = RREG8(DAC_DATA);
51 		udelay(1000);
52 		iter_max--;
53 	}
54 
55 	/*
56 	 * 3b- This step occurs only if the remove is actually
57 	 * scanning. We are waiting for the end of the frame which is
58 	 * a 1 on remvsyncsts (XSPAREREG<1>)
59 	 */
60 	if (iter_max) {
61 		iter_max = 300;
62 		while ((tmp & 0x2) && iter_max) {
63 			WREG8(DAC_INDEX, MGA1064_SPAREREG);
64 			tmp = RREG8(DAC_DATA);
65 			udelay(1000);
66 			iter_max--;
67 		}
68 	}
69 }
70 
71 void mgag200_bmc_start_scanout(struct mga_device *mdev)
72 {
73 	u8 tmp;
74 
75 	/* Assert rstlvl2 */
76 	WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
77 	tmp = RREG8(DAC_DATA);
78 	tmp |= 0x8;
79 	WREG8(DAC_DATA, tmp);
80 
81 	udelay(10);
82 
83 	/* Deassert rstlvl2 */
84 	tmp &= ~0x08;
85 	WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
86 	WREG8(DAC_DATA, tmp);
87 
88 	/* Remove mask of scan request */
89 	WREG8(DAC_INDEX, MGA1064_SPAREREG);
90 	tmp = RREG8(DAC_DATA);
91 	tmp &= ~0x80;
92 	WREG8(DAC_DATA, tmp);
93 
94 	/* Put back a 0 on the misc<0> line */
95 	WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
96 	tmp = RREG8(DAC_DATA);
97 	tmp &= ~0x10;
98 	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
99 }
100