{"id":816684,"url":"http://patchwork.ozlabs.org/api/patches/816684/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/patch/20170921062911.26724-4-anarsoul@gmail.com/","project":{"id":18,"url":"http://patchwork.ozlabs.org/api/projects/18/?format=json","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,"list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20170921062911.26724-4-anarsoul@gmail.com>","list_archive_url":null,"date":"2017-09-21T06:29:09","name":"[U-Boot,v2,3/5] video: add anx6345 DM driver","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"bb607563e63d4a3e0b6602bce86a9b85fcbe6784","submitter":{"id":6930,"url":"http://patchwork.ozlabs.org/api/people/6930/?format=json","name":"Vasily Khoruzhick","email":"anarsoul@gmail.com"},"delegate":{"id":1700,"url":"http://patchwork.ozlabs.org/api/users/1700/?format=json","username":"ag","first_name":"Anatolij","last_name":"Gustschin","email":"agust@denx.de"},"mbox":"http://patchwork.ozlabs.org/project/uboot/patch/20170921062911.26724-4-anarsoul@gmail.com/mbox/","series":[{"id":4307,"url":"http://patchwork.ozlabs.org/api/series/4307/?format=json","web_url":"http://patchwork.ozlabs.org/project/uboot/list/?series=4307","date":"2017-09-21T06:29:06","name":"sunxi: video: add DE2 LCD and ANX6345 drivers","version":2,"mbox":"http://patchwork.ozlabs.org/series/4307/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/816684/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/816684/checks/","tags":{},"related":[],"headers":{"Return-Path":"<u-boot-bounces@lists.denx.de>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"JRIMYG63\"; dkim-atps=neutral"],"Received":["from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 3xyRbX4y8Cz9t3Z\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 21 Sep 2017 16:31:52 +1000 (AEST)","by lists.denx.de (Postfix, from userid 105)\n\tid 59D40C21F4A; Thu, 21 Sep 2017 06:30:24 +0000 (UTC)","from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id A2A0BC21F38;\n\tThu, 21 Sep 2017 06:29:26 +0000 (UTC)","by lists.denx.de (Postfix, from userid 105)\n\tid 5A08FC21D75; Thu, 21 Sep 2017 06:29:21 +0000 (UTC)","from mail-pf0-f193.google.com (mail-pf0-f193.google.com\n\t[209.85.192.193])\n\tby lists.denx.de (Postfix) with ESMTPS id 8D766C21DA9\n\tfor <u-boot@lists.denx.de>; Thu, 21 Sep 2017 06:29:20 +0000 (UTC)","by mail-pf0-f193.google.com with SMTP id h4so2132663pfk.0\n\tfor <u-boot@lists.denx.de>; Wed, 20 Sep 2017 23:29:20 -0700 (PDT)","from anarsoul-thinkpad.lan (216-71-193-140.dyn.novuscom.net.\n\t[216.71.193.140]) by smtp.gmail.com with ESMTPSA id\n\tf24sm1157511pfk.137.2017.09.20.23.29.17\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tWed, 20 Sep 2017 23:29:18 -0700 (PDT)"],"X-Spam-Checker-Version":"SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de","X-Spam-Level":"","X-Spam-Status":"No, score=0.0 required=5.0 tests=FREEMAIL_FROM,\n\tRCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,\n\tT_DKIM_INVALID autolearn=unavailable\n\tautolearn_force=no version=3.4.0","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=FZVqbHK2UyCt4Bt1KAmL/6NvRUmB0Vaot1351e5Cdnc=;\n\tb=JRIMYG63HLL9t26akBTaWqj6gEwN6zRt0fD2i2rJEtM9QYlHf1gKUGkf0uZpWfkm5J\n\tHO2ZR8TTjkJWotbuQyikewWEzDfdwjvzrX6Q08CssN/Pt8x10EBJiqOPuh+Q3WnTnFy3\n\t68FkI7dP7WqBxWbOoDHk9KlxDHUGGNbjgA0mUAIu5XpoFJSMAoCM0Ftae1DZLjzp0bXR\n\t3nIgxSe4QaLanzczzhFjl86r3G9ejBaN94Bw90eCX+I9gGtLfMq9/dzmbw5FuTvy2a7f\n\t7DqCu35vYjzzJP0CjkESthsAJHdgP9LK2tM+LSZhBtVP5O/g7zLYJdBtAu+LGhZwhqBE\n\tea2w==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=FZVqbHK2UyCt4Bt1KAmL/6NvRUmB0Vaot1351e5Cdnc=;\n\tb=TQpliHKLkjHHGiYtC5bXqYltHEfomYnv1EXZX1xRfcLicZFkGuQ/LF+dgNaPf1NMpM\n\tii4OGGTElajoPVyo995qNlyDVwUcOsai+mIDdhrnl81VPwTPLr5XAieQHl1vP4gePImg\n\tAWdCS6AB5GyhjF3v6fgSDUO91z+xxY/yCrc4oBNt7FBBmHLcLzuUjRRjh3wVt3YvrMSq\n\tsEhpy7BYuyZHe7ZzIjU7WdAWY1GT87fy+dVEzO0efJuCMblfcnsFij9AYDsUz4kWs1r8\n\tiuHMvCluZ6YXxuKBqBbIK6ulbz4otRHzSswOeMkIsim5unm+1vMl2EpXrvLpNmuxc1R0\n\tvTFA==","X-Gm-Message-State":"AHPjjUgHjUTjghw90Qdvh4FYj/6QOyQ4/rInD6U4Pva4jeNF+PFtIvON\n\tL77ysIKBPLIA+cVtDKBqypk=","X-Google-Smtp-Source":"AOwi7QBEkaU2er0b92gL80L6d3XM9xMCmh+Lz0FA/ugeCCA1TOtD6IkG2ExBYmbIqqhbHsrpvUU58A==","X-Received":"by 10.99.149.28 with SMTP id p28mr4677482pgd.386.1505975359070; \n\tWed, 20 Sep 2017 23:29:19 -0700 (PDT)","From":"Vasily Khoruzhick <anarsoul@gmail.com>","To":"Jagan Teki <jagan@openedev.com>,\n\tMaxime Ripard <maxime.ripard@free-electrons.com>,\n\tAnatolij Gustschin <agust@denx.de>,\n\tJernej Skrabec <jernej.skrabec@siol.net>, icenowy@aosc.io,\n\tu-boot@lists.denx.de","Date":"Wed, 20 Sep 2017 23:29:09 -0700","Message-Id":"<20170921062911.26724-4-anarsoul@gmail.com>","X-Mailer":"git-send-email 2.14.1","In-Reply-To":"<20170921062911.26724-1-anarsoul@gmail.com>","References":"<20170921062911.26724-1-anarsoul@gmail.com>","Subject":"[U-Boot] [PATCH v2 3/5] video: add anx6345 DM driver","X-BeenThere":"u-boot@lists.denx.de","X-Mailman-Version":"2.1.18","Precedence":"list","List-Id":"U-Boot discussion <u-boot.lists.denx.de>","List-Unsubscribe":"<https://lists.denx.de/options/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=unsubscribe>","List-Archive":"<http://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\t<mailto:u-boot-request@lists.denx.de?subject=subscribe>","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"u-boot-bounces@lists.denx.de","Sender":"\"U-Boot\" <u-boot-bounces@lists.denx.de>"},"content":"This is a eDP bridge similar to ANX9804, it allows to connect eDP panels\nto the chips that can output only parallel signal\n\nSigned-off-by: Vasily Khoruzhick <anarsoul@gmail.com>\n---\nv2: - no changes\n\n drivers/video/bridge/Kconfig   |   8 +\n drivers/video/bridge/Makefile  |   1 +\n drivers/video/bridge/anx6345.c | 419 +++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 428 insertions(+)\n create mode 100644 drivers/video/bridge/anx6345.c","diff":"diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig\nindex 2a3b6c4bee..765f7380b8 100644\n--- a/drivers/video/bridge/Kconfig\n+++ b/drivers/video/bridge/Kconfig\n@@ -25,3 +25,11 @@ config VIDEO_BRIDGE_NXP_PTN3460\n \t  signalling) converter. It enables an LVDS LCD panel to be connected\n \t  to an eDP output device such as an SoC that lacks LVDS capability,\n \t  or where LVDS requires too many signals to route on the PCB.\n+\n+config VIDEO_BRIDGE_ANALOGIX_ANX6345\n+\tbool \"Support Analogix ANX6345 RGB->DP bridge\"\n+\tdepends on VIDEO_BRIDGE\n+\tselect DM_I2C\n+\thelp\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.\ndiff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile\nindex ce731fa4ca..2a746c6f8b 100644\n--- a/drivers/video/bridge/Makefile\n+++ b/drivers/video/bridge/Makefile\n@@ -7,3 +7,4 @@\n obj-$(CONFIG_VIDEO_BRIDGE) += video-bridge-uclass.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\ndiff --git a/drivers/video/bridge/anx6345.c b/drivers/video/bridge/anx6345.c\nnew file mode 100644\nindex 0000000000..6bac9a51a9\n--- /dev/null\n+++ b/drivers/video/bridge/anx6345.c\n@@ -0,0 +1,419 @@\n+/*\n+ * Copyright (C) 2017 Vasily Khoruzhick <anarsoul@gmail.com>\n+ *\n+ * SPDX-License-Identifier:\tGPL-2.0+\n+ */\n+\n+#include <common.h>\n+#include <dm.h>\n+#include <errno.h>\n+#include <i2c.h>\n+#include <edid.h>\n+#include <video_bridge.h>\n+#include <anx98xx-edp.h>\n+\n+#define DP_MAX_LINK_RATE\t\t0x001\n+#define DP_MAX_LANE_COUNT\t\t0x002\n+#define DP_MAX_LANE_COUNT_MASK\t\t0x1f\n+\n+DECLARE_GLOBAL_DATA_PTR;\n+\n+struct anx6345_priv {\n+\tu8 edid[EDID_SIZE];\n+};\n+\n+static int anx6345_write(struct udevice *dev, unsigned addr_off,\n+\t\t\t unsigned char reg_addr, unsigned char value)\n+{\n+\tuint8_t buf[2];\n+\tstruct i2c_msg msg;\n+\tint ret;\n+\n+\tmsg.addr = addr_off;\n+\tmsg.flags = 0;\n+\tbuf[0] = reg_addr;\n+\tbuf[1] = value;\n+\tmsg.buf = buf;\n+\tmsg.len = 2;\n+\tret = dm_i2c_xfer(dev, &msg, 1);\n+\tif (ret) {\n+\t\tdebug(\"%s: write failed, reg=%#x, value=%#x, ret=%d\\n\",\n+\t\t      __func__, reg_addr, value, ret);\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int anx6345_read(struct udevice *dev, unsigned addr_off,\n+\t\t\tunsigned char reg_addr, unsigned char *value)\n+{\n+\tuint8_t addr, val;\n+\tstruct i2c_msg msg[2];\n+\tint ret;\n+\n+\tmsg[0].addr = addr_off;\n+\tmsg[0].flags = 0;\n+\taddr = reg_addr;\n+\tmsg[0].buf = &addr;\n+\tmsg[0].len = 1;\n+\tmsg[1].addr = addr_off;\n+\tmsg[1].flags = I2C_M_RD;\n+\tmsg[1].buf = &val;\n+\tmsg[1].len = 1;\n+\tret = dm_i2c_xfer(dev, msg, 2);\n+\tif (ret) {\n+\t\tdebug(\"%s: read failed, reg=%.2x, value=%p, ret=%d\\n\",\n+\t\t      __func__, (int)reg_addr, value, ret);\n+\t\treturn ret;\n+\t}\n+\t*value = val;\n+\n+\treturn 0;\n+}\n+\n+static int anx6345_write_r0(struct udevice *dev, unsigned char reg_addr,\n+\t\t\t    unsigned char value)\n+{\n+\tstruct dm_i2c_chip *chip = dev_get_parent_platdata(dev);\n+\treturn anx6345_write(dev, chip->chip_addr, reg_addr, value);\n+}\n+\n+static int anx6345_read_r0(struct udevice *dev, unsigned char reg_addr,\n+\t\t\t   unsigned char *value)\n+{\n+\tstruct dm_i2c_chip *chip = dev_get_parent_platdata(dev);\n+\treturn anx6345_read(dev, chip->chip_addr, reg_addr, value);\n+}\n+\n+static int anx6345_write_r1(struct udevice *dev, unsigned char reg_addr,\n+\t\t\t    unsigned char value)\n+{\n+\tstruct dm_i2c_chip *chip = dev_get_parent_platdata(dev);\n+\treturn anx6345_write(dev, chip->chip_addr + 1, reg_addr, value);\n+}\n+\n+static int anx6345_read_r1(struct udevice *dev, unsigned char reg_addr,\n+\t\t\t   unsigned char *value)\n+{\n+\tstruct dm_i2c_chip *chip = dev_get_parent_platdata(dev);\n+\treturn anx6345_read(dev, chip->chip_addr + 1, reg_addr, value);\n+}\n+\n+static int anx6345_set_backlight(struct udevice *dev, int percent)\n+{\n+\treturn -ENOSYS;\n+}\n+\n+static int anx6345_aux_wait(struct udevice *dev)\n+{\n+\tint ret = -ETIMEDOUT;\n+\tu8 v;\n+\tint retries = 1000;\n+\tdo {\n+\t\tanx6345_read_r0(dev, ANX9804_DP_AUX_CH_CTL_2, &v);\n+\t\tif (!(v & ANX9804_AUX_EN)) {\n+\t\t\tret = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tudelay(100);\n+\t} while (retries--);\n+\n+\tif (ret) {\n+\t\tdebug(\"%s: timed out waiting for AUX_EN to clear\\n\", __func__);\n+\t\treturn ret;\n+\t}\n+\n+\tret = -ETIMEDOUT;\n+\tretries = 1000;\n+\tdo {\n+\t\tanx6345_read_r1(dev, ANX9804_DP_INT_STA, &v);\n+\t\tif (v & ANX9804_RPLY_RECEIV) {\n+\t\t\tret = 0;\n+\t\t\tbreak;\n+\t\t}\n+\t\tudelay(100);\n+\t} while (retries--);\n+\n+\tif (ret) {\n+\t\tdebug(\"%s: timed out waiting to receive reply\\n\", __func__);\n+\t\treturn ret;\n+\t}\n+\n+\t/* Clear RPLY_RECEIV bit */\n+\tanx6345_write_r1(dev, ANX9804_DP_INT_STA, v);\n+\n+\tanx6345_read_r0(dev, ANX9804_AUX_CH_STA, &v);\n+\tif ((v & ANX9804_AUX_STATUS_MASK) != 0) {\n+\t\tdebug(\"AUX status: %d\\n\", v & ANX9804_AUX_STATUS_MASK);\n+\t\tret = -EIO;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static void anx6345_aux_addr(struct udevice *dev, u32 addr)\n+{\n+\tu8 val;\n+\n+\tval = addr & 0xff;\n+\tanx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_7_0, val);\n+\tval = (addr >> 8) & 0xff;\n+\tanx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_15_8, val);\n+\tval = (addr >> 16) & 0x0f;\n+\tanx6345_write_r0(dev, ANX9804_DP_AUX_ADDR_19_16, val);\n+}\n+\n+static int anx6345_aux_transfer(struct udevice *dev, u8 req, u32 addr, u8 *buf, size_t len)\n+{\n+\tint i, ret;\n+\tu8 ctrl1 = req;\n+\tu8 ctrl2 = ANX9804_AUX_EN;\n+\n+\tif (len > 16)\n+\t\treturn -E2BIG;\n+\n+\tif (len)\n+\t\tctrl1 |= ANX9804_AUX_LENGTH(len);\n+\telse\n+\t\tctrl2 |= ANX9804_ADDR_ONLY;\n+\n+\tif (len && !(req & ANX9804_AUX_TX_COMM_READ)) {\n+\t\tfor (i = 0; i < len; i++)\n+\t\t\tanx6345_write_r0(dev, ANX9804_BUF_DATA_0 + i, buf[i]);\n+\t}\n+\n+\tanx6345_aux_addr(dev, addr);\n+\tanx6345_write_r0(dev, ANX9804_DP_AUX_CH_CTL_1, ctrl1);\n+\tanx6345_write_r0(dev, ANX9804_DP_AUX_CH_CTL_2, ctrl2);\n+\tret = anx6345_aux_wait(dev);\n+\tif (ret) {\n+\t\tdebug(\"AUX transaction timed out\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tif (len && (req & ANX9804_AUX_TX_COMM_READ)) {\n+\t\tfor (i = 0; i < len; i++)\n+\t\t\tanx6345_read_r0(dev, ANX9804_BUF_DATA_0 + i, &buf[i]);\n+\t}\n+\n+\treturn 0;\n+\n+}\n+\n+static int anx6345_read_aux_i2c(struct udevice *dev, u8 chip_addr,\n+\t\t\t        u8 offset,\n+\t\t\t\tsize_t count,\n+\t\t\t\tu8 *buf)\n+{\n+\tint i, ret;\n+\tsize_t cur_cnt;\n+\tu8 cur_offset;\n+\tfor (i = 0; i < count; i += 16) {\n+\t\tcur_cnt = (count - i) > 16 ? 16 : count - i;\n+\t\tcur_offset = offset + i;\n+\t\tret = anx6345_aux_transfer(dev, ANX9804_AUX_TX_COMM_MOT,\n+\t\t\t\t\t   chip_addr, &cur_offset, 1);\n+\t\tif (ret) {\n+\t\t\tdebug(\"%s: failed to set i2c offset: %d\\n\", __func__, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t\tret = anx6345_aux_transfer(dev, ANX9804_AUX_TX_COMM_READ,\n+\t\t\t\t\t   chip_addr, buf + i, cur_cnt);\n+\t\tif (ret) {\n+\t\t\tdebug(\"%s: failed to read from i2c device: %d\\n\", __func__, ret);\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int anx6345_read_dpcd(struct udevice *dev, u32 reg, u8 *val)\n+{\n+\tint ret;\n+\n+\tret = anx6345_aux_transfer(dev,\n+\t\t\t\t   ANX9804_AUX_TX_COMM_READ |\n+\t\t\t\t   ANX9804_AUX_TX_COMM_DP_TRANSACTION,\n+\t\t\t\t   reg, val, 1);\n+\tif (ret) {\n+\t\tdebug (\"Failed to read DPCD\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int anx6345_read_edid(struct udevice *dev, u8 *buf, int size)\n+{\n+\tstruct anx6345_priv *priv = dev_get_priv(dev);\n+\n+\tif (size > EDID_SIZE)\n+\t\tsize = EDID_SIZE;\n+\tmemcpy(buf, priv->edid, size);\n+\n+\treturn size;\n+}\n+\n+static int anx6345_attach(struct udevice *dev)\n+{\n+\t/* No-op */\n+\treturn 0;\n+}\n+\n+static int anx6345_enable(struct udevice *dev)\n+{\n+\tu8 chipid, colordepth, lanes, data_rate, c;\n+\tint ret, i, bpp;\n+\tstruct display_timing timing;\n+\tstruct anx6345_priv *priv = dev_get_priv(dev);\n+\n+\t/* Deassert reset and enable power */\n+\tret = video_bridge_set_active(dev, true);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Reset */\n+\tanx6345_write_r1(dev, ANX9804_RST_CTRL_REG, 1);\n+\tmdelay(100);\n+\tanx6345_write_r1(dev, ANX9804_RST_CTRL_REG, 0);\n+\n+\t/* Write 0 to the powerdown reg (powerup everything) */\n+\tanx6345_write_r1(dev, ANX9804_POWERD_CTRL_REG, 0);\n+\n+\tret = anx6345_read_r1(dev, ANX9804_DEV_IDH_REG, &chipid);\n+\tif (ret)\n+\t\tdebug(\"%s: read id failed: %d\\n\", __func__, ret);\n+\n+\tswitch (chipid) {\n+\tcase 0x63:\n+\t\tdebug(\"ANX63xx detected.\\n\");\n+\t\tbreak;\n+\tdefault:\n+\t\tdebug(\"Error anx6345 chipid mismatch: %.2x\\n\", (int)chipid);\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tfor (i = 0; i < 100; i++) {\n+\t\tanx6345_read_r0(dev, ANX9804_SYS_CTRL2_REG, &c);\n+\t\tanx6345_write_r0(dev, ANX9804_SYS_CTRL2_REG, c);\n+\t\tanx6345_read_r0(dev, ANX9804_SYS_CTRL2_REG, &c);\n+\t\tif ((c & ANX9804_SYS_CTRL2_CHA_STA) == 0)\n+\t\t\tbreak;\n+\n+\t\tmdelay(5);\n+\t}\n+\tif (i == 100)\n+\t\tdebug(\"Error anx6345 clock is not stable\\n\");\n+\n+\t/* Set a bunch of analog related register values */\n+\tanx6345_write_r0(dev, ANX9804_PLL_CTRL_REG, 0x00);\n+\tanx6345_write_r1(dev, ANX9804_ANALOG_DEBUG_REG1, 0x70);\n+\tanx6345_write_r0(dev, ANX9804_LINK_DEBUG_REG, 0x30);\n+\n+\t/* Force HPD */\n+\tanx6345_write_r0(dev, ANX9804_SYS_CTRL3_REG,\n+\t\t      ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL);\n+\n+\t/* Power up and configure lanes */\n+\tanx6345_write_r0(dev, ANX9804_ANALOG_POWER_DOWN_REG, 0x00);\n+\tanx6345_write_r0(dev, ANX9804_TRAINING_LANE0_SET_REG, 0x00);\n+\tanx6345_write_r0(dev, ANX9804_TRAINING_LANE1_SET_REG, 0x00);\n+\tanx6345_write_r0(dev, ANX9804_TRAINING_LANE2_SET_REG, 0x00);\n+\tanx6345_write_r0(dev, ANX9804_TRAINING_LANE3_SET_REG, 0x00);\n+\n+\t/* Reset AUX CH */\n+\tanx6345_write_r1(dev, ANX9804_RST_CTRL2_REG,\n+\t\t      ANX9804_RST_CTRL2_AUX);\n+\tanx6345_write_r1(dev, ANX9804_RST_CTRL2_REG, 0);\n+\n+\t/* Powerdown audio and some other unused bits */\n+\tanx6345_write_r1(dev, ANX9804_POWERD_CTRL_REG, ANX9804_POWERD_AUDIO);\n+\tanx6345_write_r0(dev, ANX9804_HDCP_CONTROL_0_REG, 0x00);\n+\tanx6345_write_r0(dev, 0xa7, 0x00);\n+\n+\tanx6345_read_aux_i2c(dev, 0x50, 0x0, EDID_SIZE, priv->edid);\n+\tif (edid_get_timing(priv->edid, EDID_SIZE, &timing, &bpp) != 0) {\n+\t\tdebug(\"Failed to parse EDID\\n\");\n+\t\treturn -EIO;\n+\t}\n+\tdebug(\"%s: panel found: %dx%d, bpp %d\\n\", __func__,\n+\t\ttiming.hactive.typ, timing.vactive.typ,\n+\t\tbpp);\n+\tif (bpp == 6)\n+\t\tcolordepth = 0x00; /* 6 bit */\n+\telse\n+\t\tcolordepth = 0x10; /* 8 bit */\n+\tanx6345_write_r1(dev, ANX9804_VID_CTRL2_REG, colordepth);\n+\n+\tif (anx6345_read_dpcd(dev, DP_MAX_LINK_RATE, &data_rate)) {\n+\t\tdebug(\"%s: Failed to DP_MAX_LINK_RATE\\n\", __func__);\n+\t\treturn -EIO;\n+\t}\n+\tdebug(\"%s: data_rate: %d\\n\", __func__, (int)data_rate);\n+\tif (anx6345_read_dpcd(dev, DP_MAX_LANE_COUNT, &lanes)) {\n+\t\tdebug(\"%s: Failed to read DP_MAX_LANE_COUNT\\n\", __func__);\n+\t\treturn -EIO;\n+\t}\n+\tlanes &= DP_MAX_LANE_COUNT_MASK;\n+\tdebug(\"%s: lanes: %d\\n\", __func__, (int)lanes);\n+\n+\t/* Set data-rate / lanes */\n+\tanx6345_write_r0(dev, ANX9804_LINK_BW_SET_REG, data_rate);\n+\tanx6345_write_r0(dev, ANX9804_LANE_COUNT_SET_REG, lanes);\n+\n+\t/* Link training */\n+\tanx6345_write_r0(dev, ANX9804_LINK_TRAINING_CTRL_REG,\n+\t\t      ANX9804_LINK_TRAINING_CTRL_EN);\n+\tmdelay(5);\n+\tfor (i = 0; i < 100; i++) {\n+\t\tanx6345_read_r0(dev, ANX9804_LINK_TRAINING_CTRL_REG, &c);\n+\t\tif ((chipid == 0x63) && (c & 0x80) == 0)\n+\t\t\tbreak;\n+\n+\t\tmdelay(5);\n+\t}\n+\tif(i == 100) {\n+\t\tdebug(\"Error anx6345 link training timeout\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\t/* Enable */\n+\tanx6345_write_r1(dev, ANX9804_VID_CTRL1_REG,\n+\t\t      ANX9804_VID_CTRL1_VID_EN | ANX9804_VID_CTRL1_EDGE);\n+\t/* Force stream valid */\n+\tanx6345_write_r0(dev, ANX9804_SYS_CTRL3_REG,\n+\t\t      ANX9804_SYS_CTRL3_F_HPD | ANX9804_SYS_CTRL3_HPD_CTRL |\n+\t\t      ANX9804_SYS_CTRL3_F_VALID | ANX9804_SYS_CTRL3_VALID_CTRL);\n+\n+\treturn 0;\n+}\n+\n+static int anx6345_probe(struct udevice *dev)\n+{\n+\tif (device_get_uclass_id(dev->parent) != UCLASS_I2C)\n+\t\treturn -EPROTONOSUPPORT;\n+\n+\treturn anx6345_enable(dev);\n+}\n+\n+struct video_bridge_ops anx6345_ops = {\n+\t.attach = anx6345_attach,\n+\t.set_backlight = anx6345_set_backlight,\n+\t.read_edid = anx6345_read_edid,\n+};\n+\n+static const struct udevice_id anx6345_ids[] = {\n+\t{ .compatible = \"analogix,anx6345\", },\n+\t{ }\n+};\n+\n+U_BOOT_DRIVER(analogix_anx6345) = {\n+\t.name\t= \"analogix_anx6345\",\n+\t.id\t= UCLASS_VIDEO_BRIDGE,\n+\t.of_match = anx6345_ids,\n+\t.probe\t= anx6345_probe,\n+\t.ops\t= &anx6345_ops,\n+\t.priv_auto_alloc_size = sizeof(struct anx6345_priv),\n+};\n","prefixes":["U-Boot","v2","3/5"]}