From f52a91548778b299bcf3e0bfb710a9c1b866363d Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 8 Mar 2022 15:40:17 +0100 Subject: [PATCH] lambdaconcept_ecpix5: Add initial Video support at 640x480 (with Terminal/Framebuffer). I2C intialization code adapted from https://github.com/ultraembedded/ecpix-5. Tested with: - python3 -m litex_boards.targets.lambdaconcept_ecpix5 --cpu-type=firev --with-video-terminal --build --load - python3 -m litex_boards.targets.lambdaconcept_ecpix5 --cpu-type=firev --with-video-framebuffer --build --load __ _ __ _ __ / / (_) /____ | |/_/ / /__/ / __/ -_)> < /____/_/\__/\__/_/|_| Build your hardware, easily! (c) Copyright 2012-2022 Enjoy-Digital (c) Copyright 2007-2015 M-Labs BIOS built on Mar 8 2022 15:34:22 BIOS CRC passed (c7fe9ecd) Migen git sha1: ac70301 LiteX git sha1: 7ebc7625 --=============== SoC ==================-- CPU: FireV-STANDARD @ 75MHz BUS: WISHBONE 32-bit @ 4GiB CSR: 32-bit data ROM: 128KiB SRAM: 8KiB L2: 8KiB SDRAM: 524288KiB 16-bit @ 300MT/s (CL-6 CWL-5) --========== Initialization ============-- Initializing SDRAM @0x40000000... Switching SDRAM to software control. Read leveling: m0, b00: |01110000| delays: 02+-01 m0, b01: |00000000| delays: - m0, b02: |00000000| delays: - m0, b03: |00000000| delays: - best: m0, b00 delays: 02+-01 m1, b00: |01110000| delays: 02+-01 m1, b01: |00000000| delays: - m1, b02: |00000000| delays: - m1, b03: |00000000| delays: - best: m1, b00 delays: 02+-01 Switching SDRAM to hardware control. Memtest at 0x40000000 (2.0MiB)... Write: 0x40000000-0x40200000 2.0MiB Read: 0x40000000-0x40200000 2.0MiB Memtest OK Memspeed at 0x40000000 (Sequential, 2.0MiB)... Write speed: 13.6MiB/s Read speed: 23.4MiB/s --============== Boot ==================-- Booting from serial... Press Q or ESC to abort boot completely. sL5DdSMmkekro Timeout No boot medium found --============= Console ================-- litex> ident Ident: LiteX SoC on ECPIX-5 2022-03-08 15:34:19 --- .../platforms/lambdaconcept_ecpix5.py | 16 ++- litex_boards/targets/lambdaconcept_ecpix5.py | 118 ++++++++++++++++-- 2 files changed, 126 insertions(+), 8 deletions(-) diff --git a/litex_boards/platforms/lambdaconcept_ecpix5.py b/litex_boards/platforms/lambdaconcept_ecpix5.py index cba2d32..4876f26 100644 --- a/litex_boards/platforms/lambdaconcept_ecpix5.py +++ b/litex_boards/platforms/lambdaconcept_ecpix5.py @@ -1,7 +1,7 @@ # # This file is part of LiteX-Boards. # -# Copyright (c) 2020 Florent Kermarrec +# Copyright (c) 2020-2022 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause from litex.build.generic_platform import * @@ -137,6 +137,20 @@ _io = [ Subsignal("data", Pins("M26 L25 L26 K25 K26 J23 P25 H25")), IOStandard("LVCMOS33") ), + + # HDMI / IT6613 + ("hdmi", 0, + Subsignal("r", Pins("AD26 AE25 AF25 AE26 E10 D11 D10 C10 D9 E8 H5 J4")), + Subsignal("g", Pins("AA23 AA22 AA24 AA25 E1 F2 F1 D17 D16 E16 J6 H6")), + Subsignal("b", Pins("AD25 AC26 AB24 AB25 B3 C3 D3 B1 C8 D2 D1 E3")), + Subsignal("de", Pins("A3")), + Subsignal("clk", Pins("C1")), + Subsignal("vsync", Pins("A4")), + Subsignal("hsync", Pins("B4")), + Subsignal("sda", Pins("E17")), + Subsignal("scl", Pins("C17")), + IOStandard("LVCMOS33") + ), ] # Connectors --------------------------------------------------------------------------------------- diff --git a/litex_boards/targets/lambdaconcept_ecpix5.py b/litex_boards/targets/lambdaconcept_ecpix5.py index cfe2fb5..c928002 100755 --- a/litex_boards/targets/lambdaconcept_ecpix5.py +++ b/litex_boards/targets/lambdaconcept_ecpix5.py @@ -3,7 +3,7 @@ # # This file is part of LiteX-Boards. # -# Copyright (c) 2020 Florent Kermarrec +# Copyright (c) 2020-2022 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause import os @@ -21,6 +21,8 @@ from litex.soc.cores.clock import * from litex.soc.integration.soc_core import * from litex.soc.integration.builder import * from litex.soc.cores.led import LedChaser +from litex.soc.cores.video import VideoDVIPHY +from litex.soc.cores.bitbang import I2CMaster from litedram.modules import MT41K256M16 from litedram.phy import ECP5DDRPHY @@ -78,8 +80,13 @@ class _CRG(Module): # BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): - def __init__(self, device="85F", sys_clk_freq=int(75e6), with_ethernet=False, - with_etherbone=False, with_led_chaser=True, **kwargs): + def __init__(self, device="85F", sys_clk_freq=int(75e6), + with_ethernet = False, + with_etherbone = False, + with_video_terminal = False, + with_video_framebuffer = False, + with_led_chaser = True, + **kwargs): platform = ecpix5.Platform(device=device, toolchain="trellis") # SoCCore ---------------------------------------------------------------------------------- @@ -114,6 +121,98 @@ class BaseSoC(SoCCore): if with_etherbone: self.add_etherbone(phy=self.ethphy) + # HDMI ------------------------------------------------------------------------------------- + if with_video_terminal or with_video_framebuffer: + # PHY + IT6613 I2C initialization. + hdmi_pads = platform.request("hdmi") + self.submodules.videophy = VideoDVIPHY(hdmi_pads, clock_domain="init") + self.submodules.videoi2c = I2CMaster(hdmi_pads) + + # I2C initialization adapted from https://github.com/ultraembedded/ecpix-5 + # Copyright (c) 2020 https://github.com/ultraembedded + # Adapted from C to Python. + REG_TX_SW_RST = 0x04 + B_ENTEST = (1<<7) + B_REF_RST = (1<<5) + B_AREF_RST = (1<<4) + B_VID_RST = (1<<3) + B_AUD_RST = (1<<2) + B_HDMI_RST = (1<<1) + B_HDCP_RST = (1<<0) + + REG_TX_AFE_DRV_CTRL = 0x61 + B_AFE_DRV_PWD = (1<<5) + B_AFE_DRV_RST = (1<<4) + B_AFE_DRV_PDRXDET = (1<<2) + B_AFE_DRV_TERMON = (1<<1) + B_AFE_DRV_ENCAL = (1<<0) + + REG_TX_AFE_XP_CTRL = 0x62 + B_AFE_XP_GAINBIT = (1<<7) + B_AFE_XP_PWDPLL = (1<<6) + B_AFE_XP_ENI = (1<<5) + B_AFE_XP_ER0 = (1<<4) + B_AFE_XP_RESETB = (1<<3) + B_AFE_XP_PWDI = (1<<2) + B_AFE_XP_DEI = (1<<1) + B_AFE_XP_DER = (1<<0) + + REG_TX_AFE_ISW_CTRL = 0x63 + B_AFE_RTERM_SEL = (1<<7) + B_AFE_IP_BYPASS = (1<<6) + M_AFE_DRV_ISW = (7<<3) + O_AFE_DRV_ISW = 3 + B_AFE_DRV_ISWK = 7 + + REG_TX_AFE_IP_CTRL = 0x64 + B_AFE_IP_GAINBIT = (1<<7) + B_AFE_IP_PWDPLL = (1<<6) + M_AFE_IP_CKSEL = (3<<4) + O_AFE_IP_CKSEL = 4 + B_AFE_IP_ER0 = (1<<3) + B_AFE_IP_RESETB = (1<<2) + B_AFE_IP_ENC = (1<<1) + B_AFE_IP_EC1 = (1<<0) + + REG_TX_HDMI_MODE = 0xC0 + B_TX_HDMI_MODE = 1 + B_TX_DVI_MODE = 0 + + REG_TX_GCP = 0xC1 + B_CLR_AVMUTE = 0 + B_SET_AVMUTE = 1 + B_TX_SETAVMUTE = (1<<0) + B_BLUE_SCR_MUTE = (1<<1) + B_NODEF_PHASE = (1<<2) + B_PHASE_RESYNC = (1<<3) + + self.videoi2c.add_init(addr=0x4c, init=[ + # Reset. + (REG_TX_SW_RST, B_REF_RST | B_VID_RST | B_AUD_RST | B_AREF_RST | B_HDCP_RST), + (REG_TX_SW_RST, 0), + + # Select DVI Mode. + (REG_TX_HDMI_MODE, B_TX_DVI_MODE), + + # Configure Clks. + (REG_TX_SW_RST, B_AUD_RST | B_AREF_RST | B_HDCP_RST), + (REG_TX_AFE_DRV_CTRL, B_AFE_DRV_RST), + (REG_TX_AFE_XP_CTRL, 0x18), + (REG_TX_AFE_ISW_CTRL, 0x10), + (REG_TX_AFE_IP_CTRL, 0x0C), + + # Enable Clks. + (REG_TX_AFE_DRV_CTRL, 0), + + # Enable Video. + (REG_TX_GCP, 0), + ]) + # Video Terminal/Framebuffer. + if with_video_terminal: + self.add_video_terminal(phy=self.videophy, timings="640x480@75Hz", clock_domain="init") + if with_video_framebuffer: + self.add_video_framebuffer(phy=self.videophy, timings="640x480@75Hz", clock_domain="init") + # Leds ------------------------------------------------------------------------------------- if with_led_chaser: leds_pads = [] @@ -138,6 +237,9 @@ def main(): ethopts = parser.add_mutually_exclusive_group() ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.") ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support.") + viopts = parser.add_mutually_exclusive_group() + viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (HDMI).") + viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (HDMI).") builder_args(parser) soc_core_args(parser) @@ -145,10 +247,12 @@ def main(): args = parser.parse_args() soc = BaseSoC( - device = args.device, - sys_clk_freq = int(float(args.sys_clk_freq)), - with_ethernet = args.with_ethernet, - with_etherbone = args.with_etherbone, + device = args.device, + sys_clk_freq = int(float(args.sys_clk_freq)), + with_ethernet = args.with_ethernet, + with_etherbone = args.with_etherbone, + with_video_terminal = args.with_video_terminal, + with_video_framebuffer = args.with_video_framebuffer, **soc_core_argdict(args) ) if args.with_sdcard: