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