From 70385bc17adf35ba165a85a1b9e6b649bf48030e Mon Sep 17 00:00:00 2001
From: Jeffrey Lee <jlee@gitlab.riscosopen.org>
Date: Sun, 20 Jul 2014 14:17:29 +0000
Subject: [PATCH] Disallow EDID writes. Add support for EDID reads which
 require the segment pointer to be set. Improve Pandora screen blanking.

Detail:
  s/I2C - Revise HAL_VideoIICOp implementation to disallow EDID writes (&A0 IIC address). Attempt to write the EDID segment pointer when accessing EDID addresses >= 256.
  s/Video - Make Pandora screen blanking put the LCD into/out of standby mode. If it's left active while the video sync signals are cut then there'll often be garbage displayed on the screen.
Admin:
  Tested on BB-xM, Pandora


Version 0.97. Tagged as 'OMAP3-0_97'
---
 VersionNum | 20 ++++++++++----------
 s/I2C      | 54 ++++++++++++++++++++++++++++++++++--------------------
 s/Video    | 27 ++++++++++++++++++++++++++-
 3 files changed, 70 insertions(+), 31 deletions(-)

diff --git a/VersionNum b/VersionNum
index 6fe1e26..1b361f9 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,23 @@
-/* (0.96)
+/* (0.97)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  * Last processed by srccommit version: 1.1.
  *
  */
-#define Module_MajorVersion_CMHG        0.96
+#define Module_MajorVersion_CMHG        0.97
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                14 Apr 2014
+#define Module_Date_CMHG                20 Jul 2014
 
-#define Module_MajorVersion             "0.96"
-#define Module_Version                  96
+#define Module_MajorVersion             "0.97"
+#define Module_Version                  97
 #define Module_MinorVersion             ""
-#define Module_Date                     "14 Apr 2014"
+#define Module_Date                     "20 Jul 2014"
 
-#define Module_ApplicationDate          "14-Apr-14"
+#define Module_ApplicationDate          "20-Jul-14"
 
 #define Module_ComponentName            "OMAP3"
 #define Module_ComponentPath            "castle/RiscOS/Sources/HAL/OMAP3"
 
-#define Module_FullVersion              "0.96"
-#define Module_HelpVersion              "0.96 (14 Apr 2014)"
-#define Module_LibraryVersionInfo       "0:96"
+#define Module_FullVersion              "0.97"
+#define Module_HelpVersion              "0.97 (20 Jul 2014)"
+#define Module_LibraryVersionInfo       "0:97"
diff --git a/s/I2C b/s/I2C
index f9b6286..6f60aa3 100644
--- a/s/I2C
+++ b/s/I2C
@@ -672,7 +672,7 @@ read_bytes
 
 ; int HAL_VideoIICOp(uint32_t op, uint8_t *buffer, uint32_t *size)
 ; in:
-;      r0 = b0-15 offset within IIC device to start at (currently assumed 8 bit)
+;      r0 = b0-15 offset within IIC device to start at
 ;           b16-23 base IICAddress
 ;           b24-31 zero
 ;      r1 = buffer to read from/write to
@@ -689,37 +689,51 @@ HAL_VideoIICOp
         STREQ   ip, [a3]
         MOVEQ   a1, #IICStatus_Error
         MOVEQ   pc, lr
-        ; Check for input passed end
-        UBFX    a4, a1, #0, #16
-        CMP     a4, #256
-        STRCS   ip, [a3]
-        MOVCS   a1, #IICStatus_Completed
-        MOVCS   pc, lr
-        ; Clip request at end
+        ; Check if this is an EDID read or write
+        UBFX    a4, a1, #16, #8
+        TEQ     a4, #&a0 ; Don't allow writing to EDID for safety reasons
+        STREQ   ip, [a3]
+        MOVEQ   a1, #IICStatus_Error
+        MOVEQ   pc, lr
+        TEQ     a4, #&a1
+        TSTNE   a1, #&ff00 ; If not EDID read, limit to 0-255 offset in device
+        STRNE   ip, [a3]
+        MOVNE   a1, #IICStatus_Completed
+        MOVNE   pc, lr
         Push    "a1-a3,lr"
         LDR     a3, [a3]
-        ADD     ip, a4, a3
-        CMP     ip, #256
-        RSBHI   a3, a4, #256
 
         ; Build a set of iic_transfer blocks and call RISCOS_IICOpV
-        ; We construct two iic_transfer blocks
-        ; - First block is a single byte write containing the start address (lower 8 bits of r0)
-        ; - Second block is a read. r2 bytes written to r1.
-        ; Block 2:
+        ; We construct (up to) three iic_transfer blocks
+        ; - First block is an (optional) single byte write to the EDID segment pointer
+        ; - Second block is a single byte write containing the start address (lower 8 bits of r0)
+        ; - Third block is a read. r2 bytes written to r1.
+        ; The E-EDID EEPROM spec says that the segment pointer should auto-increment when a sequential (i.e. block) read occurs, so we shouldn't have to worry about splitting requests into 256 byte blocks and manually writing the pointer each time.
+        ; Block 3:
         UBFX    a1, a1, #16, #8 ; Extract base IICAddress
         Push    "a1-a3"         ; Push the block on the stack (a2 & a3 are already correct)
-        ; Block 1:
+        ; Block 2:
         BIC     a1, a1, #1      ; Clear RnW of base address
         ADD     a2, sp, #12     ; sp+12 should point to the 8 bit offset
         MOV     a3, #1
         Push    "a1-a3"
-
+        ; Block 1:
+        MOV     a1, #&60        ; Write to segment pointer
+        ADD     a2, a2, #1      ; With bits 8-15 of the offset
+        Push    "a1-a3"
+        ; Work out if block 1 is needed or not
+        LDR     a2, [sp, #36]   ; Get r0
+        TST     a2, #&ff00      ; If segment == 0
+        MOVEQ   a2, #0          ; ... then avoid matching address &A0/&A1
+        AND     a2, a2, #&fe0000
+        TEQ     a2, #&a00000
         ; Now attempt to start the transfer
         LDRB    a2, [sb, #BoardConfig_VideoI2C]
         MOV     a2, a2, LSL #24
-        ADD     a2, a2, #2
+        ADD     a2, a2, #3
         MOV     a1, sp
+        SUBNE   a2, a2, #1      ; Skip block 1 if segment == 0 or not EDID addr
+        ADDNE   a1, a1, #12
         ; If HAL_Init isn't done yet, we can't use RISCOS_IICOpV
         LDR     a3, HALInitialised
         CMP     a3, #0
@@ -732,9 +746,9 @@ HAL_VideoIICOp
 20
         ; In case of error, assume nothing got transferred at all
         CMP     a1, #IICStatus_Completed
-        LDREQ   a4, [sp, #(3*4)+(2*4)]  ; Clipped block 2 request size
+        LDREQ   a4, [sp, #(12*2)+(2*4)] ; Block 3 request size
         MOVNE   a4, #0
-        ADD     sp, sp, #24             ; Junk the iic_transfer blocks
+        ADD     sp, sp, #12*3           ; Junk the iic_transfer blocks
         STR     a1, [sp, #0]            ; Propagate return code
         LDR     a3, [sp, #8]
         STR     a4, [a3]                ; Actual transfer size
diff --git a/s/Video b/s/Video
index aca4662..4b86f0e 100644
--- a/s/Video
+++ b/s/Video
@@ -156,7 +156,6 @@ VideoDevice_Sleep
         MOV     a1, #0
         MOV     pc, lr
 
-Video_Power_VBC_Pandora
 Video_Power_VBC_DVI
         ; a1 = HAL device
         ; a2 = brightness 0-65536, which we treat as a simple on/off flag
@@ -194,6 +193,32 @@ Video_Power_VBC_TouchBook
         BLNE    GPIOx_SetOutput
         EXIT
 
+Video_Power_VBC_Pandora ROUT
+        ; a1 = HAL device
+        ; a2 = brightness 0-65536
+        Entry   "a2,v4,sb"
+        LDR     sb, VideoWorkspace
+        ; TODO - Proper brightness controls, and proper LCD power control.
+        ; To turn the power on/off properly it looks like it needs to be done over several frames, which would ideally require some changes to OMAPVideo to ensure we're called from the foreground and aren't re-entered.
+        ; For now we'll just put the LCD in/out of standby, via the SPI interface
+        TEQ     a2, #0
+        MOVEQ   a4, #&d8
+        MOVNE   a4, #&df
+        LDR     a2, L4_Core_Log
+        ADD     a2, a2, #L4_McSPI1-L4_Core
+        ADD     a2, a2, #MCSPI_STRIDE
+        LDR     v4, =(7<<2)+(1<<6)+(15<<7)+(2<<12)+(1<<16)
+        MOV     a3, #3
+        BL      td043_write
+        ; The datasheet says we should wait 9 frames before cutting the sync
+        ; signals, but OMAPVideo will cut them right away. Luckily it looks like
+        ; we can get by with waiting just one frame.
+        LDR     a2, [sp]
+        TEQ     a2, #0
+        LDREQ   a1, =17000
+        BLEQ    HAL_CounterDelay
+        EXIT
+
 Determine_PorchSync_Limits
         ; Returns:
         ; a1 = max porch value
-- 
GitLab