ref: a194f52c9377e010c31612d6484cbd43df6d5e24
parent: a609c6102f28f53a9a151804998d4e4b5347ddb5
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Thu Sep 1 16:51:06 EDT 2022
imx8/lcd: toggle lcdif on blankscreen Stop DOTCLK on interrupt after the current frame is done, toggle PWM2.
--- a/sys/src/9/imx8/io.h
+++ b/sys/src/9/imx8/io.h
@@ -7,6 +7,8 @@
IRQcntps = PPI+13,
IRQcntpns = PPI+14,
+ IRQlcdif = SPI+5,
+
IRQusdhc1 = SPI+22,
IRQusdhc2 = SPI+23,
--- a/sys/src/9/imx8/lcd.c
+++ b/sys/src/9/imx8/lcd.c
@@ -356,6 +356,11 @@
static u32int *lcdif = (u32int*)(VIRTIO + 0x320000);
+static struct {
+ Lock;
+ int blank;
+}lcdifirq;
+
/* shift and mask */
static u32int
sm(u32int v, u32int m)
@@ -464,7 +469,8 @@
/* enable underflow recovery to fix image shift */
wr(lcdif, LCDIF_CTRL1,
sm(7, CTRL1_BYTE_PACKING_FORMAT) |
- CTRL1_RECOVER_ON_UNDERFLOW);
+ CTRL1_RECOVER_ON_UNDERFLOW |
+ CTRL1_CUR_FRAME_DONE_IRQ_EN);
wr(lcdif, LCDIF_CTRL,
CTRL_BYPASS_COUNT |
@@ -828,10 +834,35 @@
gpioout(GPIO_PIN(1, 10), 1);
}
+static void
+lcdifinterrupt(Ureg *, void *)
+{
+ wr(lcdif, LCDIF_CTRL1_CLR, CTRL1_CUR_FRAME_DONE_IRQ);
+ ilock(&lcdifirq);
+ if(lcdifirq.blank){
+ /* turn off dotclk */
+ wr(lcdif, LCDIF_CTRL_CLR, CTRL_DOTCLK_MODE);
+ /* wait for the fifo to empty */
+ while(rr(lcdif, LCDIF_CTRL) & CTRL_RUN)
+ ;
+ lcdifirq.blank = 0;
+ }
+ iunlock(&lcdifirq);
+}
+
void
blankscreen(int blank)
{
+ ilock(&lcdifirq);
+ lcdifirq.blank = blank;
+ if(blank == 0) /* restart lcdif */
+ wr(lcdif, LCDIF_CTRL_SET, CTRL_DOTCLK_MODE | CTRL_RUN);
+ iunlock(&lcdifirq);
+
+ /* toggle panel backlight */
gpioout(GPIO_PIN(1, 10), blank == 0);
+ /* toggle PWM2 */
+ mr(pwm2, PWMCR, (blank == 0)*CR_EN, CR_EN);
}
static void
@@ -890,6 +921,8 @@
setclkgate("sim_display.mainclk", 1);
lcdifreset();
+
+ intrenable(IRQlcdif, lcdifinterrupt, nil, BUSUNKNOWN, "lcdif");
setclkrate("mipi.core", "system_pll1_div3", 266*Mhz);
setclkrate("mipi.CLKREF", "system_pll2_clk", 25*Mhz);