xref: /linux/drivers/gpu/drm/mgag200/mgag200_bmc.c (revision 6f7e6393d1ce636bb7ec77a7fe7b77458fddf701)
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 
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 
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