Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2225164/?format=api
{ "id": 2225164, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2225164/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20260419173541.31592-2-ssrane_b23@ee.vjti.ac.in/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/1.1/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null }, "msgid": "<20260419173541.31592-2-ssrane_b23@ee.vjti.ac.in>", "date": "2026-04-19T17:35:39", "name": "[v2,1/2] video: bridge: add ITE IT66121 DPI-to-HDMI bridge driver", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "3c53e2796dc9fa56f4c0eadb197eb35fdb54336b", "submitter": { "id": 92105, "url": "http://patchwork.ozlabs.org/api/1.1/people/92105/?format=api", "name": "Shaurya Rane", "email": "ssrane_b23@ee.vjti.ac.in" }, "delegate": { "id": 1700, "url": "http://patchwork.ozlabs.org/api/1.1/users/1700/?format=api", "username": "ag", "first_name": "Anatolij", "last_name": "Gustschin", "email": "agust@denx.de" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20260419173541.31592-2-ssrane_b23@ee.vjti.ac.in/mbox/", "series": [ { "id": 500606, "url": "http://patchwork.ozlabs.org/api/1.1/series/500606/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=500606", "date": "2026-04-19T17:35:38", "name": "video: bridge: add ITE IT66121 DPI-to-HDMI bridge and enable on BeaglePlay", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/500606/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2225164/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2225164/checks/", "tags": {}, "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=vjti.ac.in header.i=@vjti.ac.in header.a=rsa-sha256\n header.s=google header.b=M2jSKKFa;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de\n (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de;\n envelope-from=u-boot-bounces@lists.denx.de; receiver=patchwork.ozlabs.org)", "phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=ee.vjti.ac.in", "phobos.denx.de;\n spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de", "phobos.denx.de;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=vjti.ac.in header.i=@vjti.ac.in header.b=\"M2jSKKFa\";\n\tdkim-atps=neutral", "phobos.denx.de;\n dmarc=none (p=none dis=none) header.from=ee.vjti.ac.in", "phobos.denx.de;\n spf=none smtp.mailfrom=ssrane_b23@ee.vjti.ac.in" ], "Received": [ "from phobos.denx.de (phobos.denx.de\n [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzlpM09FTz1yD4\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 22:55:39 +1000 (AEST)", "from h2850616.stratoserver.net (localhost [IPv6:::1])\n\tby phobos.denx.de (Postfix) with ESMTP id 07CA28439F;\n\tMon, 20 Apr 2026 14:54:41 +0200 (CEST)", "by phobos.denx.de (Postfix, from userid 109)\n id A0F2284258; Mon, 20 Apr 2026 13:11:54 +0200 (CEST)", "from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com\n [IPv6:2607:f8b0:4864:20::102d])\n (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits))\n (No client certificate requested)\n by phobos.denx.de (Postfix) with ESMTPS id F322883E16\n for <u-boot@lists.denx.de>; Mon, 20 Apr 2026 13:11:51 +0200 (CEST)", "by mail-pj1-x102d.google.com with SMTP id\n 98e67ed59e1d1-35fc258aaa4so1700406a91.2\n for <u-boot@lists.denx.de>; Mon, 20 Apr 2026 04:11:51 -0700 (PDT)", "from ranegod-HP-ENVY-x360-Convertible-13-bd0xxx.www.tendawifi.com\n ([14.139.108.62]) by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b5fab30f29sm98792685ad.68.2026.04.20.04.11.47\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Mon, 20 Apr 2026 04:11:49 -0700 (PDT)" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=-0.9 required=5.0 tests=BAYES_00, DATE_IN_PAST_12_24,\n DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED,\n SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=3.4.2", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=vjti.ac.in; s=google; t=1776683510; x=1777288310; darn=lists.denx.de;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=i9tQ5M7bQZVPhVWxFdc+UhBM2yIaWLQR+xBXil3n/Pw=;\n b=M2jSKKFa9CILpZ0wQ5g5KTRPcH1Ott0lRuW5pXIlapueC3agPmUdu2rdGLOzVCD08I\n MPv5zJOGajDPKwGVRa3Ed2Cw6DE0dId4OFKOZw9rfi2zDJT+FcrqgwuVpTNgOhBlPL4A\n xhCRtV3u9uOblHR0wD8oq3AxZJ+QcycQH378g=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776683510; x=1777288310;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=i9tQ5M7bQZVPhVWxFdc+UhBM2yIaWLQR+xBXil3n/Pw=;\n b=eJUWovLk4yYBNjZLQQzFzIVpk7JJQY4cHZuj59a+ozdmK64Xdpr7MPlE3RRsm1lHjV\n IXutkqdBLOrguL86r7rpXBxcyPg2yxixHWMwjpugIY2H8eldV5uSaYezs0GvENoKbXmJ\n 7G23Pj7sX4QQ/OHKNjhbcc1WO/irWdprBWbF/mfcct+1w9NRSN3fwTcgzwKxbTgRXQeM\n d87Ii1Ap71Z8qMmk3DWh/JohBqjkwQBWHbPM9aF5roZ8yDcl5oEZQ3O8dUEzMWYAYnyc\n H6icipdFBr4C6AfB5/sjGNLVkwI2FUo5tSNq1f1XohbQ5F/IjrgL+JPAwlaic9+kkLFx\n tZaQ==", "X-Gm-Message-State": "AOJu0Yw+yX5Fz3Pq7GqdWOcNnVDt/hz0Kz3Ki1kYo3U0D/s7K/8Hk2XS\n KfY3FI0B3sJKU2cGl2NqM8OtpMYSePkHyJXB+F6VKn4EXUSccoL/dhm9C6vkl8N/ilW1Er7qheM\n iOUap8wA=", "X-Gm-Gg": "AeBDietbYIbvw+if/ocRjgfURtffaZdM/QdE71fGaj3VUD5Moz/Q8Y9p7HykdCZuYl4\n s2zyNj2oA23sirSNNmtk7XGYb/i1SXFK4HI8DSpjOdOz74U3AS5xwjsPrx/Mp3lKEx/y1nBYxyv\n E4mB8+gtzbV+VQPiiNLOk7VLdgrCif5jb8o7spdDOBQlOMELBb+5PdPCawa3nNlQ2L2UhcmMWNb\n UF4sGvtHUf3ISaTGaGyN61FSW6PvE9ftovt2tKw3wVDujWio93mR9rz5vD9v5w7DhqG4K2eW+Nc\n KzvyhQaubDpzzfT/gQZxh+susJI5xlSTmLV6kARcSQL4h0Ms+8zIM+9rKZh9wawC/v+PMGuif80\n MxR2uhGVoZeXOofu0g6UZzTMEa6AGiX/dt4L0glJ+gCwwb0t3c0CjSwQfubfiGyNn5OqXqr49aS\n 6zhuYLFNsF76NxcPSpkSyqQTO44yZ4J6w1uXjHAGZGDfWqDB3uZQheKaUeAMNuK63EtVVOkwIPW\n m4xn2swgMu0KKb7dD/UvF05q4eeNeYy", "X-Received": "by 2002:a17:90b:5106:b0:35a:189b:43db with SMTP id\n 98e67ed59e1d1-361403d5c41mr11887522a91.4.1776683509846;\n Mon, 20 Apr 2026 04:11:49 -0700 (PDT)", "From": "Shaurya Rane <ssrane_b23@ee.vjti.ac.in>", "To": "u-boot@lists.denx.de", "Cc": "jd@denx.de, tl@denx.de, trini@konsulko.com, sjg@chromium.org,\n Shaurya Rane <ssrane_b23@ee.vjti.ac.in>", "Subject": "[PATCH v2 1/2] video: bridge: add ITE IT66121 DPI-to-HDMI bridge\n driver", "Date": "Sun, 19 Apr 2026 23:05:39 +0530", "Message-ID": "<20260419173541.31592-2-ssrane_b23@ee.vjti.ac.in>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20260419173541.31592-1-ssrane_b23@ee.vjti.ac.in>", "References": "<20260419173541.31592-1-ssrane_b23@ee.vjti.ac.in>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-Mailman-Approved-At": "Mon, 20 Apr 2026 14:54:39 +0200", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.39", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<https://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n <mailto:u-boot-request@lists.denx.de?subject=subscribe>", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>", "X-Virus-Scanned": "clamav-milter 0.103.8 at phobos.denx.de", "X-Virus-Status": "Clean" }, "content": "Add support for the ITE IT66121 DPI-to-HDMI bridge chip. The IT66121\nconverts parallel RGB/DPI video input to HDMI output. It is found on\nboards like the BeaglePlay where the TI AM625 SoC's DPI output is\nrouted to an HDMI connector through this chip.\n\nThe driver is based on the IT66121 Programmer Guide and the Linux\nkernel driver drivers/gpu/drm/bridge/ite-it66121.c.\n\nTested on BeaglePlay hardware with HDMI output via TI TIDSS.\n\nSigned-off-by: Shaurya Rane <ssrane_b23@ee.vjti.ac.in>\n\n---\nChanges in v2:\n - Use lowercase hex literals consistently.\n - Include <linux/bitops.h> explicitly for BIT().\n - Replace bare AFE mask/value magic numbers with named\n IT66121_AFE_{XP,IP,XP_EC1}_PCLK_{MASK,HIGH,LOW} defines and add a\n block comment referencing the Programmer Guide \"AFE Setting\" section.\n - Switch EDID pixel-clock extraction from hand-rolled byte 54/55\n parsing to edid_get_timing().\n - Add a comment in it66121_attach() explaining that the\n video_bridge_set_active() call is a no-op on BeaglePlay (no\n reset/enable GPIOs in DT); the chip relies on its internal POR\n plus the software reset sequence in it66121_hw_init().\n - Propagate it66121_setup_video() failure instead of swallowing it.\n---\n drivers/video/bridge/Kconfig | 10 +\n drivers/video/bridge/Makefile | 1 +\n drivers/video/bridge/it66121.c | 580 +++++++++++++++++++++++++++++++++\n 3 files changed, 591 insertions(+)\n create mode 100644 drivers/video/bridge/it66121.c", "diff": "diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig\nindex 5322a002928..175e836e2f3 100644\n--- a/drivers/video/bridge/Kconfig\n+++ b/drivers/video/bridge/Kconfig\n@@ -44,6 +44,16 @@ config VIDEO_BRIDGE_ANALOGIX_ANX6345\n \t The Analogix ANX6345 is RGB-to-DP converter. It enables an eDP LCD\n \t panel to be connected to an parallel LCD interface.\n \n+config VIDEO_BRIDGE_ITE_IT66121\n+\tbool \"Support ITE IT66121 DPI->HDMI bridge\"\n+\tdepends on VIDEO_BRIDGE\n+\tselect DM_I2C\n+\thelp\n+\t The ITE IT66121 is a DPI-to-HDMI bridge chip. It converts a parallel\n+\t RGB/DPI video input to an HDMI output. This is used on boards like\n+\t the BeaglePlay where the SoC's DPI output is connected to an HDMI\n+\t connector via this bridge chip.\n+\n config VIDEO_BRIDGE_SOLOMON_SSD2825\n \tbool \"Solomon SSD2825 bridge driver\"\n \tdepends on VIDEO_BRIDGE && PANEL && DM_GPIO\ndiff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile\nindex 520f36a7a6f..bd048b7333e 100644\n--- a/drivers/video/bridge/Makefile\n+++ b/drivers/video/bridge/Makefile\n@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_BRIDGE_PARADE_DP501) += dp501.o\n obj-$(CONFIG_VIDEO_BRIDGE_PARADE_PS862X) += ps862x.o\n obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o\n obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o\n+obj-$(CONFIG_VIDEO_BRIDGE_ITE_IT66121) += it66121.o\n obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o\n obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o\n obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += lvds-codec.o\ndiff --git a/drivers/video/bridge/it66121.c b/drivers/video/bridge/it66121.c\nnew file mode 100644\nindex 00000000000..79bef2f23e1\n--- /dev/null\n+++ b/drivers/video/bridge/it66121.c\n@@ -0,0 +1,580 @@\n+// SPDX-License-Identifier: GPL-2.0+\n+/*\n+ * Copyright (C) 2025 Shaurya Rane <ssrane_b23@ee.vjti.ac.in>\n+ */\n+\n+#include <dm.h>\n+#include <i2c.h>\n+#include <edid.h>\n+#include <log.h>\n+#include <video_bridge.h>\n+#include <linux/bitops.h>\n+#include <linux/delay.h>\n+\n+#define IT66121_VENDOR_ID0\t\t0x00\n+#define IT66121_VENDOR_ID1\t\t0x01\n+#define IT66121_DEVICE_ID0\t\t0x02\n+#define IT66121_DEVICE_ID1\t\t0x03\n+\n+#define IT66121_VENDOR_ID0_VAL\t\t0x54\n+#define IT66121_VENDOR_ID1_VAL\t\t0x49\n+#define IT66121_DEVICE_ID0_VAL\t\t0x12\n+#define IT66121_DEVICE_ID1_MASK\t\t0x0f\n+#define IT66121_DEVICE_ID1_VAL\t\t0x06\n+\n+#define IT66121_SW_RST\t\t\t0x04\n+#define IT66121_SW_RST_REF\t\tBIT(5)\n+#define IT66121_SW_RST_AREF\t\tBIT(4)\n+#define IT66121_SW_RST_VID\t\tBIT(3)\n+#define IT66121_SW_RST_AUD\t\tBIT(2)\n+#define IT66121_SW_RST_HDCP\t\tBIT(0)\n+\n+#define IT66121_CLK_BANK_REG\t\t0x0f\n+#define IT66121_CLK_BANK_PWROFF_RCLK\tBIT(6)\n+#define IT66121_CLK_BANK_PWROFF_TXCLK\tBIT(4)\n+#define IT66121_CLK_BANK_SEL\t\t0x03\n+\n+#define IT66121_SYS_STATUS\t\t0x0e\n+#define IT66121_SYS_STATUS_HPD\t\tBIT(6)\n+\n+#define IT66121_INT_MASK1\t\t0x09\n+#define IT66121_INT_MASK2\t\t0x0a\n+#define IT66121_INT_MASK3\t\t0x0b\n+\n+#define IT66121_PCLK_CNT_REG\t\t0x05\n+\n+#define IT66121_DDC_MASTER_SEL\t\t0x10\n+#define IT66121_DDC_HEADER\t\t0x11\n+#define IT66121_DDC_REQOFF\t\t0x12\n+#define IT66121_DDC_REQCOUNT\t\t0x13\n+#define IT66121_DDC_EDIDSEG\t\t0x14\n+#define IT66121_DDC_CMD\t\t\t0x15\n+#define IT66121_DDC_STATUS\t\t0x16\n+#define IT66121_DDC_READFIFO\t\t0x17\n+\n+#define IT66121_DDC_STATUS_DONE\t\tBIT(7)\n+#define IT66121_DDC_STATUS_ERROR_MASK\t(BIT(5) | BIT(4) | BIT(3))\n+\n+#define IT66121_DDC_CMD_EDID_RD\t\t0x03\n+#define IT66121_DDC_CMD_FIFO_CLR\t0x09\n+#define IT66121_DDC_CMD_ABORT\t\t0x0f\n+\n+#define IT66121_INPUT_MODE\t\t0x70\n+#define IT66121_INPUT_MODE_RGB\t\t0x00\n+\n+#define IT66121_INPUT_CSC\t\t0x72\n+#define IT66121_INPUT_CSC_NO_CONV\t0x00\n+\n+#define IT66121_AFE_DRV_REG\t\t0x61\n+#define IT66121_AFE_DRV_RST\t\tBIT(4)\n+#define IT66121_AFE_XP_REG\t\t0x62\n+#define IT66121_AFE_IP_REG\t\t0x64\n+#define IT66121_AFE_XP_EC1\t\t0x68\n+\n+/*\n+ * IT66121 AFE (Analog Front End) PLL settings depend on the pixel\n+ * clock. The values below program the XP/IP/EC1 registers for pclks\n+ * above and up to 80 MHz, as described in the IT66121 Programmer\n+ * Guide, \"AFE Setting\" section.\n+ */\n+#define IT66121_AFE_XP_PCLK_MASK\t0x90\n+#define IT66121_AFE_XP_PCLK_HIGH\t0x80\t/* pclk > 80 MHz */\n+#define IT66121_AFE_XP_PCLK_LOW\t\t0x10\t/* pclk <= 80 MHz */\n+\n+#define IT66121_AFE_IP_PCLK_MASK\t0x89\n+#define IT66121_AFE_IP_PCLK_HIGH\t0x80\n+#define IT66121_AFE_IP_PCLK_LOW\t\t0x09\n+\n+#define IT66121_AFE_XP_EC1_PCLK_MASK\t0x10\n+#define IT66121_AFE_XP_EC1_PCLK_HIGH\t0x00\n+#define IT66121_AFE_XP_EC1_PCLK_LOW\t0x10\n+\n+#define IT66121_AFE_PCLK_HIGH_THRESHOLD\t80000\t/* kHz */\n+\n+#define IT66121_HDMI_MODE\t\t0xc0\n+#define IT66121_HDMI_MODE_HDMI\t\tBIT(0)\n+\n+#define IT66121_AV_MUTE\t\t\t0xc1\n+#define IT66121_AV_MUTE_ON\t\tBIT(0)\n+\n+#define IT66121_PKT_GEN_CTRL\t\t0xc6\n+#define IT66121_PKT_GEN_CTRL_RPT\tBIT(1)\n+#define IT66121_PKT_GEN_CTRL_EN\t\tBIT(0)\n+\n+#define IT66121_DDC_FIFO_SIZE\t\t32\n+#define IT66121_EDID_SLAVE_ADDR\t\t0xa0\n+#define IT66121_EDID_BUF_SIZE\t\tEDID_EXT_SIZE\n+\n+struct it66121_priv {\n+\tu8 edid[IT66121_EDID_BUF_SIZE];\n+\tint edid_len;\n+};\n+\n+static int it66121_reg_read(struct udevice *dev, u8 reg, u8 *val)\n+{\n+\treturn dm_i2c_read(dev, reg, val, 1);\n+}\n+\n+static int it66121_reg_write(struct udevice *dev, u8 reg, u8 val)\n+{\n+\treturn dm_i2c_write(dev, reg, &val, 1);\n+}\n+\n+static int it66121_reg_set(struct udevice *dev, u8 reg, u8 mask, u8 val)\n+{\n+\tu8 orig;\n+\tint ret;\n+\n+\tret = it66121_reg_read(dev, reg, &orig);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\torig = (orig & ~mask) | (val & mask);\n+\n+\treturn it66121_reg_write(dev, reg, orig);\n+}\n+\n+static int it66121_identify(struct udevice *dev)\n+{\n+\tu8 v0, v1, d0, d1;\n+\tint ret;\n+\n+\tret = it66121_reg_read(dev, IT66121_VENDOR_ID0, &v0);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = it66121_reg_read(dev, IT66121_VENDOR_ID1, &v1);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = it66121_reg_read(dev, IT66121_DEVICE_ID0, &d0);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = it66121_reg_read(dev, IT66121_DEVICE_ID1, &d1);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (v0 != IT66121_VENDOR_ID0_VAL || v1 != IT66121_VENDOR_ID1_VAL ||\n+\t d0 != IT66121_DEVICE_ID0_VAL ||\n+\t (d1 & IT66121_DEVICE_ID1_MASK) != IT66121_DEVICE_ID1_VAL) {\n+\t\tdebug(\"IT66121: chip not found (vendor=%02x%02x dev=%02x%02x)\\n\",\n+\t\t v1, v0, d1, d0);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tdebug(\"IT66121: found chip (vendor=%02x%02x dev=%02x%02x)\\n\",\n+\t v1, v0, d1, d0);\n+\treturn 0;\n+}\n+\n+static int it66121_hw_init(struct udevice *dev)\n+{\n+\tint ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_CLK_BANK_REG,\n+\t\t\t IT66121_CLK_BANK_PWROFF_RCLK, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_CLK_BANK_REG,\n+\t\t\t IT66121_CLK_BANK_SEL, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_PCLK_CNT_REG, BIT(0), 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AFE_DRV_REG, BIT(5), 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AFE_XP_REG, BIT(6) | BIT(2), 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AFE_IP_REG, BIT(6), 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AFE_DRV_REG, BIT(4), 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AFE_XP_REG, BIT(3), BIT(3));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AFE_IP_REG, BIT(2), BIT(2));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Keep AREF/VID/AUD/HDCP in reset, leave REF clock running. */\n+\tret = it66121_reg_write(dev, IT66121_SW_RST,\n+\t\t\t\tIT66121_SW_RST_AREF | IT66121_SW_RST_VID |\n+\t\t\t\tIT66121_SW_RST_AUD | IT66121_SW_RST_HDCP);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmdelay(5);\n+\n+\tret = it66121_reg_write(dev, IT66121_HDMI_MODE, 0x00);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = it66121_reg_write(dev, IT66121_AV_MUTE, 0x00);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_INT_MASK1, 0xff);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = it66121_reg_write(dev, IT66121_INT_MASK2, 0xff);\n+\tif (ret)\n+\t\treturn ret;\n+\tret = it66121_reg_write(dev, IT66121_INT_MASK3, 0xff);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+static int it66121_ddc_wait(struct udevice *dev)\n+{\n+\tu8 status;\n+\tint i, ret;\n+\n+\tfor (i = 0; i < 200; i++) {\n+\t\tret = it66121_reg_read(dev, IT66121_DDC_STATUS, &status);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tif (status & IT66121_DDC_STATUS_DONE)\n+\t\t\treturn 0;\n+\n+\t\tif (status & IT66121_DDC_STATUS_ERROR_MASK) {\n+\t\t\tdebug(\"IT66121: DDC error status=0x%02x\\n\", status);\n+\t\t\treturn -EIO;\n+\t\t}\n+\n+\t\tmdelay(2);\n+\t}\n+\n+\tdebug(\"IT66121: DDC timeout\\n\");\n+\treturn -ETIMEDOUT;\n+}\n+\n+static int it66121_ddc_fifo_clear(struct udevice *dev)\n+{\n+\tint ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_DDC_CMD,\n+\t\t\t\tIT66121_DDC_CMD_FIFO_CLR);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn it66121_ddc_wait(dev);\n+}\n+\n+static int it66121_read_edid_block(struct udevice *dev, u8 *buf,\n+\t\t\t\t int offset, int segment, int len)\n+{\n+\tint ret, i, bytes_read = 0;\n+\n+\twhile (bytes_read < len) {\n+\t\tint chunk = len - bytes_read;\n+\n+\t\tif (chunk > IT66121_DDC_FIFO_SIZE)\n+\t\t\tchunk = IT66121_DDC_FIFO_SIZE;\n+\n+\t\tret = it66121_reg_write(dev, IT66121_DDC_MASTER_SEL, 0x01);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_ddc_fifo_clear(dev);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_reg_write(dev, IT66121_DDC_HEADER,\n+\t\t\t\t\tIT66121_EDID_SLAVE_ADDR);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_reg_write(dev, IT66121_DDC_REQOFF,\n+\t\t\t\t\t(offset + bytes_read) & 0xFF);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_reg_write(dev, IT66121_DDC_REQCOUNT, chunk);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_reg_write(dev, IT66121_DDC_EDIDSEG, segment);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_reg_write(dev, IT66121_DDC_CMD,\n+\t\t\t\t\tIT66121_DDC_CMD_EDID_RD);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = it66121_ddc_wait(dev);\n+\t\tif (ret) {\n+\t\t\tdebug(\"IT66121: EDID read failed at offset %d\\n\",\n+\t\t\t offset + bytes_read);\n+\t\t\tit66121_reg_write(dev, IT66121_DDC_CMD,\n+\t\t\t\t\t IT66121_DDC_CMD_ABORT);\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tfor (i = 0; i < chunk; i++) {\n+\t\t\tret = it66121_reg_read(dev, IT66121_DDC_READFIFO,\n+\t\t\t\t\t &buf[bytes_read + i]);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\n+\t\tbytes_read += chunk;\n+\t}\n+\n+\treturn bytes_read;\n+}\n+\n+static int it66121_setup_afe(struct udevice *dev, unsigned long pclk_khz)\n+{\n+\tint ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_AFE_DRV_REG, IT66121_AFE_DRV_RST);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (pclk_khz > IT66121_AFE_PCLK_HIGH_THRESHOLD) {\n+\t\tret = it66121_reg_set(dev, IT66121_AFE_XP_REG,\n+\t\t\t\t IT66121_AFE_XP_PCLK_MASK,\n+\t\t\t\t IT66121_AFE_XP_PCLK_HIGH);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t\tret = it66121_reg_set(dev, IT66121_AFE_IP_REG,\n+\t\t\t\t IT66121_AFE_IP_PCLK_MASK,\n+\t\t\t\t IT66121_AFE_IP_PCLK_HIGH);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t\tret = it66121_reg_set(dev, IT66121_AFE_XP_EC1,\n+\t\t\t\t IT66121_AFE_XP_EC1_PCLK_MASK,\n+\t\t\t\t IT66121_AFE_XP_EC1_PCLK_HIGH);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t} else {\n+\t\tret = it66121_reg_set(dev, IT66121_AFE_XP_REG,\n+\t\t\t\t IT66121_AFE_XP_PCLK_MASK,\n+\t\t\t\t IT66121_AFE_XP_PCLK_LOW);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t\tret = it66121_reg_set(dev, IT66121_AFE_IP_REG,\n+\t\t\t\t IT66121_AFE_IP_PCLK_MASK,\n+\t\t\t\t IT66121_AFE_IP_PCLK_LOW);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t\tret = it66121_reg_set(dev, IT66121_AFE_XP_EC1,\n+\t\t\t\t IT66121_AFE_XP_EC1_PCLK_MASK,\n+\t\t\t\t IT66121_AFE_XP_EC1_PCLK_LOW);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tret = it66121_reg_set(dev, IT66121_SW_RST,\n+\t\t\t IT66121_SW_RST_REF | IT66121_SW_RST_VID, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_AFE_DRV_REG, 0x00);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+/* Basic HDMI RGB output; AVI InfoFrame programming is not implemented. */\n+static int it66121_setup_video(struct udevice *dev, unsigned long pclk_khz)\n+{\n+\tint ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AV_MUTE,\n+\t\t\t IT66121_AV_MUTE_ON, IT66121_AV_MUTE_ON);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_HDMI_MODE,\n+\t\t\t\tIT66121_HDMI_MODE_HDMI);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_CLK_BANK_REG,\n+\t\t\t IT66121_CLK_BANK_PWROFF_TXCLK,\n+\t\t\t IT66121_CLK_BANK_PWROFF_TXCLK);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_INPUT_MODE,\n+\t\t\t\tIT66121_INPUT_MODE_RGB);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_INPUT_CSC,\n+\t\t\t\tIT66121_INPUT_CSC_NO_CONV);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_setup_afe(dev, pclk_khz);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_CLK_BANK_REG,\n+\t\t\t IT66121_CLK_BANK_PWROFF_TXCLK, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_write(dev, IT66121_PKT_GEN_CTRL,\n+\t\t\t\tIT66121_PKT_GEN_CTRL_RPT |\n+\t\t\t\tIT66121_PKT_GEN_CTRL_EN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_reg_set(dev, IT66121_AV_MUTE, IT66121_AV_MUTE_ON, 0);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn 0;\n+}\n+\n+static int it66121_attach(struct udevice *dev)\n+{\n+\tstruct it66121_priv *priv = dev_get_priv(dev);\n+\tstruct display_timing timing;\n+\tunsigned long pclk_khz;\n+\tint bpp;\n+\tu8 status;\n+\tint ret;\n+\n+\t/*\n+\t * Toggle reset-gpios / enable-gpios if present in DT. With no such\n+\t * GPIOs configured (as on BeaglePlay) this is a no-op and we rely\n+\t * on the chip's internal power-on reset plus the software reset\n+\t * sequence performed in it66121_hw_init().\n+\t */\n+\tret = video_bridge_set_active(dev, true);\n+\tif (ret) {\n+\t\tdebug(\"IT66121: set_active failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tmdelay(50);\n+\n+\tret = it66121_identify(dev);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = it66121_hw_init(dev);\n+\tif (ret) {\n+\t\tdebug(\"IT66121: hw_init failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = it66121_reg_read(dev, IT66121_SYS_STATUS, &status);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (!(status & IT66121_SYS_STATUS_HPD)) {\n+\t\tdebug(\"IT66121: no HPD, skipping EDID read\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tret = it66121_read_edid_block(dev, priv->edid, 0, 0, 128);\n+\tif (ret < 0) {\n+\t\tdebug(\"IT66121: EDID block 0 read failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tpriv->edid_len = 128;\n+\n+\tif (priv->edid[0x7e] > 0) {\n+\t\tret = it66121_read_edid_block(dev, priv->edid + 128,\n+\t\t\t\t\t 128, 0, 128);\n+\t\tif (ret < 0)\n+\t\t\tdebug(\"IT66121: EDID block 1 read failed: %d\\n\", ret);\n+\t\telse\n+\t\t\tpriv->edid_len = 256;\n+\t}\n+\n+\tret = edid_get_timing(priv->edid, priv->edid_len, &timing, &bpp);\n+\tif (ret) {\n+\t\tdebug(\"IT66121: edid_get_timing failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\tpclk_khz = timing.pixelclock.typ / 1000;\n+\tdebug(\"IT66121: configuring video for %lu kHz pclk\\n\", pclk_khz);\n+\n+\tret = it66121_setup_video(dev, pclk_khz);\n+\tif (ret) {\n+\t\tdebug(\"IT66121: setup_video failed: %d\\n\", ret);\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int it66121_check_attached(struct udevice *dev)\n+{\n+\tu8 status;\n+\tint ret;\n+\n+\tret = it66121_reg_read(dev, IT66121_SYS_STATUS, &status);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (status & IT66121_SYS_STATUS_HPD)\n+\t\treturn 0;\n+\n+\treturn -ENOTCONN;\n+}\n+\n+static int it66121_read_edid(struct udevice *dev, u8 *buf, int buf_size)\n+{\n+\tstruct it66121_priv *priv = dev_get_priv(dev);\n+\tint size;\n+\n+\tif (!priv->edid_len)\n+\t\treturn -ENODATA;\n+\n+\tsize = min_t(int, buf_size, priv->edid_len);\n+\tmemcpy(buf, priv->edid, size);\n+\n+\treturn size;\n+}\n+\n+static int it66121_probe(struct udevice *dev)\n+{\n+\tif (device_get_uclass_id(dev->parent) != UCLASS_I2C)\n+\t\treturn -EPROTONOSUPPORT;\n+\n+\tdebug(\"IT66121: probed on I2C bus\\n\");\n+\treturn 0;\n+}\n+\n+static const struct video_bridge_ops it66121_ops = {\n+\t.attach\t\t= it66121_attach,\n+\t.check_attached\t= it66121_check_attached,\n+\t.read_edid\t= it66121_read_edid,\n+};\n+\n+static const struct udevice_id it66121_ids[] = {\n+\t{ .compatible = \"ite,it66121\" },\n+\t{ }\n+};\n+\n+U_BOOT_DRIVER(ite_it66121) = {\n+\t.name\t\t= \"ite_it66121\",\n+\t.id\t\t= UCLASS_VIDEO_BRIDGE,\n+\t.of_match\t= it66121_ids,\n+\t.probe\t\t= it66121_probe,\n+\t.ops\t\t= &it66121_ops,\n+\t.priv_auto\t= sizeof(struct it66121_priv),\n+};\n", "prefixes": [ "v2", "1/2" ] }