Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/808232/?format=api
{ "id": 808232, "url": "http://patchwork.ozlabs.org/api/patches/808232/?format=api", "web_url": "http://patchwork.ozlabs.org/project/devicetree-bindings/patch/1504182434-8201-2-git-send-email-m.purski@samsung.com/", "project": { "id": 37, "url": "http://patchwork.ozlabs.org/api/projects/37/?format=api", "name": "Devicetree Bindings", "link_name": "devicetree-bindings", "list_id": "devicetree.vger.kernel.org", "list_email": "devicetree@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1504182434-8201-2-git-send-email-m.purski@samsung.com>", "list_archive_url": null, "date": "2017-08-31T12:27:13", "name": "[v2,1/2] drm/bridge: add Silicon Image SiI9234 driver", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "7a903e39d5e4882870bee924acab6e7e75265ca8", "submitter": { "id": 72100, "url": "http://patchwork.ozlabs.org/api/people/72100/?format=api", "name": "Maciej Purski", "email": "m.purski@samsung.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/devicetree-bindings/patch/1504182434-8201-2-git-send-email-m.purski@samsung.com/mbox/", "series": [ { "id": 819, "url": "http://patchwork.ozlabs.org/api/series/819/?format=api", "web_url": "http://patchwork.ozlabs.org/project/devicetree-bindings/list/?series=819", "date": "2017-08-31T12:27:12", "name": "add Silicon Image SiI9234 driver", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/819/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/808232/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/808232/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<devicetree-owner@vger.kernel.org>", "X-Original-To": "incoming-dt@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming-dt@bilbo.ozlabs.org", "Authentication-Results": "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=devicetree-owner@vger.kernel.org; receiver=<UNKNOWN>)", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xjhVd5N0dz9sMN\n\tfor <incoming-dt@patchwork.ozlabs.org>;\n\tThu, 31 Aug 2017 22:28:25 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751285AbdHaM2X (ORCPT\n\t<rfc822;incoming-dt@patchwork.ozlabs.org>);\n\tThu, 31 Aug 2017 08:28:23 -0400", "from mailout2.w1.samsung.com ([210.118.77.12]:36926 \"EHLO\n\tmailout2.w1.samsung.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751775AbdHaM1t (ORCPT\n\t<rfc822; devicetree@vger.kernel.org>); Thu, 31 Aug 2017 08:27:49 -0400", "from eucas1p1.samsung.com (unknown [182.198.249.206])\n\tby mailout2.w1.samsung.com (KnoxPortal) with ESMTP id\n\t20170831122746euoutp0257932904f0c55dc84fb3abdde95128f6~f7fvtIPm-2051420514euoutp02E;\n\tThu, 31 Aug 2017 12:27:46 +0000 (GMT)", "from eusmges3.samsung.com (unknown [203.254.199.242]) by\n\teucas1p2.samsung.com (KnoxPortal) with ESMTP id\n\t20170831122746eucas1p23a3b80328729044892eb754256b27ada~f7fvBYahG2266322663eucas1p2C;\n\tThu, 31 Aug 2017 12:27:46 +0000 (GMT)", "from eucas1p2.samsung.com ( [182.198.249.207]) by\n\teusmges3.samsung.com (EUCPMTA) with SMTP id 17.61.12867.1C008A95;\n\tThu, 31 Aug 2017 13:27:45 +0100 (BST)", "from eusmgms1.samsung.com (unknown [182.198.249.179]) by\n\teucas1p2.samsung.com (KnoxPortal) with ESMTP id\n\t20170831122745eucas1p27a178da2e30023292c57653a8dc45813~f7fuR5KGQ0142701427eucas1p2_;\n\tThu, 31 Aug 2017 12:27:45 +0000 (GMT)", "from eusync4.samsung.com ( [203.254.199.214]) by\n\teusmgms1.samsung.com (EUCPMTA) with SMTP id DA.29.18832.1C008A95;\n\tThu, 31 Aug 2017 13:27:45 +0100 (BST)", "from AMDC2075.DIGITAL.local ([106.120.51.25]) by\n\teusync4.samsung.com (Oracle Communications Messaging Server\n\t7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id\n\t<0OVJ00D98ULFMQ90@eusync4.samsung.com>; \n\tThu, 31 Aug 2017 13:27:45 +0100 (BST)" ], "X-AuditID": "cbfec7f2-f793b6d000003243-c2-59a800c19450", "From": "Maciej Purski <m.purski@samsung.com>", "To": "dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,\n\tlinux-samsung-soc@vger.kernel.org", "Cc": "airlied@linux.ie, robh+dt@kernel.org, mark.rutland@arm.com,\n\tarchitt@codeaurora.org, a.hajda@samsung.com,\n\tLaurent.pinchart@ideasonboard.com, krzk@kernel.org,\n\tb.zolnierkie@samsung.com, Maciej Purski <m.purski@samsung.com>", "Subject": "[PATCH v2 1/2] drm/bridge: add Silicon Image SiI9234 driver", "Date": "Thu, 31 Aug 2017 14:27:13 +0200", "Message-id": "<1504182434-8201-2-git-send-email-m.purski@samsung.com>", "X-Mailer": "git-send-email 2.7.4", "In-reply-to": "<1504182434-8201-1-git-send-email-m.purski@samsung.com>", "X-Brightmail-Tracker": [ "H4sIAAAAAAAAA+NgFvrIIsWRmVeSWpSXmKPExsWy7djP87oHGVZEGjyaYmxxa905VovecyeZ\n\tLJo63rJabJyxntVi/hGg2JWv79kszp/fwG7ROXEJu8WM8/uYLBa8vMVisfT6RSaL1r1H2B14\n\tPNbMW8Pocbmvl8ljdsdMVo9NqzrZPLZ/e8Dqcb/7OJNH35ZVjB6fN8kFcERx2aSk5mSWpRbp\n\t2yVwZRzveMhS0NPKVLHjYRdbA+P864xdjJwcEgImEk1n9zNB2GISF+6tZ+ti5OIQEljKKDH1\n\twm9WCOczo8S8nmVsMB2zu/ZDJZYxSiy/8wTK+c8o8WDSESCHg4NNQEtiTXs8SIOIQIrEl4ur\n\tmUFqmAWeMkpsW3uCGaRGWMBFYvtOdpAaFgFViU89z8BsXgFnicWHH0KdJCdx81wnM4jNCVS+\n\t4u1ZsPMkBNaxS/RdmwO2S0JAVmLTAWaIeheJvav2skDYwhKvjm9hh7BlJDo7DkLNrJa4+HUX\n\t1DM1Eo23N0DVWEt8nrQFbA6zAJ/EpG3TmSHG80p0tAlBlHhIdC9YBrXKUWLro3lgrUIC0xkl\n\tnn7LncAos4CRYRWjSGppcW56arGxXnFibnFpXrpecn7uJkZgQjj97/inHYxfT1gdYhTgYFTi\n\t4e3gXR4pxJpYVlyZe4hRgoNZSYR33z+gEG9KYmVValF+fFFpTmrxIUZpDhYlcV7bqLZIIYH0\n\txJLU7NTUgtQimCwTB6dUA+OOD7bhxz2TzXY36roGOTMfXnDp7Srx3qY5zFEhfVH932bvzzmS\n\ty9Mh7lsp8eXE97k9ujOknt168vyb3PPVSivUH3zekf5hV33ftsliSbOVnjOeS7I3mT+r/0hM\n\tlIho+vl1GVv3K0589Mb+0GJ2FY2qr6vMZ8gGqlXdT8s6bpE/efWcLR/UvJSUWIozEg21mIuK\n\tEwFxagblBAMAAA==", "H4sIAAAAAAAAA+NgFprAIsWRmVeSWpSXmKPExsVy+t/xa7oHGVZEGjy8KWBxa905VovecyeZ\n\tLJo63rJabJyxntVi/hGg2JWv79kszp/fwG7ROXEJu8WM8/uYLBa8vMVisfT6RSaL1r1H2B14\n\tPNbMW8Pocbmvl8ljdsdMVo9NqzrZPLZ/e8Dqcb/7OJNH35ZVjB6fN8kFcES52WSkJqakFimk\n\t5iXnp2TmpdsqhYa46VooKeQl5qbaKkXo+oYEKSmUJeaUAnlGBmjAwTnAPVhJ3y7BLeN4x0OW\n\tgp5WpoodD7vYGhjnX2fsYuTkkBAwkZjdtZ8VwhaTuHBvPVsXIxeHkMASRonJJ16zQjiNTBJT\n\t9ixk6WLk4GAT0JJY0x4P0iAikCJxc3MDG4jNLPCUUWJtHy9IibCAi8T2newgYRYBVYlPPc/A\n\tbF4BZ4nFhx8yQeySk7h5rpMZxOYEKl/x9iwbSKsQUM3Ufo8JjLwLGBlWMYqklhbnpucWG+oV\n\tJ+YWl+al6yXn525iBMbGtmM/N+9gvLQx+BCjAAejEg/vgyPLIoVYE8uKK3MPMUpwMCuJ8O77\n\ttzxSiDclsbIqtSg/vqg0J7X4EKMp0E0TmaVEk/OBcZtXEm9oYmhuaWhkbGFhbmSkJM6rfrkp\n\tUkggPbEkNTs1tSC1CKaPiYNTqoFRd//SSYdeXbvCsOT4+rucDuJ6s/0DnwXbhq2Z8VfLcNHq\n\tzYLWc9lWKLx6v/PO4Yfv/jzeZ5RaKrroEK8OY5/JmR9LJkhU8WqHZTN8MneY1CawY3rKpuPV\n\tfZ5W/deOezI8D2d4Yft8Kafza4Gt+0OWNB5aO6f6XZ6bnvb2N6WrOJ5dmb37vgbnIyWW4oxE\n\tQy3mouJEAHpjJx+jAgAA" ], "X-MTR": "20000000000000000@CPGS", "X-CMS-MailID": "20170831122745eucas1p27a178da2e30023292c57653a8dc45813", "X-Msg-Generator": "CA", "X-Sender-IP": "182.198.249.179", "X-Local-Sender": "=?utf-8?q?Maciej_Purski=1BSecurity_=28TP=29=1BSamsung_Ele?=\n\t=?utf-8?q?ctronics=1BTrainee_=28=29?=", "X-Global-Sender": "=?utf-8?q?Maciej_Purski=1BSecurity_=28TP=29=1BSamsung_El?=\n\t=?utf-8?q?ectronics=1BTrainee_=28=29?=", "X-Sender-Code": "=?utf-8?q?C10=1BEHQ=1BC10CD02CD027395?=", "CMS-TYPE": "201P", "X-CMS-RootMailID": "20170831122745eucas1p27a178da2e30023292c57653a8dc45813", "X-RootMTR": "20170831122745eucas1p27a178da2e30023292c57653a8dc45813", "References": "<1504182434-8201-1-git-send-email-m.purski@samsung.com>\n\t<CGME20170831122745eucas1p27a178da2e30023292c57653a8dc45813@eucas1p2.samsung.com>", "Sender": "devicetree-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<devicetree.vger.kernel.org>", "X-Mailing-List": "devicetree@vger.kernel.org" }, "content": "SiI9234 transmitter converts eTMDS/HDMI signal to MHL 1.0.\nIt is controlled via I2C bus. Its interaction with other\ndevices in video pipeline is performed mainly on HW level.\nThe only interaction it does on device driver level is\nfiltering-out unsupported video modes, it exposes drm_bridge\ninterface to perform this operation.\n\nThis patch is based on the code refactored by Tomasz Stanislawski\n<t.stanislaws@samsung.com>, which was initially developed by:\nAdam Hampson <ahampson@sta.samsung.com>\nErik Gilling <konkers@android.com>\nShankar Bandal <shankar.b@samsung.com>\nDharam Kumar <dharam.kr@samsung.com>\n\nSigned-off-by: Maciej Purski <m.purski@samsung.com>\n---\nChanges in v2:\n- use bulk_requlators instead of single one\n- substitute some of the magic values with macros\n- improve coding style\n- improved error handling in sii9234_probe()\n---\n .../devicetree/bindings/display/bridge/sii9234.txt | 34 +\n drivers/gpu/drm/bridge/Kconfig | 8 +\n drivers/gpu/drm/bridge/Makefile | 1 +\n drivers/gpu/drm/bridge/sii9234.c | 993 +++++++++++++++++++++\n 4 files changed, 1036 insertions(+)\n create mode 100644 Documentation/devicetree/bindings/display/bridge/sii9234.txt\n create mode 100644 drivers/gpu/drm/bridge/sii9234.c", "diff": "diff --git a/Documentation/devicetree/bindings/display/bridge/sii9234.txt b/Documentation/devicetree/bindings/display/bridge/sii9234.txt\nnew file mode 100644\nindex 0000000..3ce7413\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/display/bridge/sii9234.txt\n@@ -0,0 +1,34 @@\n+Silicon Image SiI9234 HDMI/MHL bridge bindings\n+\n+Required properties:\n+\t- compatible : \"sil,sii9234\".\n+\t- reg : I2C address for TPI interface, use 0x39\n+\t- avcc33-supply : MHL/USB Switch Supply Voltage (3.3V)\n+\t- iovcc18-supply : I/O Supply Voltage (1.8V)\n+\t- avcc12-supply : TMDS Analog Supply Voltage (1.2V)\n+\t- cvcc12-supply : Digital Core Supply Voltage (1.2V)\n+\t- interrupts, interrupt-parent: interrupt specifier of INT pin\n+\t- reset-gpios: gpio specifier of RESET pin (active low)\n+\t- video interfaces: Device node can contain video interface port\n+\t\t\t node for HDMI encoder according to [1].\n+\n+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt\n+\n+Example:\n+\tsii9234@39 {\n+\t\tcompatible = \"sil,sii9234\";\n+\t\treg = <0x39>;\n+\t\tavcc33-supply = <&vcc33mhl>;\n+\t\tiovcc18-supply = <&vcc18mhl>;\n+\t\tavcc12-supply = <&vsil12>;\n+\t\tcvcc12-supply = <&vsil12>;\n+\t\treset-gpios = <&gpf3 4 GPIO_ACTIVE_LOW>;\n+\t\tinterrupt-parent = <&gpf3>;\n+\t\tinterrupts = <5 IRQ_TYPE_LEVEL_HIGH>;\n+\n+\t\tport {\n+\t\t\tmhl_to_hdmi: endpoint {\n+\t\t\t\tremote-endpoint = <&hdmi_to_mhl>;\n+\t\t\t};\n+\t\t};\n+\t};\ndiff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig\nindex adf9ae0..9dba16fd 100644\n--- a/drivers/gpu/drm/bridge/Kconfig\n+++ b/drivers/gpu/drm/bridge/Kconfig\n@@ -84,6 +84,14 @@ config DRM_SII902X\n \t---help---\n \t Silicon Image sii902x bridge chip driver.\n \n+config DRM_SII9234\n+\ttristate \"Silicon Image SII9234 HDMI/MHL bridge\"\n+\tdepends on OF\n+\t---help---\n+\t Say Y here if you want support for the MHL interface.\n+\t It is an I2C driver, that detects connection of MHL bridge\n+\t and starts encapsulation of HDMI signal.\n+\n config DRM_TOSHIBA_TC358767\n \ttristate \"Toshiba TC358767 eDP bridge\"\n \tdepends on OF\ndiff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile\nindex defcf1e..e3d5eb0 100644\n--- a/drivers/gpu/drm/bridge/Makefile\n+++ b/drivers/gpu/drm/bridge/Makefile\n@@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o\n obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o\n obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o\n obj-$(CONFIG_DRM_SII902X) += sii902x.o\n+obj-$(CONFIG_DRM_SII9234) += sii9234.o\n obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o\n obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/\n obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/\ndiff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c\nnew file mode 100644\nindex 0000000..b70d69a\n--- /dev/null\n+++ b/drivers/gpu/drm/bridge/sii9234.c\n@@ -0,0 +1,993 @@\n+/*\n+ * Copyright (C) 2017 Samsung Electronics\n+ *\n+ * Authors:\n+ * Tomasz Stanislawski <t.stanislaws@samsung.com>\n+ * Maciej Purski <m.purski@samsung.com>\n+ *\n+ * Based on sii9234 driver created by:\n+ * Adam Hampson <ahampson@sta.samsung.com>\n+ * Erik Gilling <konkers@android.com>\n+ * Shankar Bandal <shankar.b@samsung.com>\n+ * Dharam Kumar <dharam.kr@samsung.com>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation; either version 2 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program\n+ *\n+ */\n+#include <drm/bridge/mhl.h>\n+#include <drm/drm_crtc.h>\n+#include <drm/drm_edid.h>\n+\n+#include <linux/delay.h>\n+#include <linux/err.h>\n+#include <linux/gpio/consumer.h>\n+#include <linux/i2c.h>\n+#include <linux/interrupt.h>\n+#include <linux/irq.h>\n+#include <linux/kernel.h>\n+#include <linux/module.h>\n+#include <linux/mutex.h>\n+#include <linux/regulator/consumer.h>\n+#include <linux/slab.h>\n+\n+#define CBUS_DEVCAP_OFFSET\t\t0x80\n+\n+#define SII9234_MHL_VERSION\t\t0x11\n+#define SII9234_SCRATCHPAD_SIZE\t\t0x10\n+#define SII9234_INT_STAT_SIZE\t\t0x33\n+\n+#define BIT_TMDS_CCTRL_TMDS_OE\t\tBIT(4)\n+#define MHL_HPD_OUT_OVR_EN\t\tBIT(4)\n+#define MHL_HPD_OUT_OVR_VAL\t\tBIT(5)\n+#define MHL_INIT_TIMEOUT\t\t0x0C\n+\n+/* MHL Tx registers and bits */\n+#define MHL_TX_SRST 0x05\n+#define MHL_TX_SYSSTAT_REG 0x09\n+#define MHL_TX_INTR1_REG 0x71\n+#define MHL_TX_INTR4_REG 0x74\n+#define MHL_TX_INTR1_ENABLE_REG 0x75\n+#define MHL_TX_INTR4_ENABLE_REG 0x78\n+#define MHL_TX_INT_CTRL_REG 0x79\n+#define MHL_TX_TMDS_CCTRL 0x80\n+#define MHL_TX_DISC_CTRL1_REG 0x90\n+#define MHL_TX_DISC_CTRL2_REG 0x91\n+#define MHL_TX_DISC_CTRL3_REG 0x92\n+#define MHL_TX_DISC_CTRL4_REG\t\t0x93\n+#define MHL_TX_DISC_CTRL5_REG 0x94\n+#define MHL_TX_DISC_CTRL6_REG 0x95\n+#define MHL_TX_DISC_CTRL7_REG 0x96\n+#define MHL_TX_DISC_CTRL8_REG\t\t0x97\n+#define MHL_TX_STAT2_REG 0x99\n+#define MHL_TX_MHLTX_CTL1_REG 0xA0\n+#define MHL_TX_MHLTX_CTL2_REG 0xA1\n+#define MHL_TX_MHLTX_CTL4_REG 0xA3\n+#define MHL_TX_MHLTX_CTL6_REG 0xA5\n+#define MHL_TX_MHLTX_CTL7_REG 0xA6\n+\n+\n+#define RSEN_STATUS\t\t\tBIT(2)\n+#define HPD_CHANGE_INT\t\t\tBIT(6)\n+#define RSEN_CHANGE_INT\t\t\tBIT(5)\n+#define RGND_READY_INT\t\t\tBIT(6)\n+#define VBUS_LOW_INT\t\t\tBIT(5)\n+#define CBUS_LKOUT_INT\t\t\tBIT(4)\n+#define MHL_DISC_FAIL_INT\t\tBIT(3)\n+#define MHL_EST_INT\t\t\tBIT(2)\n+#define HPD_CHANGE_INT_MASK\t\tBIT(6)\n+#define RSEN_CHANGE_INT_MASK\t\tBIT(5)\n+\n+#define RGND_READY_MASK\t\t\tBIT(6)\n+#define CBUS_LKOUT_MASK\t\t\tBIT(4)\n+#define MHL_DISC_FAIL_MASK\t\tBIT(3)\n+#define MHL_EST_MASK\t\t\tBIT(2)\n+\n+#define SKIP_GND\t\t\tBIT(6)\n+\n+#define ATT_THRESH_SHIFT\t\t0x04\n+#define ATT_THRESH_MASK\t\t\t(0x03 << ATT_THRESH_SHIFT)\n+#define USB_D_OEN\t\t\tBIT(3)\n+#define DEGLITCH_TIME_MASK\t\t0x07\n+#define DEGLITCH_TIME_2MS\t\t0\n+#define DEGLITCH_TIME_4MS\t\t1\n+#define DEGLITCH_TIME_8MS\t\t2\n+#define DEGLITCH_TIME_16MS\t\t3\n+#define DEGLITCH_TIME_40MS\t\t4\n+#define DEGLITCH_TIME_50MS\t\t5\n+#define DEGLITCH_TIME_60MS\t\t6\n+#define DEGLITCH_TIME_128MS\t\t7\n+\n+#define USB_D_OVR\t\t\tBIT(7)\n+#define USB_ID_OVR\t\t\tBIT(6)\n+#define DVRFLT_SEL\t\t\tBIT(5)\n+#define BLOCK_RGND_INT\t\t\tBIT(4)\n+#define SKIP_DEG\t\t\tBIT(3)\n+#define CI2CA_POL\t\t\tBIT(2)\n+#define CI2CA_WKUP\t\t\tBIT(1)\n+#define SINGLE_ATT\t\t\tBIT(0)\n+\n+#define USB_D_ODN\t\t\tBIT(5)\n+#define VBUS_CHECK\t\t\tBIT(2)\n+#define RGND_INTP_MASK\t\t\t0x03\n+#define RGND_INTP_OPEN\t\t\t0\n+#define RGND_INTP_2K\t\t\t1\n+#define RGND_INTP_1K\t\t\t2\n+#define RGND_INTP_SHORT\t\t\t3\n+\n+/* HDMI registers */\n+#define HDMI_RX_TMDS0_CCTRL1_REG\t0x10\n+#define HDMI_RX_TMDS_CLK_EN_REG\t\t0x11\n+#define HDMI_RX_TMDS_CH_EN_REG\t\t0x12\n+#define HDMI_RX_PLL_CALREFSEL_REG\t0x17\n+#define HDMI_RX_PLL_VCOCAL_REG\t\t0x1A\n+#define HDMI_RX_EQ_DATA0_REG\t\t0x22\n+#define HDMI_RX_EQ_DATA1_REG\t\t0x23\n+#define HDMI_RX_EQ_DATA2_REG\t\t0x24\n+#define HDMI_RX_EQ_DATA3_REG\t\t0x25\n+#define HDMI_RX_EQ_DATA4_REG\t\t0x26\n+#define HDMI_RX_TMDS_ZONE_CTRL_REG\t0x4C\n+#define HDMI_RX_TMDS_MODE_CTRL_REG\t0x4D\n+\n+/* CBUS registers */\n+#define CBUS_INT_STATUS_1_REG\t\t0x08\n+#define CBUS_INTR1_ENABLE_REG\t\t0x09\n+#define CBUS_MSC_REQ_ABORT_REASON_REG\t0x0D\n+#define CBUS_INT_STATUS_2_REG\t\t0x1E\n+#define CBUS_INTR2_ENABLE_REG\t\t0x1F\n+#define CBUS_LINK_CONTROL_2_REG\t\t0x31\n+#define CBUS_MHL_STATUS_REG_0\t\t0xB0\n+#define CBUS_MHL_STATUS_REG_1\t\t0xB1\n+\n+#define BIT_CBUS_RESET\t\t\tBIT(3)\n+#define SET_HPD_DOWNSTREAM\t\tBIT(6)\n+\n+/* TPI registers */\n+#define TPI_DPD_REG\t\t\t0x3D\n+\n+/* timeouts */\n+#define T_SRC_VBUS_CBUS_TO_STABLE\t200\n+#define T_SRC_CBUS_FLOAT\t\t100\n+#define T_SRC_CBUS_DEGLITCH\t\t2\n+#define T_SRC_RXSENSE_DEGLITCH\t\t110\n+#define MHL1_MAX_CLK\t\t\t75000\n+\n+/* I2C addresses */\n+#define I2C_TPI_ADDR\t\t\t0x3D\n+#define I2C_HDMI_ADDR\t\t\t0x49\n+#define I2C_CBUS_ADDR\t\t\t0x64\n+\n+enum sii9234_state {\n+\tST_OFF,\n+\tST_D3,\n+\tST_RGND_INIT,\n+\tST_RGND_1K,\n+\tST_RSEN_HIGH,\n+\tST_MHL_ESTABLISHED,\n+\tST_FAILURE_DISCOVERY,\n+\tST_FAILURE,\n+};\n+\n+struct sii9234 {\n+\tstruct i2c_client *client[4];\n+\tstruct drm_bridge bridge;\n+\tstruct device *dev;\n+\tstruct gpio_desc *gpio_reset;\n+\tint i2c_error;\n+\tstruct regulator_bulk_data supplies[4];\n+\n+\tenum sii9234_state state;\n+\tstruct mutex lock;\n+};\n+\n+enum sii9234_client_id {\n+\tI2C_MHL,\n+\tI2C_TPI,\n+\tI2C_HDMI,\n+\tI2C_CBUS,\n+};\n+\n+static char *sii9234_client_name[] = {\n+\t[I2C_MHL] = \"MHL\",\n+\t[I2C_TPI] = \"TPI\",\n+\t[I2C_HDMI] = \"HDMI\",\n+\t[I2C_CBUS] = \"CBUS\",\n+};\n+\n+static int sii9234_writeb(struct sii9234 *ctx, int id, int offset,\n+\t\t\t int value)\n+{\n+\tint ret;\n+\tstruct i2c_client *client = ctx->client[id];\n+\n+\tif (ctx->i2c_error)\n+\t\treturn ctx->i2c_error;\n+\n+\tret = i2c_smbus_write_byte_data(client, offset, value);\n+\tif (ret < 0)\n+\t\tdev_err(ctx->dev, \"writeb: %4s[0x%02x] <- 0x%02x\\n\",\n+\t\t\tsii9234_client_name[id], offset, value);\n+\tctx->i2c_error = ret;\n+\n+\treturn ret;\n+}\n+\n+static int sii9234_writebm(struct sii9234 *ctx, int id, int offset,\n+\t\t\t int value, int mask)\n+{\n+\tint ret;\n+\tstruct i2c_client *client = ctx->client[id];\n+\n+\tif (ctx->i2c_error)\n+\t\treturn ctx->i2c_error;\n+\n+\tret = i2c_smbus_write_byte(client, offset);\n+\tif (ret < 0) {\n+\t\tdev_err(ctx->dev, \"writebm: %4s[0x%02x] <- 0x%02x\\n\",\n+\t\t\tsii9234_client_name[id], offset, value);\n+\t\tctx->i2c_error = ret;\n+\t\treturn ret;\n+\t}\n+\n+\tret = i2c_smbus_read_byte(client);\n+\tif (ret < 0) {\n+\t\tdev_err(ctx->dev, \"writebm: %4s[0x%02x] <- 0x%02x\\n\",\n+\t\t\tsii9234_client_name[id], offset, value);\n+\t\tctx->i2c_error = ret;\n+\t\treturn ret;\n+\t}\n+\n+\tvalue = (value & mask) | (ret & ~mask);\n+\n+\tret = i2c_smbus_write_byte_data(client, offset, value);\n+\tif (ret < 0) {\n+\t\tdev_err(ctx->dev, \"writebm: %4s[0x%02x] <- 0x%02x\\n\",\n+\t\t\tsii9234_client_name[id], offset, value);\n+\t\tctx->i2c_error = ret;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int sii9234_readb(struct sii9234 *ctx, int id, int offset)\n+{\n+\tint ret;\n+\tstruct i2c_client *client = ctx->client[id];\n+\n+\tif (ctx->i2c_error)\n+\t\treturn ctx->i2c_error;\n+\n+\tret = i2c_smbus_write_byte(client, offset);\n+\tif (ret < 0) {\n+\t\tdev_err(ctx->dev, \"readb: %4s[0x%02x]\\n\",\n+\t\t\tsii9234_client_name[id], offset);\n+\t\tctx->i2c_error = ret;\n+\t\treturn ret;\n+\t}\n+\n+\tret = i2c_smbus_read_byte(client);\n+\tif (ret < 0) {\n+\t\tdev_err(ctx->dev, \"readb: %4s[0x%02x]\\n\",\n+\t\t\tsii9234_client_name[id], offset);\n+\t\tctx->i2c_error = ret;\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int sii9234_clear_error(struct sii9234 *ctx)\n+{\n+\tint ret = ctx->i2c_error;\n+\n+\tctx->i2c_error = 0;\n+\n+\treturn ret;\n+}\n+\n+#define mhl_tx_writeb(sii9234, offset, value) \\\n+\tsii9234_writeb(sii9234, I2C_MHL, offset, value)\n+#define mhl_tx_writebm(sii9234, offset, value, mask) \\\n+\tsii9234_writebm(sii9234, I2C_MHL, offset, value, mask)\n+#define mhl_tx_readb(sii9234, offset) \\\n+\tsii9234_readb(sii9234, I2C_MHL, offset)\n+#define cbus_writeb(sii9234, offset, value) \\\n+\tsii9234_writeb(sii9234, I2C_CBUS, offset, value)\n+#define cbus_writebm(sii9234, offset, value, mask) \\\n+\tsii9234_writebm(sii9234, I2C_CBUS, offset, value, mask)\n+#define cbus_readb(sii9234, offset) \\\n+\tsii9234_readb(sii9234, I2C_CBUS, offset)\n+#define hdmi_writeb(sii9234, offset, value) \\\n+\tsii9234_writeb(sii9234, I2C_HDMI, offset, value)\n+#define hdmi_writebm(sii9234, offset, value, mask) \\\n+\tsii9234_writebm(sii9234, I2C_HDMI, offset, value, mask)\n+#define hdmi_readb(sii9234, offset) \\\n+\tsii9234_readb(sii9234, I2C_HDMI, offset)\n+#define tpi_writeb(sii9234, offset, value) \\\n+\tsii9234_writeb(sii9234, I2C_TPI, offset, value)\n+#define tpi_writebm(sii9234, offset, value, mask) \\\n+\tsii9234_writebm(sii9234, I2C_TPI, offset, value, mask)\n+#define tpi_readb(sii9234, offset) \\\n+\tsii9234_readb(sii9234, I2C_TPI, offset)\n+\n+static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable)\n+{\n+\tmhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0,\n+\t\t\t\t\t\tBIT_TMDS_CCTRL_TMDS_OE);\n+\tmhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0,\n+\t\t\t\tMHL_HPD_OUT_OVR_EN | MHL_HPD_OUT_OVR_VAL);\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+static int sii9234_cbus_reset(struct sii9234 *ctx)\n+{\n+\tint i;\n+\n+\tmhl_tx_writebm(ctx, MHL_TX_SRST, ~0, BIT_CBUS_RESET);\n+\tmsleep(T_SRC_CBUS_DEGLITCH);\n+\tmhl_tx_writebm(ctx, MHL_TX_SRST, 0, BIT_CBUS_RESET);\n+\n+\tfor (i = 0; i < 4; i++) {\n+\t\t/* Enable WRITE_STAT interrupt for writes to all\n+\t\t * 4 MSC Status registers.\n+\t\t */\n+\t\tcbus_writeb(ctx, 0xE0 + i, 0xF2);\n+\t\t/* Enable SET_INT interrupt for writes to all\n+\t\t * 4 MSC Interrupt registers.\n+\t\t */\n+\t\tcbus_writeb(ctx, 0xF0 + i, 0xF2);\n+\t}\n+\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+/* Require to chek mhl imformation of samsung in cbus_init_register */\n+static int sii9234_cbus_init(struct sii9234 *ctx)\n+{\n+\tcbus_writeb(ctx, 0x07, 0xF2);\n+\tcbus_writeb(ctx, 0x40, 0x03);\n+\tcbus_writeb(ctx, 0x42, 0x06);\n+\tcbus_writeb(ctx, 0x36, 0x0C);\n+\tcbus_writeb(ctx, 0x3D, 0xFD);\n+\tcbus_writeb(ctx, 0x1C, 0x01);\n+\tcbus_writeb(ctx, 0x1D, 0x0F);\n+\tcbus_writeb(ctx, 0x44, 0x02);\n+\t/* Setup our devcap */\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEV_STATE, 0x00);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_MHL_VERSION,\n+\t\t\t\t\t\t\tSII9234_MHL_VERSION);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_CAT,\n+\t\t\t\t\t\t\tMHL_DCAP_CAT_SOURCE);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_H, 0x01);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_L, 0x41);\n+\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VID_LINK_MODE,\n+\t\t\tMHL_DCAP_VID_LINK_RGB444 | MHL_DCAP_VID_LINK_YCBCR444);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VIDEO_TYPE,\n+\t\t\t\t\t\t\tMHL_DCAP_VT_GRAPHICS);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_LOG_DEV_MAP,\n+\t\t\t\t\t\t\tMHL_DCAP_LD_GUI);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_BANDWIDTH, 0x0F);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_FEATURE_FLAG,\n+\t\t MHL_DCAP_FEATURE_RCP_SUPPORT | MHL_DCAP_FEATURE_RAP_SUPPORT\n+\t\t | MHL_DCAP_FEATURE_SP_SUPPORT);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_H, 0x0);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_L, 0x0);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_SCRATCHPAD_SIZE,\n+\t\t\t\t\t\tSII9234_SCRATCHPAD_SIZE);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_INT_STAT_SIZE,\n+\t\t\t\t\t\tSII9234_INT_STAT_SIZE);\n+\tcbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_RESERVED, 0);\n+\tcbus_writebm(ctx, 0x31, 0x0C, 0x0C);\n+\tcbus_writeb(ctx, 0x30, 0x01);\n+\tcbus_writebm(ctx, 0x3C, 0x30, 0x38);\n+\tcbus_writebm(ctx, 0x22, 0x0D, 0x0F);\n+\tcbus_writebm(ctx, 0x2E, 0x15, 0x15);\n+\tcbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0);\n+\tcbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0);\n+\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+static void force_usb_id_switch_open(struct sii9234 *ctx)\n+{\n+\t/* Disable CBUS discovery */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01);\n+\t/* Force USB ID switch to open */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);\n+\t/* Force upstream HPD to 0 when not in MHL mode. */\n+\tmhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30);\n+}\n+\n+static void release_usb_id_switch_open(struct sii9234 *ctx)\n+{\n+\tmsleep(T_SRC_CBUS_FLOAT);\n+\t/* Clear USB ID switch to open */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);\n+\t/* Enable CBUS discovery */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01);\n+}\n+\n+static int sii9234_power_init(struct sii9234 *ctx)\n+{\n+\t/* Force the SiI9234 into the D0 state. */\n+\ttpi_writeb(ctx, TPI_DPD_REG, 0x3F);\n+\t/* Enable TxPLL Clock */\n+\thdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01);\n+\t/* Enable Tx Clock Path & Equalizer */\n+\thdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15);\n+\t/* Power Up TMDS */\n+\tmhl_tx_writeb(ctx, 0x08, 0x35);\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+static int sii9234_hdmi_init(struct sii9234 *ctx)\n+{\n+\thdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);\n+\thdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03);\n+\thdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20);\n+\thdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A);\n+\thdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A);\n+\thdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA);\n+\thdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA);\n+\thdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA);\n+\thdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0);\n+\thdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00);\n+\tmhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34);\n+\thdmi_writeb(ctx, 0x45, 0x44);\n+\thdmi_writeb(ctx, 0x31, 0x0A);\n+\thdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);\n+\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx)\n+{\n+\tmhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0);\n+\tmhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC);\n+\tmhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB);\n+\tmhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C);\n+\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+static int sii9234_reset(struct sii9234 *ctx)\n+{\n+\tint ret;\n+\n+\tsii9234_clear_error(ctx);\n+\n+\tret = sii9234_power_init(ctx);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\tret = sii9234_cbus_reset(ctx);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\tret = sii9234_hdmi_init(ctx);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\tret = sii9234_mhl_tx_ctl_int(ctx);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\t/* Enable HDCP Compliance safety */\n+\tmhl_tx_writeb(ctx, 0x2B, 0x01);\n+\t/* CBUS discovery cycle time for each drive and float = 150us */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06);\n+\t/* Clear bit 6 (reg_skip_rgnd) */\n+\tmhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7) /* Reserved */\n+\t\t| 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS);\n+\t/* Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel\n+\t * 1.8V CBUS VTH & GND threshold\n+\t * to meet CTS 3.3.7.2 spec\n+\t */\n+\tmhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);\n+\tcbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, MHL_INIT_TIMEOUT);\n+\tmhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0);\n+\t/* RGND & single discovery attempt (RGND blocking) */\n+\tmhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |\n+\t\t\t DVRFLT_SEL | SINGLE_ATT);\n+\t/* Use VBUS path of discovery state machine */\n+\tmhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0);\n+\t/* 0x92[3] sets the CBUS / ID switch */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);\n+\t/* To allow RGND engine to operate correctly.\n+\t * When moving the chip from D2 to D0 (power up, init regs)\n+\t * the values should be\n+\t * 94[1:0] = 01 reg_cbusmhl_pup_sel[1:0] should be set for 5k\n+\t * 93[7:6] = 10 reg_cbusdisc_pup_sel[1:0] should be\n+\t * set for 10k (default)\n+\t * 93[5:4] = 00 reg_cbusidle_pup_sel[1:0] = open (default)\n+\t */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);\n+\t/* Change from CC to 8C to match 5K\n+\t * to meet CTS 3.3.72 spec\n+\t */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);\n+\t/* Configure the interrupt as active high */\n+\tmhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06);\n+\n+\tmsleep(25);\n+\n+\t/* Release usb_id switch */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);\n+\tmhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27);\n+\n+\tret = sii9234_clear_error(ctx);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\tret = sii9234_cbus_init(ctx);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\t/* Enable Auto soft reset on SCDT = 0 */\n+\tmhl_tx_writeb(ctx, 0x05, 0x04);\n+\t/* HDMI Transcode mode enable */\n+\tmhl_tx_writeb(ctx, 0x0D, 0x1C);\n+\tmhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG,\n+\t\t\t RGND_READY_MASK | CBUS_LKOUT_MASK |\n+\t\t\t MHL_DISC_FAIL_MASK | MHL_EST_MASK);\n+\tmhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60);\n+\n+\t/* This point is very important before measure RGND impedance */\n+\tforce_usb_id_switch_open(ctx);\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0);\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03);\n+\trelease_usb_id_switch_open(ctx);\n+\n+\t/* Force upstream HPD to 0 when not in MHL mode */\n+\tmhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5);\n+\tmhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4);\n+\n+\treturn sii9234_clear_error(ctx);\n+}\n+\n+static int sii9234_goto_d3(struct sii9234 *ctx)\n+{\n+\tint ret;\n+\n+\tdev_dbg(ctx->dev, \"sii9234: detection started d3\\n\");\n+\n+\tret = sii9234_reset(ctx);\n+\tif (ret < 0)\n+\t\tgoto exit;\n+\n+\thdmi_writeb(ctx, 0x01, 0x03);\n+\ttpi_writebm(ctx, TPI_DPD_REG, 0, 1);\n+\t/* I2C above is expected to fail because power goes down */\n+\tsii9234_clear_error(ctx);\n+\n+\tctx->state = ST_D3;\n+\n+\treturn 0;\n+ exit:\n+\tdev_err(ctx->dev, \"%s failed\\n\", __func__);\n+\treturn -1;\n+}\n+\n+static int sii9234_hw_on(struct sii9234 *ctx)\n+{\n+\treturn regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);\n+}\n+\n+static void sii9234_hw_off(struct sii9234 *ctx)\n+{\n+\tgpiod_set_value(ctx->gpio_reset, 1);\n+\tusleep_range(10000, 20000);\n+\tregulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);\n+}\n+\n+static void sii9234_hw_reset(struct sii9234 *ctx)\n+{\n+\tgpiod_set_value(ctx->gpio_reset, 1);\n+\tusleep_range(10000, 20000);\n+\tgpiod_set_value(ctx->gpio_reset, 0);\n+}\n+\n+static void sii9234_cable_in(struct sii9234 *ctx)\n+{\n+\tint ret;\n+\n+\tmutex_lock(&ctx->lock);\n+\tif (ctx->state != ST_OFF)\n+\t\tgoto unlock;\n+\tret = sii9234_hw_on(ctx);\n+\tif (ret < 0)\n+\t\tgoto unlock;\n+\n+\tsii9234_hw_reset(ctx);\n+\tsii9234_goto_d3(ctx);\n+\t/* To avoid irq storm, when hw is in meta state */\n+\tenable_irq(to_i2c_client(ctx->dev)->irq);\n+\n+unlock:\n+\tmutex_unlock(&ctx->lock);\n+}\n+\n+static void sii9234_cable_out(struct sii9234 *ctx)\n+{\n+\tmutex_lock(&ctx->lock);\n+\n+\tif (ctx->state == ST_OFF)\n+\t\tgoto unlock;\n+\n+\tdisable_irq(to_i2c_client(ctx->dev)->irq);\n+\ttpi_writeb(ctx, TPI_DPD_REG, 0);\n+\t/* Turn on&off hpd festure for only QCT HDMI */\n+\tsii9234_hw_off(ctx);\n+\n+\tctx->state = ST_OFF;\n+\n+unlock:\n+\tmutex_unlock(&ctx->lock);\n+}\n+\n+static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx)\n+{\n+\tint value;\n+\n+\tif (ctx->state == ST_D3) {\n+\t\tint ret;\n+\n+\t\tdev_dbg(ctx->dev, \"RGND_READY_INT\\n\");\n+\t\tsii9234_hw_reset(ctx);\n+\n+\t\tret = sii9234_reset(ctx);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(ctx->dev, \"sii9234_reset() failed\\n\");\n+\t\t\treturn ST_FAILURE;\n+\t\t}\n+\n+\t\treturn ST_RGND_INIT;\n+\t}\n+\n+\t/* Got interrupt in inappropriate state */\n+\tif (ctx->state != ST_RGND_INIT)\n+\t\treturn ST_FAILURE;\n+\n+\tvalue = mhl_tx_readb(ctx, MHL_TX_STAT2_REG);\n+\tif (sii9234_clear_error(ctx))\n+\t\treturn ST_FAILURE;\n+\n+\tif ((value & RGND_INTP_MASK) != RGND_INTP_1K) {\n+\t\tdev_warn(ctx->dev, \"RGND is not 1k\\n\");\n+\t\treturn ST_RGND_INIT;\n+\t}\n+\tdev_dbg(ctx->dev, \"RGND 1K!!\\n\");\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);\n+\tmhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05);\n+\tif (sii9234_clear_error(ctx))\n+\t\treturn ST_FAILURE;\n+\n+\tusleep_range(T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC,\n+\t\t T_SRC_VBUS_CBUS_TO_STABLE * USEC_PER_MSEC);\n+\n+\treturn ST_RGND_1K;\n+}\n+\n+static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx)\n+{\n+\tdev_dbg(ctx->dev, \"mhl est interrupt\\n\");\n+\n+\t/* Discovery override */\n+\tmhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10);\n+\t/* Increase DDC translation layer timer (byte mode) */\n+\tcbus_writeb(ctx, 0x07, 0x32);\n+\tcbus_writebm(ctx, 0x44, ~0, 1 << 1);\n+\t/* Keep the discovery enabled. Need RGND interrupt */\n+\tmhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1);\n+\tmhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG,\n+\t RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK);\n+\n+\tif (sii9234_clear_error(ctx))\n+\t\treturn ST_FAILURE;\n+\n+\treturn ST_MHL_ESTABLISHED;\n+}\n+\n+static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx)\n+{\n+\tint value;\n+\n+\tvalue = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG);\n+\tif (sii9234_clear_error(ctx))\n+\t\treturn ST_FAILURE;\n+\n+\tif (value & SET_HPD_DOWNSTREAM) {\n+\t\t/* Downstream HPD High, Enable TMDS */\n+\t\tsii9234_tmds_control(ctx, true);\n+\t} else {\n+\t\t/* Downstream HPD Low, Disable TMDS */\n+\t\tsii9234_tmds_control(ctx, false);\n+\t}\n+\n+\treturn ctx->state;\n+}\n+\n+static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx)\n+{\n+\tint value;\n+\n+\t/* Work_around code to handle wrong interrupt */\n+\tif (ctx->state != ST_RGND_1K) {\n+\t\tdev_err(ctx->dev, \"RSEN_HIGH without RGND_1K\\n\");\n+\t\treturn ST_FAILURE;\n+\t}\n+\tvalue = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);\n+\tif (value < 0)\n+\t\treturn ST_FAILURE;\n+\n+\tif (value & RSEN_STATUS) {\n+\t\tdev_dbg(ctx->dev, \"MHL cable connected.. RSEN High\\n\");\n+\t\treturn ST_RSEN_HIGH;\n+\t}\n+\tdev_dbg(ctx->dev, \"RSEN lost\\n\");\n+\t/* Once RSEN loss is confirmed,we need to check\n+\t * based on cable status and chip power status,whether\n+\t * it is SINK Loss(HDMI cable not connected, TV Off)\n+\t * or MHL cable disconnection\n+\t * TODO: Define the below mhl_disconnection()\n+\t */\n+\tmsleep(T_SRC_RXSENSE_DEGLITCH);\n+\tvalue = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);\n+\tif (value < 0)\n+\t\treturn ST_FAILURE;\n+\tdev_dbg(ctx->dev, \"sys_stat: %x\\n\", value);\n+\n+\tif (value & RSEN_STATUS) {\n+\t\tdev_dbg(ctx->dev, \"RSEN recovery\\n\");\n+\t\treturn ST_RSEN_HIGH;\n+\t}\n+\tdev_dbg(ctx->dev, \"RSEN Really LOW\\n\");\n+\t/* To meet CTS 3.3.22.2 spec */\n+\tsii9234_tmds_control(ctx, false);\n+\tforce_usb_id_switch_open(ctx);\n+\trelease_usb_id_switch_open(ctx);\n+\n+\treturn ST_FAILURE;\n+}\n+\n+static irqreturn_t sii9234_irq_thread(int irq, void *data)\n+{\n+\tstruct sii9234 *ctx = data;\n+\tint intr1, intr4;\n+\tint intr1_en, intr4_en;\n+\tint cbus_intr1, cbus_intr2;\n+\n+\tdev_dbg(ctx->dev, \"%s\\n\", __func__);\n+\n+\tmutex_lock(&ctx->lock);\n+\n+\tintr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG);\n+\tintr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG);\n+\tintr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG);\n+\tintr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG);\n+\tcbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG);\n+\tcbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG);\n+\n+\tif (sii9234_clear_error(ctx))\n+\t\tgoto done;\n+\n+\tdev_dbg(ctx->dev, \"irq %02x/%02x %02x/%02x %02x/%02x\\n\",\n+\t\t intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2);\n+\n+\tif (intr4 & RGND_READY_INT)\n+\t\tctx->state = sii9234_rgnd_ready_irq(ctx);\n+\tif (intr1 & RSEN_CHANGE_INT)\n+\t\tctx->state = sii9234_rsen_change(ctx);\n+\tif (intr4 & MHL_EST_INT)\n+\t\tctx->state = sii9234_mhl_established(ctx);\n+\tif (intr1 & HPD_CHANGE_INT)\n+\t\tctx->state = sii9234_hpd_change(ctx);\n+\tif (intr4 & CBUS_LKOUT_INT)\n+\t\tctx->state = ST_FAILURE;\n+\tif (intr4 & MHL_DISC_FAIL_INT)\n+\t\tctx->state = ST_FAILURE_DISCOVERY;\n+\n+ done:\n+\t/* Clean interrupt status and pending flags */\n+\tmhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1);\n+\tmhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4);\n+\tcbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF);\n+\tcbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF);\n+\tcbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1);\n+\tcbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2);\n+\n+\tsii9234_clear_error(ctx);\n+\n+\tif (ctx->state == ST_FAILURE) {\n+\t\tdev_dbg(ctx->dev, \"try to reset after failure\\n\");\n+\t\tsii9234_hw_reset(ctx);\n+\t\tsii9234_goto_d3(ctx);\n+\t}\n+\n+\tif (ctx->state == ST_FAILURE_DISCOVERY) {\n+\t\tdev_err(ctx->dev, \"discovery failed, no power for MHL?\\n\");\n+\t\ttpi_writebm(ctx, TPI_DPD_REG, 0, 1);\n+\t\tctx->state = ST_D3;\n+\t}\n+\n+\tmutex_unlock(&ctx->lock);\n+\n+\treturn IRQ_HANDLED;\n+}\n+\n+\n+static int sii9234_init_resources(struct sii9234 *ctx,\n+\tstruct i2c_client *client)\n+{\n+\tstruct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);\n+\tint ret;\n+\n+\tif (!ctx->dev->of_node) {\n+\t\tdev_err(ctx->dev, \"not DT device\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tctx->gpio_reset = devm_gpiod_get(ctx->dev, \"reset\", GPIOD_OUT_LOW);\n+\tif (IS_ERR(ctx->gpio_reset)) {\n+\t\tdev_err(ctx->dev, \"failed to get reset gpio from DT\\n\");\n+\t\treturn PTR_ERR(ctx->gpio_reset);\n+\t}\n+\n+\tctx->supplies[0].supply = \"cvcc12\";\n+\tctx->supplies[1].supply = \"avcc33\";\n+\tctx->supplies[2].supply = \"iovcc18\";\n+\tctx->supplies[3].supply = \"avcc12\";\n+\tret = devm_regulator_bulk_get(ctx->dev, 4, ctx->supplies);\n+\tif (ret) {\n+\t\tdev_err(ctx->dev, \"regulator_bulk failed\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tctx->client[I2C_MHL] = client;\n+\n+\tctx->client[I2C_TPI] = i2c_new_dummy(adapter, I2C_TPI_ADDR);\n+\tif (!ctx->client[I2C_TPI]) {\n+\t\tdev_err(ctx->dev, \"failed to create TPI client\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tctx->client[I2C_HDMI] = i2c_new_dummy(adapter, I2C_HDMI_ADDR);\n+\tif (!ctx->client[I2C_HDMI]) {\n+\t\tdev_err(ctx->dev, \"failed to create HDMI RX client\\n\");\n+\t\tgoto fail_tpi;\n+\t}\n+\n+\tctx->client[I2C_CBUS] = i2c_new_dummy(adapter, I2C_CBUS_ADDR);\n+\tif (!ctx->client[I2C_CBUS]) {\n+\t\tdev_err(ctx->dev, \"failed to create CBUS client\\n\");\n+\t\tgoto fail_hdmi;\n+\t}\n+\n+\treturn 0;\n+\n+fail_hdmi:\n+\ti2c_unregister_device(ctx->client[I2C_HDMI]);\n+fail_tpi:\n+\ti2c_unregister_device(ctx->client[I2C_TPI]);\n+\n+\treturn -ENODEV;\n+}\n+\n+static void sii9234_deinit_resources(struct sii9234 *ctx)\n+{\n+\ti2c_unregister_device(ctx->client[I2C_CBUS]);\n+\ti2c_unregister_device(ctx->client[I2C_HDMI]);\n+\ti2c_unregister_device(ctx->client[I2C_TPI]);\n+}\n+\n+static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge)\n+{\n+\treturn container_of(bridge, struct sii9234, bridge);\n+}\n+\n+static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,\n+\t\t\t\t\tconst struct drm_display_mode *mode)\n+{\n+\tif (mode->clock > MHL1_MAX_CLK)\n+\t\treturn MODE_CLOCK_HIGH;\n+\n+\treturn MODE_OK;\n+}\n+\n+static const struct drm_bridge_funcs sii9234_bridge_funcs = {\n+\t.mode_valid = sii9234_mode_valid,\n+};\n+\n+static int sii9234_probe(struct i2c_client *client,\n+\t\t\t\t\t const struct i2c_device_id *id)\n+{\n+\tstruct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);\n+\tstruct sii9234 *ctx;\n+\tstruct device *dev = &client->dev;\n+\tint ret;\n+\n+\tctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);\n+\tif (!ctx)\n+\t\treturn -ENOMEM;\n+\n+\tctx->dev = dev;\n+\tmutex_init(&ctx->lock);\n+\n+\tif (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {\n+\t\tdev_err(dev, \"I2C adapter lacks SMBUS feature\\n\");\n+\t\treturn -EIO;\n+\t}\n+\n+\tif (!client->irq) {\n+\t\tdev_err(dev, \"no irq provided\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tirq_set_status_flags(client->irq, IRQ_NOAUTOEN);\n+\tret = devm_request_threaded_irq(dev, client->irq, NULL,\n+\t\t\t\t\tsii9234_irq_thread,\n+\t\t\t\t\tIRQF_TRIGGER_HIGH | IRQF_ONESHOT,\n+\t\t\t\t\t\"sii9234\", ctx);\n+\tif (ret < 0) {\n+\t\tdev_err(dev, \"failed to install IRQ handler\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tret = sii9234_init_resources(ctx, client);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\ti2c_set_clientdata(client, ctx);\n+\n+\tctx->bridge.funcs = &sii9234_bridge_funcs;\n+\tctx->bridge.of_node = dev->of_node;\n+\tdrm_bridge_add(&ctx->bridge);\n+\n+\tsii9234_cable_in(ctx);\n+\n+\treturn 0;\n+}\n+\n+static int sii9234_remove(struct i2c_client *client)\n+{\n+\tstruct sii9234 *ctx = i2c_get_clientdata(client);\n+\n+\tsii9234_cable_out(ctx);\n+\tdrm_bridge_remove(&ctx->bridge);\n+\tsii9234_deinit_resources(ctx);\n+\n+\treturn 0;\n+}\n+\n+static const struct of_device_id sii9234_dt_match[] = {\n+\t{ .compatible = \"sil,sii9234\" },\n+\t{ },\n+};\n+MODULE_DEVICE_TABLE(of, sii9234_dt_match);\n+\n+static const struct i2c_device_id sii9234_id[] = {\n+\t{ \"SII9234\", 0 },\n+\t{ },\n+};\n+MODULE_DEVICE_TABLE(i2c, sii9234_id);\n+\n+static struct i2c_driver sii9234_driver = {\n+\t.driver = {\n+\t\t.name\t= \"sii9234\",\n+\t\t.of_match_table = sii9234_dt_match,\n+\t},\n+\t.probe\t\t= sii9234_probe,\n+\t.remove\t\t= sii9234_remove,\n+\t.id_table = sii9234_id,\n+};\n+\n+module_i2c_driver(sii9234_driver);\n+MODULE_LICENSE(\"GPL\");\n", "prefixes": [ "v2", "1/2" ] }