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