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