meta-nuvoton: add program-edid recipe

Add program-edid recipe to support program default EDID data to
internal SMB module as I2C EEPROM when we use DVO.

reference Linux dts:

  &i2c11 {
    status = "okay";
    slave_eeprom:slave_eeprom@40000050 {
      compatible = "slave-24c02";
      reg = <0x40000050>;
      status = "okay";
    };
  };

Change-Id: I2d12c0abe9e4815bd95382afa874c0b740af5358
Signed-off-by: Brian Ma <chma0@nuvoton.com>
diff --git a/meta-nuvoton/recipes-nuvoton/program-edid/program-edid.bb b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid.bb
new file mode 100644
index 0000000..163a5ef
--- /dev/null
+++ b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid.bb
@@ -0,0 +1,32 @@
+SUMMARY = "Program EDID data when use DP connector"
+DESCRIPTION = "Add program EDID data support for DDC to SMB internal \
+loopback mode."
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit obmc-phosphor-systemd
+DEPENDS = "systemd python3-edid-json-tool-native"
+RDEPENDS:${PN} += "bash"
+
+SRC_URI = "file://program-edid.service \
+           file://program-edid.sh \
+           file://edid.json \
+"
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE:${PN} = "program-edid.service"
+SYSTEMD_ENVIRONMENT_FILE:${PN} +="obmc/edid/program_edid"
+FILES:${PN} += "/usr/share/edid/edid.bin"
+
+do_compile() {
+    json2edid ${WORKDIR}/edid.json ${WORKDIR}/edid.bin
+}
+
+do_install() {
+    install -d ${D}${bindir}
+    install -m 0755 ${WORKDIR}/program-edid.sh ${D}${bindir}/
+    install -d ${D}${datadir}/edid
+    install -m 0644 -D ${WORKDIR}/edid.bin \
+        ${D}${datadir}/edid/edid.bin
+}
diff --git a/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/edid.json b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/edid.json
new file mode 100644
index 0000000..6daa7c3
--- /dev/null
+++ b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/edid.json
@@ -0,0 +1,198 @@
+{
+    "Base": {
+        "Basic Display": {
+            "Aspect ratio (landscape)": null,
+            "Aspect ratio (portrait)": null,
+            "Color Bit Depth": null,
+            "Continuous frequency supported": false,
+            "DPM active-off supported": true,
+            "DPM standby supported": true,
+            "DPM suspend supported": true,
+            "Digital Video Interface Standard Support": null,
+            "Display color type": "RGB 4:4:4 + YCrCb 4:4:4",
+            "Display gamma": 2.2,
+            "Maximum dimensions (cm)": {
+                "x": 52,
+                "y": 33
+            },
+            "Preferred timing includes native timing pixel format and refresh rate": true,
+            "Video input type": "Digital",
+            "sRGB Standard is default colour space": false
+        },
+        "Chromaticity": {
+            "Blue": {
+                "x": 147,
+                "y": 77
+            },
+            "Green": {
+                "x": 302,
+                "y": 622
+            },
+            "Red": {
+                "x": 669,
+                "y": 345
+            },
+            "White": {
+                "x": 321,
+                "y": 337
+            }
+        },
+        "Descriptors": [
+            {
+                "Addressable": {
+                    "x": 1920,
+                    "y": 1200
+                },
+                "Blanking": {
+                    "x": 160,
+                    "y": 35
+                },
+                "Border": {
+                    "x": 0,
+                    "y": 0
+                },
+                "Front porch": {
+                    "x": 48,
+                    "y": 3
+                },
+                "Image size (mm)": {
+                    "x": 519,
+                    "y": 324
+                },
+                "Interlace": false,
+                "Pixel clock (MHz)": 154.0,
+                "Stereo viewing": "No stereo",
+                "Sync pulse": {
+                    "x": 32,
+                    "y": 6
+                },
+                "Sync type": {
+                    "Horizontal sync (outside of V-sync)": "Positive",
+                    "Type": "Digital Separate Sync",
+                    "Vertical sync": "Positive"
+                },
+                "Type": "Detailed Timing Descriptor"
+            },
+            {
+                "Addressable": {
+                    "x": 640,
+                    "y": 350
+                },
+                "Blanking": {
+                    "x": 160,
+                    "y": 99
+                },
+                "Border": {
+                    "x": 0,
+                    "y": 0
+                },
+                "Front porch": {
+                    "x": 16,
+                    "y": 37
+                },
+                "Image size (mm)": {
+                    "x": 376,
+                    "y": 301
+                },
+                "Interlace": false,
+                "Pixel clock (MHz)": 25.17,
+                "Stereo viewing": "No stereo",
+                "Sync pulse": {
+                    "x": 96,
+                    "y": 2
+                },
+                "Sync type": {
+                    "Horizontal sync (outside of V-sync)": "Positive",
+                    "Type": "Digital Separate Sync",
+                    "Vertical sync": "Negative"
+                },
+                "Type": "Detailed Timing Descriptor"
+            },
+            {
+                "Horizontal rate (kHz)": {
+                    "Maximum": 83,
+                    "Minimum": 30
+                },
+                "Pixel clock (MHz)": 170,
+                "Subtype": "Default GTF supported",
+                "Type": "Display Range Limits Descriptor",
+                "Vertical rate (Hz)": {
+                    "Maximum": 76,
+                    "Minimum": 56
+                }
+            },
+            {
+                "Data string": "BenQ 241W",
+                "Type": "Display Product Name"
+            }
+        ],
+        "Established Timing": {
+            "1024x768 @ 60 Hz": true,
+            "1024x768 @ 72 Hz": true,
+            "1024x768 @ 75 Hz": true,
+            "1024x768 @ 87 Hz, interlaced (1024x768i)": false,
+            "1152x870 @ 75 Hz (Apple Macintosh II)": true,
+            "1280x1024 @ 75 Hz": true,
+            "640x480 @ 60 Hz": true,
+            "640x480 @ 67 Hz": true,
+            "640x480 @ 72 Hz": true,
+            "640x480 @ 75 Hz": true,
+            "720x400 @ 70 Hz": true,
+            "720x400 @ 88 Hz": false,
+            "800x600 @ 56 Hz": false,
+            "800x600 @ 60 Hz": true,
+            "800x600 @ 72 Hz": true,
+            "800x600 @ 75 Hz": true,
+            "832x624 @ 75 Hz": true,
+            "Manufacturer specific display mode 1": false,
+            "Manufacturer specific display mode 2": false,
+            "Manufacturer specific display mode 3": false,
+            "Manufacturer specific display mode 4": false,
+            "Manufacturer specific display mode 5": false,
+            "Manufacturer specific display mode 6": false,
+            "Manufacturer specific display mode 7": false
+        },
+        "Manufacturer Info": {
+            "ID Product Code": 30427,
+            "Manufacturer ID": "BNQ",
+            "Model year": null,
+            "Serial number": 4538,
+            "Week of manufacture": 3,
+            "Year of manufacture": 2007
+        },
+        "Standard Timing": [
+            {
+                "Frequency": 75,
+                "Ratio": "4:3",
+                "X resolution": 1152
+            },
+            {
+                "Frequency": 76,
+                "Ratio": "5:4",
+                "X resolution": 1280
+            },
+            {
+                "Frequency": 60,
+                "Ratio": "5:4",
+                "X resolution": 1280
+            },
+            {
+                "Frequency": 72,
+                "Ratio": "5:4",
+                "X resolution": 1280
+            },
+            {
+                "Frequency": 60,
+                "Ratio": "4:3",
+                "X resolution": 1600
+            },
+            {
+                "Frequency": 60,
+                "Ratio": "16:10",
+                "X resolution": 1680
+            }
+        ]
+    },
+    "Extensions": [],
+    "Version": "1.3"
+}
diff --git a/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/obmc/edid/program_edid b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/obmc/edid/program_edid
new file mode 100644
index 0000000..f9d6f3b
--- /dev/null
+++ b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/obmc/edid/program_edid
@@ -0,0 +1,2 @@
+SOURCE=/usr/share/edid/edid.bin
+TARGET=/sys/bus/i2c/devices/11-1050/slave-eeprom
diff --git a/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/program-edid.service b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/program-edid.service
new file mode 100644
index 0000000..3b2dd4d
--- /dev/null
+++ b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/program-edid.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Program edid service
+
+[Service]
+Restart=no
+Type=oneshot
+ExecStart=/usr/bin/program-edid.sh ${{SOURCE}} ${{TARGET}}
+SyslogIdentifier=program-edid
+EnvironmentFile=/etc/default/obmc/edid/program_edid
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/program-edid.sh b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/program-edid.sh
new file mode 100644
index 0000000..5cef056
--- /dev/null
+++ b/meta-nuvoton/recipes-nuvoton/program-edid/program-edid/program-edid.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -e
+log_file="/var/log/program_edid.log"
+
+if [ ! -f "$1" ]; then
+    echo "$1 does not exist." >> "$log_file"
+    exit 1
+fi
+
+if [ ! -f "$2" ]; then
+    echo "$2 does not exist." >> "$log_file"
+    exit 1
+fi
+
+echo "Programmning $1 to $2" >> "$log_file"
+cat "$1" > "$2"
+
+crc_file=$(crc32 < "$1")
+fsiz=$(stat -c %s "$1")
+crc_eeprom=$(head -c "$fsiz" "$2" | crc32)
+
+if [[ "$crc_file" == "$crc_eeprom" ]]; then
+  echo "Program EDID success" >> "$log_file"
+  exit 0
+fi
+
+echo "Program EDID failed" >> "$log_file"
+exit 1
diff --git a/meta-nuvoton/recipes-nuvoton/program-edid/python3-edid-json-tool_0.9.1.bb b/meta-nuvoton/recipes-nuvoton/program-edid/python3-edid-json-tool_0.9.1.bb
new file mode 100644
index 0000000..9bca875
--- /dev/null
+++ b/meta-nuvoton/recipes-nuvoton/program-edid/python3-edid-json-tool_0.9.1.bb
@@ -0,0 +1,20 @@
+SUMMARY = "EDID to JSON tool"
+DESCRIPTION = "This is a collection of tools that helps you work with \
+EDID files, by parsing them as well as by converting between EDID \
+binaries and JSON files."
+HOMEPAGE = "https://github.com/rpavlik/edid-json-tools"
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=dc64d2d7c140d9bd69045b5abaede3a7"
+
+SRC_URI = "git://github.com/rpavlik/edid-json-tools.git;branch=main;protocol=https"
+SRCREV = "1cb9416c10c8186b572fbbc98b51b67c00ec2e70"
+
+S = "${WORKDIR}/git"
+
+inherit setuptools3
+PIP_INSTALL_PACKAGE = "edid-json-tools"
+
+RDEPENDS:${PN} += " \
+    python3-click \
+"
+BBCLASSEXTEND = "native"