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
mgag200_bmc_stop_scanout(struct mga_device * mdev)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
mgag200_bmc_start_scanout(struct mga_device * mdev)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