linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [RFC v2 0/8] Acer Chromebook R13 support
@ 2017-10-16 15:31 Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 1/8] drm/bridge: GPIO-controlled display multiplexer driver Ulrich Hecht
                   ` (9 more replies)
  0 siblings, 10 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

This is a new revision of the Acer Chromebook R13 support series. It does
not offer anything new in terms of functionality, but eliminates three out
of four ugly hacks and adds a few minor cleanups; see below for details.
Thanks to Robin Murphy and CK Hu for their comments and suggestions!

I'm still looking for advice on how to implement the dual-role mmsys device
correctly; see "hack: mediatek: get mmsys to register as both DRM and clock
device" for details on this.

Like the previous revision, you can find this series at
https://github.com/uli/kernel/tree/elm-working, which also contains a config
file and several ancillary bits that are required to build a kernel
partition for the Chromebook. Instructions on how to do so (and various
other things that have to be done to get it running on your device) are
available at
https://www.elinux.org/User:Uli/Acer_Chromebook_R13_GPU_test_system (These
instructions have been written for the vendor kernel, but apply to mainline
as well, except that you won't need any extra patches.)

CU
Uli

Changes since RFC v1:
- cmdq: remove obsolete driver; not currently used anyway
- dt: remove CD GPIO from mmc1, does not seem to be correct
- mmc: remove mtk-sd.c revert hack (works fine without the CD pin)
- dsi: fix port number for drm_of_find_panel_or_bridge(), remove hack
- fbdev: add missing Signed-off-bys
- iommu: remove io-pgtable sanity check hack, has been properly fixed
- minor style fixes


Ulrich Hecht (8):
  drm/bridge: GPIO-controlled display multiplexer driver
  platform/chrome: ChromeOS firmware interface driver
  drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver
  drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver
  arm64: dts: mediatek: Add Elm Rev. 3 device tree
  hack: mediatek: get mmsys to register as both DRM and clock device
  drm/mediatek: Add DRM-based framebuffer device
  drm: mediatek: Fix drm_of_find_panel_or_bridge conversion

 arch/arm64/boot/dts/mediatek/Makefile            |    1 +
 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts |   21 +
 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi     |  210 ++++
 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi     | 1013 ++++++++++++++++++++
 drivers/clk/mediatek/clk-mt8173.c                |    4 +-
 drivers/gpu/drm/bridge/Kconfig                   |   32 +
 drivers/gpu/drm/bridge/Makefile                  |    5 +
 drivers/gpu/drm/bridge/analogix-anx7688.c        |  233 +++++
 drivers/gpu/drm/bridge/generic-gpio-mux.c        |  316 +++++++
 drivers/gpu/drm/bridge/parade-ps8640.c           | 1104 ++++++++++++++++++++++
 drivers/gpu/drm/mediatek/Makefile                |    2 +
 drivers/gpu/drm/mediatek/mtk_dpi.c               |    5 +-
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c           |    5 +-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c           |   15 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.h           |    4 +-
 drivers/gpu/drm/mediatek/mtk_drm_fb.c            |   13 +
 drivers/gpu/drm/mediatek/mtk_drm_fb.h            |    3 +
 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c         |  181 ++++
 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h         |   32 +
 drivers/gpu/drm/mediatek/mtk_dsi.c               |    2 +-
 drivers/gpu/drm/mediatek/mtk_hdmi.c              |    5 +-
 drivers/platform/chrome/Kconfig                  |   18 +
 drivers/platform/chrome/Makefile                 |    2 +
 drivers/platform/chrome/chromeos.c               |  120 +++
 drivers/platform/chrome/chromeos.h               |   61 ++
 drivers/platform/chrome/chromeos_arm.c           |  264 ++++++
 drivers/platform/chrome/elog.h                   |  186 ++++
 include/linux/chromeos_platform.h                |   27 +
 28 files changed, 3874 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
 create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c
 create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c
 create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
 create mode 100644 drivers/platform/chrome/chromeos.c
 create mode 100644 drivers/platform/chrome/chromeos.h
 create mode 100644 drivers/platform/chrome/chromeos_arm.c
 create mode 100644 drivers/platform/chrome/elog.h
 create mode 100644 include/linux/chromeos_platform.h

-- 
2.7.4

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 1/8] drm/bridge: GPIO-controlled display multiplexer driver
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 2/8] platform/chrome: ChromeOS firmware interface driver Ulrich Hecht
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Ported from chromeos-3.18 kernel.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/gpu/drm/bridge/Kconfig            |  11 ++
 drivers/gpu/drm/bridge/Makefile           |   1 +
 drivers/gpu/drm/bridge/generic-gpio-mux.c | 316 ++++++++++++++++++++++++++++++
 3 files changed, 328 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index adf9ae0..966f4eb 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -15,6 +15,17 @@ config DRM_PANEL_BRIDGE
 menu "Display Interface Bridges"
 	depends on DRM && DRM_BRIDGE
 
+config DRM_GENERIC_GPIO_MUX
+	tristate "Generic GPIO-controlled mux"
+	depends on DRM
+	depends on OF
+	select DRM_KMS_HELPER
+	---help---
+	  This bridge driver models a GPIO-controlled display mux with one
+	  input, 2 outputs (e.g. an HDMI mux). The hardware decides which output
+	  is active, reports it as a GPIO, and the driver redirects calls to the
+	  appropriate downstream bridge (if any).
+
 config DRM_ANALOGIX_ANX78XX
 	tristate "Analogix ANX78XX bridge"
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index defcf1e..2d5652e 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
+obj-$(CONFIG_DRM_GENERIC_GPIO_MUX) += generic-gpio-mux.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
 obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o
 obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o
diff --git a/drivers/gpu/drm/bridge/generic-gpio-mux.c b/drivers/gpu/drm/bridge/generic-gpio-mux.c
new file mode 100644
index 0000000..744804b
--- /dev/null
+++ b/drivers/gpu/drm/bridge/generic-gpio-mux.c
@@ -0,0 +1,316 @@
+/*
+ * ANX7688 HDMI->DP bridge driver
+ *
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+struct gpio_display_mux {
+	struct device *dev;
+
+	struct gpio_desc *gpiod_detect;
+	int detect_irq;
+
+	struct drm_bridge bridge;
+
+	struct drm_bridge *next[2];
+};
+
+static inline struct gpio_display_mux *bridge_to_gpio_display_mux(
+		struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct gpio_display_mux, bridge);
+}
+
+static irqreturn_t gpio_display_mux_det_threaded_handler(int unused, void *data)
+{
+	struct gpio_display_mux *gpio_display_mux = data;
+	int active = gpiod_get_value(gpio_display_mux->gpiod_detect);
+
+	dev_dbg(gpio_display_mux->dev, "Interrupt %d!\n", active);
+
+	if (gpio_display_mux->bridge.dev)
+		drm_kms_helper_hotplug_event(gpio_display_mux->bridge.dev);
+
+	return IRQ_HANDLED;
+}
+
+static int gpio_display_mux_attach(struct drm_bridge *bridge)
+{
+	struct gpio_display_mux *gpio_display_mux =
+			bridge_to_gpio_display_mux(bridge);
+	struct drm_bridge *next;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_display_mux->next); i++) {
+		next = gpio_display_mux->next[i];
+		if (next)
+			next->encoder = bridge->encoder;
+	}
+
+	return 0;
+}
+
+static bool gpio_display_mux_mode_fixup(struct drm_bridge *bridge,
+				const struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct gpio_display_mux *gpio_display_mux =
+		bridge_to_gpio_display_mux(bridge);
+	int active;
+	struct drm_bridge *next;
+
+	active = gpiod_get_value(gpio_display_mux->gpiod_detect);
+	next = gpio_display_mux->next[active];
+
+	if (next && next->funcs->mode_fixup)
+		return next->funcs->mode_fixup(next, mode, adjusted_mode);
+	else
+		return true;
+}
+
+static void gpio_display_mux_mode_set(struct drm_bridge *bridge,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct gpio_display_mux *gpio_display_mux =
+		bridge_to_gpio_display_mux(bridge);
+	int active;
+	struct drm_bridge *next;
+
+	active = gpiod_get_value(gpio_display_mux->gpiod_detect);
+	next = gpio_display_mux->next[active];
+
+	if (next && next->funcs->mode_set)
+		next->funcs->mode_set(next, mode, adjusted_mode);
+}
+
+/**
+ * Since this driver _reacts_ to mux changes, we need to make sure all
+ * downstream bridges are pre-enabled.
+ */
+static void gpio_display_mux_pre_enable(struct drm_bridge *bridge)
+{
+	struct gpio_display_mux *gpio_display_mux =
+		bridge_to_gpio_display_mux(bridge);
+	struct drm_bridge *next;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_display_mux->next); i++) {
+		next = gpio_display_mux->next[i];
+		if (next && next->funcs->pre_enable)
+			next->funcs->pre_enable(next);
+	}
+}
+
+static void gpio_display_mux_post_disable(struct drm_bridge *bridge)
+{
+	struct gpio_display_mux *gpio_display_mux =
+		bridge_to_gpio_display_mux(bridge);
+	struct drm_bridge *next;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_display_mux->next); i++) {
+		next = gpio_display_mux->next[i];
+		if (next && next->funcs->post_disable)
+			next->funcs->post_disable(next);
+	}
+}
+
+/**
+ * In an ideal mux driver, only the currently selected bridge should be enabled.
+ * For the sake of simplicity, we just just enable/disable all downstream
+ * bridges at the same time.
+ */
+static void gpio_display_mux_enable(struct drm_bridge *bridge)
+{
+	struct gpio_display_mux *gpio_display_mux =
+		bridge_to_gpio_display_mux(bridge);
+	struct drm_bridge *next;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_display_mux->next); i++) {
+		next = gpio_display_mux->next[i];
+		if (next && next->funcs->enable)
+			next->funcs->enable(next);
+	}
+}
+
+static void gpio_display_mux_disable(struct drm_bridge *bridge)
+{
+	struct gpio_display_mux *gpio_display_mux =
+		bridge_to_gpio_display_mux(bridge);
+	struct drm_bridge *next;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gpio_display_mux->next); i++) {
+		next = gpio_display_mux->next[i];
+		if (next && next->funcs->disable)
+			next->funcs->disable(next);
+	}
+}
+
+static const struct drm_bridge_funcs gpio_display_mux_bridge_funcs = {
+	.attach = gpio_display_mux_attach,
+	.mode_fixup = gpio_display_mux_mode_fixup,
+	.disable = gpio_display_mux_disable,
+	.post_disable = gpio_display_mux_post_disable,
+	.mode_set = gpio_display_mux_mode_set,
+	.pre_enable = gpio_display_mux_pre_enable,
+	.enable = gpio_display_mux_enable,
+};
+
+static int gpio_display_mux_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct gpio_display_mux *gpio_display_mux;
+	struct device_node *port, *ep, *remote;
+	int ret;
+	u32 reg;
+
+	gpio_display_mux = devm_kzalloc(dev, sizeof(*gpio_display_mux),
+					GFP_KERNEL);
+	if (!gpio_display_mux)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, gpio_display_mux);
+	gpio_display_mux->dev = &pdev->dev;
+
+	gpio_display_mux->bridge.of_node = dev->of_node;
+
+	gpio_display_mux->gpiod_detect =
+		devm_gpiod_get(dev, "detect", GPIOD_IN);
+	if (IS_ERR(gpio_display_mux->gpiod_detect))
+		return PTR_ERR(gpio_display_mux->gpiod_detect);
+
+	gpio_display_mux->detect_irq =
+		gpiod_to_irq(gpio_display_mux->gpiod_detect);
+	if (gpio_display_mux->detect_irq < 0) {
+		dev_err(dev, "Failed to get output irq %d\n",
+			gpio_display_mux->detect_irq);
+		return -ENODEV;
+	}
+
+	port = of_graph_get_port_by_id(dev->of_node, 1);
+	if (!port) {
+		dev_err(dev, "Missing output port node\n");
+		return -EINVAL;
+	}
+
+	for_each_child_of_node(port, ep) {
+		if (!ep->name || (of_node_cmp(ep->name, "endpoint") != 0)) {
+			of_node_put(ep);
+			continue;
+		}
+
+		if (of_property_read_u32(ep, "reg", &reg) < 0 ||
+				reg >= ARRAY_SIZE(gpio_display_mux->next)) {
+			dev_err(dev,
+			    "Missing/invalid reg property for endpoint %s\n",
+				ep->full_name);
+			of_node_put(ep);
+			of_node_put(port);
+			return -EINVAL;
+		}
+
+		remote = of_graph_get_remote_port_parent(ep);
+		if (!remote) {
+			dev_err(dev,
+			    "Missing connector/bridge node for endpoint %s\n",
+				ep->full_name);
+			of_node_put(ep);
+			of_node_put(port);
+			return -EINVAL;
+		}
+		of_node_put(ep);
+
+		if (of_device_is_compatible(remote, "hdmi-connector")) {
+			of_node_put(remote);
+			continue;
+		}
+
+		gpio_display_mux->next[reg] = of_drm_find_bridge(remote);
+		if (!gpio_display_mux->next[reg]) {
+			dev_err(dev, "Waiting for external bridge %s\n",
+				remote->name);
+			of_node_put(remote);
+			of_node_put(port);
+			return -EPROBE_DEFER;
+		}
+
+		of_node_put(remote);
+	}
+	of_node_put(port);
+
+	gpio_display_mux->bridge.funcs = &gpio_display_mux_bridge_funcs;
+	ret = drm_bridge_add(&gpio_display_mux->bridge);
+	if (ret < 0) {
+		dev_err(dev, "Failed to add drm bridge\n");
+		return ret;
+	}
+
+	ret = devm_request_threaded_irq(dev, gpio_display_mux->detect_irq,
+				NULL,
+				gpio_display_mux_det_threaded_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+					IRQF_ONESHOT,
+				"gpio-display-mux-det", gpio_display_mux);
+	if (ret) {
+		dev_err(dev, "Failed to request MUX_DET threaded irq\n");
+		goto err_bridge_remove;
+	}
+
+	return 0;
+
+err_bridge_remove:
+	drm_bridge_remove(&gpio_display_mux->bridge);
+
+	return ret;
+}
+
+static int gpio_display_mux_remove(struct platform_device *pdev)
+{
+	struct gpio_display_mux *gpio_display_mux = platform_get_drvdata(pdev);
+
+	drm_bridge_remove(&gpio_display_mux->bridge);
+
+	return 0;
+}
+
+static const struct of_device_id gpio_display_mux_match[] = {
+	{ .compatible = "gpio-display-mux", },
+	{},
+};
+
+struct platform_driver gpio_display_mux_driver = {
+	.probe = gpio_display_mux_probe,
+	.remove = gpio_display_mux_remove,
+	.driver = {
+		.name = "gpio-display-mux",
+		.of_match_table = gpio_display_mux_match,
+	},
+};
+
+module_platform_driver(gpio_display_mux_driver);
+
+MODULE_DESCRIPTION("GPIO-controlled display mux");
+MODULE_AUTHOR("Nicolas Boichat <drinkcat@chromium.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 2/8] platform/chrome: ChromeOS firmware interface driver
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 1/8] drm/bridge: GPIO-controlled display multiplexer driver Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 3/8] drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver Ulrich Hecht
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Ported from chromeos-3.18 kernel.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/platform/chrome/Kconfig        |  18 +++
 drivers/platform/chrome/Makefile       |   2 +
 drivers/platform/chrome/chromeos.c     | 120 +++++++++++++++
 drivers/platform/chrome/chromeos.h     |  61 ++++++++
 drivers/platform/chrome/chromeos_arm.c | 264 +++++++++++++++++++++++++++++++++
 drivers/platform/chrome/elog.h         | 186 +++++++++++++++++++++++
 include/linux/chromeos_platform.h      |  27 ++++
 7 files changed, 678 insertions(+)
 create mode 100644 drivers/platform/chrome/chromeos.c
 create mode 100644 drivers/platform/chrome/chromeos.h
 create mode 100644 drivers/platform/chrome/chromeos_arm.c
 create mode 100644 drivers/platform/chrome/elog.h
 create mode 100644 include/linux/chromeos_platform.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 0ad6e29..f8b1876 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -14,6 +14,24 @@ menuconfig CHROME_PLATFORMS
 
 if CHROME_PLATFORMS
 
+config CHROMEOS
+	bool
+	depends on CHROMEOS_OF_FIRMWARE || (NVRAM && ACPI_CHROMEOS)
+
+	---help---
+	  Provides abstracted interfaces to the firmware features provided on
+	  ChromeOS devices. It depends on a lowlevel driver to implement the
+	  firmware interface on the platform.
+
+config CHROMEOS_OF_FIRMWARE
+	bool "ChromeOS firmware interface driver"
+	depends on OF
+	select CHROMEOS
+	---help---
+	  This driver provides an interface to ChromeOS firmware.
+
+	  Say Y here if you are building for a ChromeOS device.
+
 config CHROMEOS_LAPTOP
 	tristate "Chrome OS Laptop"
 	depends on I2C && DMI && X86
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 66c345c..f10a7b6 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -1,4 +1,6 @@
 
+obj-$(CONFIG_CHROMEOS)		+= chromeos.o
+obj-$(CONFIG_CHROMEOS_OF_FIRMWARE) += chromeos_arm.o
 obj-$(CONFIG_CHROMEOS_LAPTOP)		+= chromeos_laptop.o
 obj-$(CONFIG_CHROMEOS_PSTORE)		+= chromeos_pstore.o
 cros_ec_devs-objs			:= cros_ec_dev.o cros_ec_sysfs.o \
diff --git a/drivers/platform/chrome/chromeos.c b/drivers/platform/chrome/chromeos.c
new file mode 100644
index 0000000..8b01630
--- /dev/null
+++ b/drivers/platform/chrome/chromeos.c
@@ -0,0 +1,120 @@
+/*
+ *  ChromeOS platform support code. Glue layer between higher level functions
+ *  and per-platform firmware interfaces.
+ *
+ *  Copyright (C) 2010 The Chromium OS Authors
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/chromeos_platform.h>
+#include <linux/module.h>
+#include "chromeos.h"
+
+static struct chromeos_vbc *chromeos_vbc_ptr;
+
+static int vbc_read(u8 *buf, int buf_size);
+static int vbc_write_byte(unsigned offset, u8 value);
+
+/* the following defines are copied from
+ * vboot_reference:firmware/lib/vboot_nvstorage.c.
+ */
+#define RECOVERY_OFFSET              2
+#define VBNV_RECOVERY_RW_INVALID_OS  0x43
+
+int chromeos_set_need_recovery(void)
+{
+	if (!chromeos_legacy_set_need_recovery())
+		return 0;
+
+	return vbc_write_byte(RECOVERY_OFFSET, VBNV_RECOVERY_RW_INVALID_OS);
+}
+EXPORT_SYMBOL(chromeos_set_need_recovery);
+
+/*
+ * Lifted from vboot_reference:firmware/lib/vboot_nvstorage.c and formatted.
+ *
+ * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based
+ * algorithm would be faster, but for only 15 bytes isn't worth the code size.
+ */
+static u8 crc8(const u8 *data, int len)
+{
+	unsigned crc = 0;
+	int i, j;
+
+	for (j = len; j; j--, data++) {
+		crc ^= (*data << 8);
+		for (i = 8; i; i--) {
+			if (crc & 0x8000)
+				crc ^= (0x1070 << 3);
+			crc <<= 1;
+		}
+	}
+	return (u8)(crc >> 8);
+}
+
+static int vbc_write_byte(unsigned offset, u8 value)
+{
+	u8 buf[MAX_VBOOT_CONTEXT_BUFFER_SIZE];
+	ssize_t size;
+
+	if (!chromeos_vbc_ptr)
+		return -ENOSYS;
+
+	size = vbc_read(buf, sizeof(buf));
+	if (size <= 0)
+		return -EINVAL;
+
+	if (offset >= (size - 1))
+		return -EINVAL;
+
+	if (buf[offset] == value)
+		return 0;
+
+	buf[offset] = value;
+	buf[size - 1] = crc8(buf, size - 1);
+
+	return chromeos_vbc_ptr->write(buf, size);
+}
+
+/*
+ * Read vboot context and verify it.  If everything checks out, return number
+ * of bytes in the vboot context buffer, -1 on any error (uninitialized
+ * subsystem, corrupted crc8 value, not enough room in the buffer, etc.).
+ */
+static int vbc_read(u8 *buf, int buf_size)
+{
+	ssize_t size;
+
+	if (!chromeos_vbc_ptr)
+		return -ENOSYS;
+
+	size = chromeos_vbc_ptr->read(buf, buf_size);
+	if (size <= 0)
+		return -1;
+
+	if (buf[size - 1] != crc8(buf, size - 1)) {
+		pr_err("%s: vboot context contents corrupted\n", __func__);
+		return -1;
+	}
+	return size;
+}
+
+int chromeos_vbc_register(struct chromeos_vbc *chromeos_vbc)
+{
+	chromeos_vbc_ptr = chromeos_vbc;
+	return 0;
+}
diff --git a/drivers/platform/chrome/chromeos.h b/drivers/platform/chrome/chromeos.h
new file mode 100644
index 0000000..8f4384a
--- /dev/null
+++ b/drivers/platform/chrome/chromeos.h
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2011 The Chromium OS Authors
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _DRIVERS_PLATFORM_CHROMEOS_H
+#define _DRIVERS_PLATFORM_CHROMEOS_H
+
+#define MAX_VBOOT_CONTEXT_BUFFER_SIZE 64  /* Should be enough for anything. */
+
+#ifdef CONFIG_ACPI_CHROMEOS
+extern int chromeos_legacy_set_need_recovery(void);
+#else
+static inline int chromeos_legacy_set_need_recovery(void) { return -ENODEV; }
+#endif
+
+struct chromeos_vbc {
+	/**
+	 * Read vboot context to buffer
+	 *
+	 * @param buf		Pointer to buffer for storing vboot context
+	 * @param count		Size of buffer
+	 * @return	on success, the number of bytes read is returned and
+	 *		on error, -err is returned.
+	 */
+	ssize_t (*read)(void *buf, size_t count);
+
+	/**
+	 * Write vboot context from buffer
+	 *
+	 * @param buf		Pointer to buffer of new vboot context content
+	 * @param count		Size of buffer
+	 * @return	on success, the number of bytes written is returned and
+	 *		on error, -err is returned.
+	 */
+	ssize_t (*write)(const void *buf, size_t count);
+
+	const char *name;
+};
+
+/**
+ * Register chromeos_vbc callbacks.
+ *
+ * @param chromeos_vbc	Pointer to struct holding callbacks
+ * @return	on success, return 0, on error, -err is returned.
+ */
+int chromeos_vbc_register(struct chromeos_vbc *chromeos_vbc);
+
+#endif /* _DRIVERS_PLATFORM_CHROMEOS_H */
diff --git a/drivers/platform/chrome/chromeos_arm.c b/drivers/platform/chrome/chromeos_arm.c
new file mode 100644
index 0000000..337e24d
--- /dev/null
+++ b/drivers/platform/chrome/chromeos_arm.c
@@ -0,0 +1,264 @@
+/*
+ *  Copyright (C) 2011 The Chromium OS Authors
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt) "chromeos_arm: " fmt
+
+#include <linux/bcd.h>
+#include <linux/gpio.h>
+#include <linux/notifier.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "chromeos.h"
+#include "elog.h"
+
+struct chromeos_arm_elog_panic_buffer {
+	uint32_t start;
+	uint32_t size;
+	void __iomem *virt_addr;
+	struct notifier_block nb;
+};
+
+/*
+ * Update the checksum at the last byte
+ */
+static void elog_update_checksum(struct event_header *event, u8 checksum)
+{
+	u8 *event_data = (u8 *)event;
+	event_data[event->length - 1] = checksum;
+}
+
+/*
+ * Simple byte checksum for events
+ */
+static u8 elog_checksum_event(struct event_header *event)
+{
+	u8 index, checksum = 0;
+	u8 *data = (u8 *)event;
+
+	for (index = 0; index < event->length; index++)
+		checksum += data[index];
+	return checksum;
+}
+
+/*
+ * Populate timestamp in event header with current time
+ */
+static void elog_fill_timestamp(struct event_header *event)
+{
+	struct timeval timeval;
+	struct tm time;
+
+	do_gettimeofday(&timeval);
+	time_to_tm(timeval.tv_sec, 0, &time);
+
+	event->second = bin2bcd(time.tm_sec);
+	event->minute = bin2bcd(time.tm_min);
+	event->hour   = bin2bcd(time.tm_hour);
+	event->day    = bin2bcd(time.tm_mday);
+	event->month  = bin2bcd(time.tm_mon + 1);
+	event->year   = bin2bcd(time.tm_year % 100);
+}
+
+/*
+ * Fill out an event structure with space for the data and checksum.
+ */
+void elog_prepare_event(struct event_header *event, u8 event_type, void *data,
+			u8 data_size)
+{
+	event->type = event_type;
+	event->length = sizeof(*event) + data_size + 1;
+	elog_fill_timestamp(event);
+
+	if (data_size)
+		memcpy(&event[1], data, data_size);
+
+	/* Zero the checksum byte and then compute checksum */
+	elog_update_checksum(event, 0);
+	elog_update_checksum(event, -(elog_checksum_event(event)));
+}
+
+static int chromeos_arm_elog_panic(struct notifier_block *this,
+				   unsigned long p_event, void *ptr)
+{
+	struct chromeos_arm_elog_panic_buffer *buf;
+	uint32_t reason = ELOG_SHUTDOWN_PANIC;
+	const u8 data_size = sizeof(reason);
+	union {
+		struct event_header hdr;
+		u8 bytes[sizeof(struct event_header) + data_size + 1];
+	} event;
+
+	buf = container_of(this, struct chromeos_arm_elog_panic_buffer, nb);
+	elog_prepare_event(&event.hdr, ELOG_TYPE_OS_EVENT, &reason, data_size);
+	memcpy_toio(buf->virt_addr, event.bytes, sizeof(event.bytes));
+
+	return NOTIFY_DONE;
+}
+
+static int chromeos_arm_panic_init(struct platform_device *pdev, u32 start,
+				   u32 size)
+{
+	int ret = -EINVAL;
+	struct chromeos_arm_elog_panic_buffer *buf;
+
+	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf) {
+		dev_err(&pdev->dev, "failed to allocate panic notifier.\n");
+		ret = -ENOMEM;
+		goto fail1;
+	}
+
+	buf->start = start;
+	buf->size = size;
+	buf->nb.notifier_call = chromeos_arm_elog_panic;
+
+	if (!request_mem_region(start, size, "elog panic event")) {
+		dev_err(&pdev->dev, "failed to request panic event buffer.\n");
+		goto fail2;
+	}
+
+	buf->virt_addr = ioremap(start, size);
+	if (!buf->virt_addr) {
+		dev_err(&pdev->dev, "failed to map panic event buffer.\n");
+		goto fail3;
+	}
+
+	atomic_notifier_chain_register(&panic_notifier_list, &buf->nb);
+
+	platform_set_drvdata(pdev, buf);
+
+	return 0;
+
+fail3:
+	release_mem_region(start, size);
+fail2:
+	kfree(buf);
+fail1:
+	return ret;
+}
+
+static int dt_gpio_init(struct platform_device *pdev, const char *of_list_name,
+			const char *gpio_desc_name, const char *sysfs_name)
+{
+	int gpio, err, active_low;
+	enum of_gpio_flags flags;
+	struct device_node *np = pdev->dev.of_node;
+
+	gpio = of_get_named_gpio_flags(np, of_list_name, 0, &flags);
+	if (!gpio_is_valid(gpio)) {
+		dev_err(&pdev->dev, "invalid %s descriptor\n", of_list_name);
+		return -EINVAL;
+	}
+
+	err = gpio_request_one(gpio, GPIOF_DIR_IN, gpio_desc_name);
+	if (err)
+		return err;
+
+	active_low = !!(flags & OF_GPIO_ACTIVE_LOW);
+//	err = gpio_sysfs_set_active_low(gpio, active_low);
+//	if (err)
+//		return err;
+
+	gpio_export(gpio, 0);
+	gpio_export_link(&pdev->dev, sysfs_name, gpio);
+	return 0;
+}
+
+static int chromeos_arm_probe(struct platform_device *pdev)
+{
+	int err;
+	u32 elog_panic_event[2];
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np) {
+		err = -ENODEV;
+		goto err;
+	}
+
+	err = dt_gpio_init(pdev, "write-protect-gpio",
+			   "firmware-write-protect", "write-protect");
+	if (err)
+		goto err;
+	err = dt_gpio_init(pdev, "recovery-switch",
+			   "firmware-recovery-switch", "recovery-switch");
+	err = dt_gpio_init(pdev, "developer-switch",
+			   "firmware-developer-switch", "developer-switch");
+
+	if (!of_property_read_u32_array(np, "elog-panic-event",
+					elog_panic_event,
+					ARRAY_SIZE(elog_panic_event))) {
+		err = chromeos_arm_panic_init(pdev, elog_panic_event[0],
+					      elog_panic_event[1]);
+		if (err)
+			goto err;
+	}
+
+	dev_info(&pdev->dev, "chromeos system detected\n");
+
+	err = 0;
+err:
+	of_node_put(np);
+
+	return err;
+}
+
+static int chromeos_arm_remove(struct platform_device *pdev)
+{
+	struct chromeos_arm_elog_panic_buffer *buf;
+
+	buf = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+	if (buf) {
+		atomic_notifier_chain_unregister(&panic_notifier_list,
+						 &buf->nb);
+		release_mem_region(buf->start, buf->size);
+		iounmap(buf->virt_addr);
+		kfree(buf);
+	}
+	return 0;
+}
+
+static struct platform_driver chromeos_arm_driver = {
+	.probe = chromeos_arm_probe,
+	.remove = chromeos_arm_remove,
+	.driver = {
+		.name = "chromeos_arm",
+	},
+};
+
+static int __init chromeos_arm_init(void)
+{
+	struct device_node *fw_dn;
+	struct platform_device *pdev;
+
+	fw_dn = of_find_compatible_node(NULL, NULL, "chromeos-firmware");
+	if (!fw_dn)
+		return -ENODEV;
+
+	pdev = platform_device_register_simple("chromeos_arm", -1, NULL, 0);
+	pdev->dev.of_node = fw_dn;
+
+	platform_driver_register(&chromeos_arm_driver);
+
+	return 0;
+}
+subsys_initcall(chromeos_arm_init);
diff --git a/drivers/platform/chrome/elog.h b/drivers/platform/chrome/elog.h
new file mode 100644
index 0000000..84b005f
--- /dev/null
+++ b/drivers/platform/chrome/elog.h
@@ -0,0 +1,186 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 The ChromiumOS Authors.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#ifndef ELOG_H_
+#define ELOG_H_
+
+/* SMI command code for GSMI event logging */
+#define ELOG_GSMI_APM_CNT                 0xEF
+
+#define MAX_EVENT_SIZE                    0x7F
+
+/* End of log */
+#define ELOG_TYPE_EOL                     0xFF
+
+/*
+ * Standard SMBIOS event log types below 0x80
+ */
+#define ELOG_TYPE_UNDEFINED_EVENT         0x00
+#define ELOG_TYPE_SINGLE_BIT_ECC_MEM_ERR  0x01
+#define ELOG_TYPE_MULTI_BIT_ECC_MEM_ERR   0x02
+#define ELOG_TYPE_MEM_PARITY_ERR          0x03
+#define ELOG_TYPE_BUS_TIMEOUT             0x04
+#define ELOG_TYPE_IO_CHECK                0x05
+#define ELOG_TYPE_SW_NMI                  0x06
+#define ELOG_TYPE_POST_MEM_RESIZE         0x07
+#define ELOG_TYPE_POST_ERR                0x08
+#define ELOG_TYPE_PCI_PERR                0x09
+#define ELOG_TYPE_PCI_SERR                0x0A
+#define ELOG_TYPE_CPU_FAIL                0x0B
+#define ELOG_TYPE_EISA_TIMEOUT            0x0C
+#define ELOG_TYPE_CORRECTABLE_MEMLOG_DIS  0x0D
+#define ELOG_TYPE_LOG_DISABLED            0x0E
+#define ELOG_TYPE_UNDEFINED_EVENT2        0x0F
+#define ELOG_TYPE_SYS_LIMIT_EXCEED        0x10
+#define ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED  0x11
+#define ELOG_TYPE_SYS_CONFIG_INFO         0x12
+#define ELOG_TYPE_HDD_INFO                0x13
+#define ELOG_TYPE_SYS_RECONFIG            0x14
+#define ELOG_TYPE_CPU_ERROR               0x15
+#define ELOG_TYPE_LOG_CLEAR               0x16
+#define ELOG_TYPE_BOOT                    0x17
+
+/*
+ * Extended defined OEM event types start at 0x80
+ */
+
+/* OS/kernel events */
+#define ELOG_TYPE_OS_EVENT                0x81
+#define  ELOG_SHUTDOWN_CLEAN              0    /* Clean Shutdown */
+#define  ELOG_SHUTDOWN_NMIWDT             1    /* NMI Watchdog */
+#define  ELOG_SHUTDOWN_PANIC              2    /* Panic */
+#define  ELOG_SHUTDOWN_OOPS               3    /* Oops */
+#define  ELOG_SHUTDOWN_DIE                4    /* Die - No longer meaningful */
+#define  ELOG_SHUTDOWN_MCE                5    /* Machine Check */
+#define  ELOG_SHUTDOWN_SOFTWDT            6    /* Software Watchdog */
+#define  ELOG_SHUTDOWN_MBE                7    /* Uncorrected ECC */
+#define  ELOG_SHUTDOWN_TRIPLE             8    /* Triple Fault */
+#define  ELOG_SHUTDOWN_THERMAL            9    /* Critical Thermal Threshold */
+
+/* Last event from coreboot */
+#define ELOG_TYPE_OS_BOOT                 0x90
+
+/* Embedded controller event */
+#define ELOG_TYPE_EC_EVENT                0x91
+#define EC_EVENT_LID_CLOSED                0x01
+#define EC_EVENT_LID_OPEN                  0x02
+#define EC_EVENT_POWER_BUTTON              0x03
+#define EC_EVENT_AC_CONNECTED              0x04
+#define EC_EVENT_AC_DISCONNECTED           0x05
+#define EC_EVENT_BATTERY_LOW               0x06
+#define EC_EVENT_BATTERY_CRITICAL          0x07
+#define EC_EVENT_BATTERY                   0x08
+#define EC_EVENT_THERMAL_THRESHOLD         0x09
+#define EC_EVENT_THERMAL_OVERLOAD          0x0a
+#define EC_EVENT_THERMAL                   0x0b
+#define EC_EVENT_USB_CHARGER               0x0c
+#define EC_EVENT_KEY_PRESSED               0x0d
+#define EC_EVENT_INTERFACE_READY           0x0e
+#define EC_EVENT_KEYBOARD_RECOVERY         0x0f
+#define EC_EVENT_THERMAL_SHUTDOWN          0x10
+#define EC_EVENT_BATTERY_SHUTDOWN          0x11
+#define EC_EVENT_FAN_ERROR                 0x12
+
+/* Power */
+#define ELOG_TYPE_POWER_FAIL              0x92
+#define ELOG_TYPE_SUS_POWER_FAIL          0x93
+#define ELOG_TYPE_PWROK_FAIL              0x94
+#define ELOG_TYPE_SYS_PWROK_FAIL          0x95
+#define ELOG_TYPE_POWER_ON                0x96
+#define ELOG_TYPE_POWER_BUTTON            0x97
+#define ELOG_TYPE_POWER_BUTTON_OVERRIDE   0x98
+
+/* Reset */
+#define ELOG_TYPE_RESET_BUTTON            0x99
+#define ELOG_TYPE_SYSTEM_RESET            0x9a
+#define ELOG_TYPE_RTC_RESET               0x9b
+#define ELOG_TYPE_TCO_RESET               0x9c
+
+/* Sleep/Wake */
+#define ELOG_TYPE_ACPI_ENTER              0x9d
+#define ELOG_TYPE_ACPI_WAKE               0x9e
+#define ELOG_TYPE_WAKE_SOURCE             0x9f
+#define  ELOG_WAKE_SOURCE_PCIE             0x00
+#define  ELOG_WAKE_SOURCE_PME              0x01
+#define  ELOG_WAKE_SOURCE_PME_INTERNAL     0x02
+#define  ELOG_WAKE_SOURCE_RTC              0x03
+#define  ELOG_WAKE_SOURCE_GPIO             0x04
+#define  ELOG_WAKE_SOURCE_SMBUS            0x05
+#define  ELOG_WAKE_SOURCE_PWRBTN           0x06
+struct elog_event_data_wake {
+	u8 source;
+	u32 instance;
+} __packed;
+
+/* Chrome OS related events */
+#define ELOG_TYPE_CROS_DEVELOPER_MODE     0xa0
+#define ELOG_TYPE_CROS_RECOVERY_MODE      0xa1
+#define  ELOG_CROS_RECOVERY_MODE_BUTTON    0x02
+
+/* Management Engine Events */
+#define ELOG_TYPE_MANAGEMENT_ENGINE       0xa2
+#define ELOG_TYPE_MANAGEMENT_ENGINE_EXT   0xa4
+struct elog_event_data_me_extended {
+	u8 current_working_state;
+	u8 operation_state;
+	u8 operation_mode;
+	u8 error_code;
+	u8 progress_code;
+	u8 current_pmevent;
+	u8 current_state;
+} __packed;
+
+/* Last post code from previous boot */
+#define ELOG_TYPE_LAST_POST_CODE          0xa3
+
+/* EC Shutdown Reason */
+#define ELOG_TYPE_EC_SHUTDOWN             0xa5
+
+/* ARM/generic versions of sleep/wake */
+#define ELOG_TYPE_SLEEP                   0xa7
+#define ELOG_TYPE_WAKE                    0xa8
+
+/* ELOG header */
+struct elog_header {
+	u32 magic;
+	u8 version;
+	u8 header_size;
+	u8 reserved[2];
+} __packed;
+
+/* ELOG related constants */
+#define ELOG_SIGNATURE			0x474f4c45  /* 'ELOG' */
+#define ELOG_VERSION			1
+
+/* SMBIOS event log header */
+struct event_header {
+	u8 type;
+	u8 length;
+	u8 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 minute;
+	u8 second;
+} __packed;
+
+extern void elog_prepare_event(struct event_header *event, u8 event_type,
+			       void *data, u8 data_size);
+
+#endif /* ELOG_H_ */
diff --git a/include/linux/chromeos_platform.h b/include/linux/chromeos_platform.h
new file mode 100644
index 0000000..32c4510
--- /dev/null
+++ b/include/linux/chromeos_platform.h
@@ -0,0 +1,27 @@
+#ifndef _LINUX_CHROMEOS_PLATFORM_H
+#define _LINUX_CHROMEOS_PLATFORM_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_CHROMEOS
+/*
+ * ChromeOS platform support code. Glue layer between higher level functions
+ * and per-platform firmware interfaces.
+ */
+
+/*
+ * Set the taint bit telling firmware that the currently running side needs
+ * recovery (or reinstall).
+ */
+extern int chromeos_set_need_recovery(void);
+
+#else
+
+static inline int chromeos_set_need_recovery(void)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_CHROMEOS */
+
+#endif /* _LINUX_CHROMEOS_PLATFORM_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 3/8] drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 1/8] drm/bridge: GPIO-controlled display multiplexer driver Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 2/8] platform/chrome: ChromeOS firmware interface driver Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 4/8] drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver Ulrich Hecht
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Ported from chromeos-3.18 kernel.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/gpu/drm/bridge/Kconfig         |   12 +
 drivers/gpu/drm/bridge/Makefile        |    3 +
 drivers/gpu/drm/bridge/parade-ps8640.c | 1104 ++++++++++++++++++++++++++++++++
 3 files changed, 1119 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 966f4eb..a1c0d95 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -26,6 +26,18 @@ config DRM_GENERIC_GPIO_MUX
 	  is active, reports it as a GPIO, and the driver redirects calls to the
 	  appropriate downstream bridge (if any).
 
+config DRM_PARADE_PS8640
+	tristate "Parade PS8640 MIPI DSI to eDP Converter"
+	depends on DRM
+	depends on OF
+	select DRM_KMS_HELPER
+	select DRM_MIPI_DSI
+	select DRM_PANEL
+	---help---
+	  Choose this option if you have PS8640 for display
+	  The PS8640 is a high-performance and low-power
+	  MIPI DSI to eDP converter
+
 config DRM_ANALOGIX_ANX78XX
 	tristate "Analogix ANX78XX bridge"
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 2d5652e..6be8a9d 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,3 +1,6 @@
+ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_GENERIC_GPIO_MUX) += generic-gpio-mux.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
new file mode 100644
index 0000000..8489f6c
--- /dev/null
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -0,0 +1,1104 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
+#include <asm/unaligned.h>
+#include <drm/drm_panel.h>
+
+#include <drmP.h>
+#include <drm_atomic_helper.h>
+#include <drm_crtc_helper.h>
+#include <drm_crtc.h>
+#include <drm_edid.h>
+#include <drm_mipi_dsi.h>
+
+#define PAGE1_VSTART		0x6b
+#define PAGE2_SPI_CFG3		0x82
+#define I2C_TO_SPI_RESET	0x20
+#define PAGE2_ROMADD_BYTE1	0x8e
+#define PAGE2_ROMADD_BYTE2	0x8f
+#define PAGE2_SWSPI_WDATA	0x90
+#define PAGE2_SWSPI_RDATA	0x91
+#define PAGE2_SWSPI_LEN		0x92
+#define PAGE2_SWSPI_CTL		0x93
+#define TRIGGER_NO_READBACK	0x05
+#define TRIGGER_READBACK	0x01
+#define PAGE2_SPI_STATUS	0x9e
+#define SPI_READY		0x0c
+#define PAGE2_GPIO_L		0xa6
+#define PAGE2_GPIO_H		0xa7
+#define PS_GPIO9		BIT(1)
+#define PAGE2_IROM_CTRL		0xb0
+#define IROM_ENABLE		0xc0
+#define IROM_DISABLE		0x80
+#define PAGE2_SW_RESET		0xbc
+#define SPI_SW_RESET		BIT(7)
+#define MPU_SW_RESET		BIT(6)
+#define PAGE2_ENCTLSPI_WR	0xda
+#define PAGE2_I2C_BYPASS	0xea
+#define I2C_BYPASS_EN		0xd0
+#define PAGE2_MCS_EN		0xf3
+#define MCS_EN			BIT(0)
+#define PAGE3_SET_ADD		0xfe
+#define PAGE3_SET_VAL		0xff
+#define VDO_CTL_ADD		0x13
+#define VDO_DIS			0x18
+#define VDO_EN			0x1c
+#define PAGE4_REV_L		0xf0
+#define PAGE4_REV_H		0xf1
+#define PAGE4_CHIP_L		0xf2
+#define PAGE4_CHIP_H		0xf3
+
+/* Firmware */
+#define SPI_MAX_RETRY_CNT	8
+#define PS_FW_NAME		"ps864x_fw.bin"
+
+#define FW_CHIP_ID_OFFSET	0
+#define FW_VERSION_OFFSET	2
+#define EDID_I2C_ADDR		0x50
+
+#define WRITE_STATUS_REG_CMD	0x01
+#define READ_STATUS_REG_CMD	0x05
+#define BUSY			BIT(0)
+#define CLEAR_ALL_PROTECT	0x00
+#define BLK_PROTECT_BITS	0x0c
+#define STATUS_REG_PROTECT	BIT(7)
+#define WRITE_ENABLE_CMD	0x06
+#define CHIP_ERASE_CMD		0xc7
+#define MAX_DEVS		0x8
+struct ps8640_info {
+	u8 family_id;
+	u8 variant_id;
+	u16 version;
+};
+
+struct ps8640 {
+	struct drm_connector connector;
+	struct drm_bridge bridge;
+	struct edid *edid;
+	struct mipi_dsi_device dsi;
+	struct i2c_client *page[MAX_DEVS];
+	struct i2c_client *ddc_i2c;
+	struct regulator *v33;
+	struct regulator *v12;
+	struct drm_panel *panel;
+	struct gpio_desc *gpio_rst_n;
+	struct gpio_desc *gpio_slp_n;
+	struct gpio_desc *gpio_mode_sel_n;
+	bool enabled;
+
+	/* firmware file info */
+	struct ps8640_info info;
+	bool in_fw_update;
+	/* for firmware update protect */
+	struct mutex fw_mutex;
+};
+
+static const u8 enc_ctrl_code[6] = { 0xaa, 0x55, 0x50, 0x41, 0x52, 0x44 };
+static const u8 hw_chip_id[4] = { 0x00, 0x0a, 0x00, 0x30 };
+
+static inline struct ps8640 *bridge_to_ps8640(struct drm_bridge *e)
+{
+	return container_of(e, struct ps8640, bridge);
+}
+
+static inline struct ps8640 *connector_to_ps8640(struct drm_connector *e)
+{
+	return container_of(e, struct ps8640, connector);
+}
+
+static int ps8640_read(struct i2c_client *client, u8 reg, u8 *data,
+		       u16 data_len)
+{
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = client->addr,
+		 .flags = 0,
+		 .len = 1,
+		 .buf = &reg,
+		},
+		{
+		 .addr = client->addr,
+		 .flags = I2C_M_RD,
+		 .len = data_len,
+		 .buf = data,
+		}
+	};
+
+	ret = i2c_transfer(client->adapter, msgs, 2);
+
+	if (ret == 2)
+		return 0;
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int ps8640_write_bytes(struct i2c_client *client, const u8 *data,
+			      u16 data_len)
+{
+	int ret;
+	struct i2c_msg msg;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = data_len;
+	msg.buf = (u8 *)data;
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret == 1)
+		return 0;
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int ps8640_write_byte(struct i2c_client *client, u8 reg,  u8 data)
+{
+	u8 buf[] = { reg, data };
+
+	return ps8640_write_bytes(client, buf, sizeof(buf));
+}
+
+static void ps8640_get_mcu_fw_version(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[5];
+	u8 fw_ver[2];
+
+	ps8640_read(client, 0x4, fw_ver, sizeof(fw_ver));
+	ps_bridge->info.version = (fw_ver[0] << 8) | fw_ver[1];
+
+	DRM_INFO_ONCE("ps8640 rom fw version %d.%d\n", fw_ver[0], fw_ver[1]);
+}
+
+static int ps8640_bridge_unmute(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[3];
+	u8 vdo_ctrl_buf[3] = { PAGE3_SET_ADD, VDO_CTL_ADD, VDO_EN };
+
+	return ps8640_write_bytes(client, vdo_ctrl_buf, sizeof(vdo_ctrl_buf));
+}
+
+static int ps8640_bridge_mute(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[3];
+	u8 vdo_ctrl_buf[3] = { PAGE3_SET_ADD, VDO_CTL_ADD, VDO_DIS };
+
+	return ps8640_write_bytes(client, vdo_ctrl_buf, sizeof(vdo_ctrl_buf));
+}
+
+static void ps8640_pre_enable(struct drm_bridge *bridge)
+{
+	struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
+	struct i2c_client *client = ps_bridge->page[2];
+	struct i2c_client *page1 = ps_bridge->page[1];
+	int err;
+	u8 set_vdo_done, mcs_en, vstart;
+	ktime_t timeout;
+
+	if (ps_bridge->in_fw_update)
+		return;
+
+	if (ps_bridge->enabled)
+		return;
+
+	err = drm_panel_prepare(ps_bridge->panel);
+	if (err < 0) {
+		DRM_ERROR("failed to prepare panel: %d\n", err);
+		return;
+	}
+
+	err = regulator_enable(ps_bridge->v12);
+	if (err) {
+		DRM_ERROR("failed to enable power 1.2v %d", err);
+		goto err_panel_unprepare;
+	}
+
+	usleep_range(5000, 5500);
+
+	err = regulator_enable(ps_bridge->v33);
+	if (err) {
+		DRM_ERROR("failed to enable power 3.3v %d", err);
+		goto err_pwr_v12_disable;
+	}
+
+	gpiod_set_value(ps_bridge->gpio_slp_n, 1);
+	usleep_range(2000, 2500);
+	gpiod_set_value(ps_bridge->gpio_rst_n, 1);
+
+	/*
+	 * Wait for the ps8640 embed mcu ready
+	 * First wait 200ms and then check the mcu ready flag every 20ms
+	 */
+	msleep(200);
+
+	timeout = ktime_add_ms(ktime_get(), 200);
+	for (;;) {
+		err = ps8640_read(client, PAGE2_GPIO_H, &set_vdo_done, 1);
+		if (err < 0) {
+			DRM_ERROR("failed read PAGE2_GPIO_H: %d\n", err);
+			goto err_pwr_v33_disable;
+		}
+		if ((set_vdo_done & PS_GPIO9) == PS_GPIO9)
+			break;
+		if (ktime_compare(ktime_get(), timeout) > 0)
+			break;
+		msleep(20);
+	}
+
+	msleep(50);
+
+	ps8640_read(page1, PAGE1_VSTART, &vstart, 1);
+	DRM_INFO("PS8640 PAGE1.0x6B = 0x%x\n", vstart);
+
+	/**
+	 * The Manufacturer Command Set (MCS) is a device dependent interface
+	 * intended for factory programming of the display module default
+	 * parameters. Once the display module is configured, the MCS shall be
+	 * disabled by the manufacturer. Once disabled, all MCS commands are
+	 * ignored by the display interface.
+	 */
+	ps8640_read(client, PAGE2_MCS_EN, &mcs_en, 1);
+	ps8640_write_byte(client, PAGE2_MCS_EN, mcs_en & ~MCS_EN);
+
+	if (ps_bridge->info.version == 0)
+		ps8640_get_mcu_fw_version(ps_bridge);
+
+	err = ps8640_bridge_unmute(ps_bridge);
+	if (err)
+		DRM_ERROR("failed to enable unmutevideo: %d\n", err);
+	/* Switch access edp panel's edid through i2c */
+	ps8640_write_byte(client, PAGE2_I2C_BYPASS, I2C_BYPASS_EN);
+	ps_bridge->enabled = true;
+
+	return;
+
+err_pwr_v33_disable:
+	gpiod_set_value(ps_bridge->gpio_rst_n, 0);
+	gpiod_set_value(ps_bridge->gpio_slp_n, 0);
+	regulator_disable(ps_bridge->v33);
+err_pwr_v12_disable:
+	regulator_disable(ps_bridge->v12);
+err_panel_unprepare:
+	drm_panel_unprepare(ps_bridge->panel);
+}
+
+static void ps8640_enable(struct drm_bridge *bridge)
+{
+	struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
+	int err;
+
+	err = drm_panel_enable(ps_bridge->panel);
+	if (err < 0)
+		DRM_ERROR("failed to enable panel: %d\n", err);
+}
+
+static void ps8640_disable(struct drm_bridge *bridge)
+{
+	struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
+	int err;
+
+	err = drm_panel_disable(ps_bridge->panel);
+	if (err < 0)
+		DRM_ERROR("failed to disable panel: %d\n", err);
+}
+
+static void ps8640_post_disable(struct drm_bridge *bridge)
+{
+	struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
+	int err;
+
+	if (ps_bridge->in_fw_update)
+		return;
+
+	if (!ps_bridge->enabled)
+		return;
+
+	ps_bridge->enabled = false;
+
+	err = ps8640_bridge_mute(ps_bridge);
+	if (err < 0)
+		DRM_ERROR("failed to unmutevideo: %d\n", err);
+
+	gpiod_set_value(ps_bridge->gpio_rst_n, 0);
+	gpiod_set_value(ps_bridge->gpio_slp_n, 0);
+
+	err = regulator_disable(ps_bridge->v33);
+	if (err)
+		DRM_ERROR("failed to disable power 3.3v: %d\n", err);
+
+	err = regulator_disable(ps_bridge->v12);
+	if (err)
+		DRM_ERROR("failed to disable power 1.2v: %d\n", err);
+
+	err = drm_panel_unprepare(ps_bridge->panel);
+	if (err)
+		DRM_ERROR("failed to unprepare panel: %d\n", err);
+}
+
+static int ps8640_get_modes(struct drm_connector *connector)
+{
+	struct ps8640 *ps_bridge = connector_to_ps8640(connector);
+	struct device *dev = &ps_bridge->page[0]->dev;
+	struct edid *edid;
+	int num_modes = 0;
+	bool power_off;
+
+	if (ps_bridge->edid)
+		return drm_add_edid_modes(connector, ps_bridge->edid);
+
+	power_off = !ps_bridge->enabled;
+	ps8640_pre_enable(&ps_bridge->bridge);
+
+	edid = devm_kmalloc(dev, sizeof(edid), GFP_KERNEL);
+	if (!edid) {
+		DRM_ERROR("Failed to allocate EDID\n");
+		return 0;
+	}
+
+	edid = drm_get_edid(connector, ps_bridge->ddc_i2c->adapter);
+	if (edid == NULL)
+		goto out;
+
+	ps_bridge->edid = edid;
+	drm_mode_connector_update_edid_property(connector, ps_bridge->edid);
+	num_modes = drm_add_edid_modes(connector, ps_bridge->edid);
+
+out:
+	if (power_off)
+		ps8640_post_disable(&ps_bridge->bridge);
+
+	return num_modes;
+}
+
+static struct drm_encoder *ps8640_best_encoder(struct drm_connector *connector)
+{
+	struct ps8640 *ps_bridge = connector_to_ps8640(connector);
+
+	return ps_bridge->bridge.encoder;
+}
+
+static const struct drm_connector_helper_funcs ps8640_connector_helper_funcs = {
+	.get_modes = ps8640_get_modes,
+	.best_encoder = ps8640_best_encoder,
+};
+
+static enum drm_connector_status ps8640_detect(struct drm_connector *connector,
+					       bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs ps8640_connector_funcs = {
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = ps8640_detect,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+int ps8640_bridge_attach(struct drm_bridge *bridge)
+{
+	struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
+	struct device *dev = &ps_bridge->page[0]->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *port, *in_ep;
+	struct device_node *dsi_node = NULL;
+	struct mipi_dsi_host *host = ps_bridge->dsi.host;
+	int ret;
+
+	ret = drm_connector_init(bridge->dev, &ps_bridge->connector,
+				 &ps8640_connector_funcs,
+				 DRM_MODE_CONNECTOR_eDP);
+
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm: %d\n", ret);
+		return ret;
+	}
+
+	drm_connector_helper_add(&ps_bridge->connector,
+				 &ps8640_connector_helper_funcs);
+
+	ps_bridge->connector.dpms = DRM_MODE_DPMS_ON;
+	drm_mode_connector_attach_encoder(&ps_bridge->connector,
+					  bridge->encoder);
+
+	if (ps_bridge->panel)
+		drm_panel_attach(ps_bridge->panel, &ps_bridge->connector);
+
+	/* port at 0 is ps8640 dsi input port */
+	port = of_graph_get_port_by_id(np, 0);
+	if (port) {
+		in_ep = of_get_child_by_name(port, "endpoint");
+		of_node_put(port);
+		if (in_ep) {
+			dsi_node = of_graph_get_remote_port_parent(in_ep);
+			of_node_put(in_ep);
+		}
+	}
+	if (dsi_node) {
+		host = of_find_mipi_dsi_host_by_node(dsi_node);
+		of_node_put(dsi_node);
+		if (!host) {
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+
+	ps_bridge->dsi.host = host;
+	ps_bridge->dsi.mode_flags = MIPI_DSI_MODE_VIDEO |
+				     MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+	ps_bridge->dsi.format = MIPI_DSI_FMT_RGB888;
+	ps_bridge->dsi.lanes = 4;
+	ret = mipi_dsi_attach(&ps_bridge->dsi);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	if (ps_bridge->panel)
+		drm_panel_detach(ps_bridge->panel);
+	drm_connector_cleanup(&ps_bridge->connector);
+	return ret;
+}
+
+static const struct drm_bridge_funcs ps8640_bridge_funcs = {
+	.attach = ps8640_bridge_attach,
+	.disable = ps8640_disable,
+	.post_disable = ps8640_post_disable,
+	.pre_enable = ps8640_pre_enable,
+	.enable = ps8640_enable,
+};
+
+/* Firmware Version is returned as Major.Minor */
+static ssize_t ps8640_fw_version_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct ps8640 *ps_bridge = dev_get_drvdata(dev);
+	struct ps8640_info *info = &ps_bridge->info;
+
+	return scnprintf(buf, PAGE_SIZE, "%u.%u\n", info->version >> 8,
+			 info->version & 0xff);
+}
+
+/* Hardware Version is returned as FamilyID.VariantID */
+static ssize_t ps8640_hw_version_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct ps8640 *ps_bridge = dev_get_drvdata(dev);
+	struct ps8640_info *info = &ps_bridge->info;
+
+	return scnprintf(buf, PAGE_SIZE, "ps%u.%u\n", info->family_id,
+			 info->variant_id);
+}
+
+static int ps8640_spi_send_cmd(struct ps8640 *ps_bridge, u8 *cmd, u8 cmd_len)
+{
+	struct i2c_client *client = ps_bridge->page[2];
+	u8 i, buf[3] = { PAGE2_SWSPI_LEN, cmd_len - 1, TRIGGER_NO_READBACK };
+	int ret;
+
+	ret = ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_ENABLE);
+	if (ret)
+		goto err;
+
+	/* write command in write port */
+	for (i = 0; i < cmd_len; i++) {
+		ret = ps8640_write_byte(client, PAGE2_SWSPI_WDATA, cmd[i]);
+		if (ret)
+			goto err_irom_disable;
+	}
+
+	ret = ps8640_write_bytes(client, buf, sizeof(buf));
+	if (ret)
+		goto err_irom_disable;
+
+	ret = ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_DISABLE);
+	if (ret)
+		goto err;
+
+	return 0;
+err_irom_disable:
+	ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_DISABLE);
+err:
+	dev_err(&client->dev, "send command err: %d\n", ret);
+	return ret;
+}
+
+static int ps8640_wait_spi_ready(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[2];
+	u8 spi_rdy_st;
+	ktime_t timeout;
+
+	timeout = ktime_add_ms(ktime_get(), 200);
+	for (;;) {
+		ps8640_read(client, PAGE2_SPI_STATUS, &spi_rdy_st, 1);
+		if ((spi_rdy_st & SPI_READY) != SPI_READY)
+			break;
+
+		if (ktime_compare(ktime_get(), timeout) > 0) {
+			dev_err(&client->dev, "wait spi ready timeout\n");
+			return -EBUSY;
+		}
+
+		msleep(20);
+	}
+
+	return 0;
+}
+
+static int ps8640_wait_spi_nobusy(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[2];
+	u8 spi_status, buf[3] = { PAGE2_SWSPI_LEN, 0, TRIGGER_READBACK };
+	int ret;
+	ktime_t timeout;
+
+	timeout = ktime_add_ms(ktime_get(), 500);
+	for (;;) {
+		/* 0x05 RDSR; Read-Status-Register */
+		ret = ps8640_write_byte(client, PAGE2_SWSPI_WDATA,
+					READ_STATUS_REG_CMD);
+		if (ret)
+			goto err_send_cmd_exit;
+
+		ret = ps8640_write_bytes(client, buf, 3);
+		if (ret)
+			goto err_send_cmd_exit;
+
+		/* delay for cmd send */
+		usleep_range(300, 500);
+		/* wait for SPI ROM until not busy */
+		ret = ps8640_read(client, PAGE2_SWSPI_RDATA, &spi_status, 1);
+		if (ret)
+			goto err_send_cmd_exit;
+
+		if (!(spi_status & BUSY))
+			break;
+
+		if (ktime_compare(ktime_get(), timeout) > 0) {
+			dev_err(&client->dev, "wait spi no busy timeout: %d\n",
+				ret);
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+
+err_send_cmd_exit:
+	dev_err(&client->dev, "send command err: %d\n", ret);
+	return ret;
+}
+
+static int ps8640_wait_rom_idle(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[0];
+	int ret;
+
+	ret = ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_ENABLE);
+	if (ret)
+		goto exit;
+
+	ret = ps8640_wait_spi_ready(ps_bridge);
+	if (ret)
+		goto err_spi;
+
+	ret = ps8640_wait_spi_nobusy(ps_bridge);
+	if (ret)
+		goto err_spi;
+
+	ret = ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_DISABLE);
+	if (ret)
+		goto exit;
+
+	return 0;
+
+err_spi:
+	ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_DISABLE);
+exit:
+	if (ret)
+		dev_err(&client->dev, "wait ps8640 rom idle fail: %d\n", ret);
+
+	return ret;
+}
+
+static int ps8640_spi_dl_mode(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[2];
+	int ret;
+
+	/* switch ps8640 mode to spi dl mode */
+	if (ps_bridge->gpio_mode_sel_n)
+		gpiod_set_value(ps_bridge->gpio_mode_sel_n, 0);
+
+	/* reset spi interface */
+	ret = ps8640_write_byte(client, PAGE2_SW_RESET,
+				SPI_SW_RESET | MPU_SW_RESET);
+	if (ret)
+		goto exit;
+
+	ret = ps8640_write_byte(client, PAGE2_SW_RESET, MPU_SW_RESET);
+	if (ret)
+		goto exit;
+
+exit:
+	if (ret)
+		dev_err(&client->dev, "fail reset spi interface: %d\n", ret);
+
+	return ret;
+}
+
+static int ps8640_rom_prepare(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[2];
+	struct device *dev = &client->dev;
+	u8 i, cmd[2];
+	int ret;
+
+	cmd[0] = WRITE_ENABLE_CMD;
+	ret = ps8640_spi_send_cmd(ps_bridge, cmd, 1);
+	if (ret) {
+		dev_err(dev, "failed enable-write-status-register: %d\n", ret);
+		return ret;
+	}
+
+	cmd[0] = WRITE_STATUS_REG_CMD;
+	cmd[1] = CLEAR_ALL_PROTECT;
+	ret = ps8640_spi_send_cmd(ps_bridge, cmd, 2);
+	if (ret) {
+		dev_err(dev, "fail disable all protection: %d\n", ret);
+		return ret;
+	}
+
+	/* wait for SPI module ready */
+	ret = ps8640_wait_rom_idle(ps_bridge);
+	if (ret) {
+		dev_err(dev, "fail wait rom idle: %d\n", ret);
+		return ret;
+	}
+
+	ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_ENABLE);
+	for (i = 0; i < 6; i++)
+		ps8640_write_byte(client, PAGE2_ENCTLSPI_WR, enc_ctrl_code[i]);
+	ps8640_write_byte(client, PAGE2_IROM_CTRL, IROM_DISABLE);
+
+	/* Enable-Write-Status-Register */
+	cmd[0] = WRITE_ENABLE_CMD;
+	ret = ps8640_spi_send_cmd(ps_bridge, cmd, 1);
+	if (ret) {
+		dev_err(dev, "fail enable-write-status-register: %d\n", ret);
+		return ret;
+	}
+
+	/* chip erase command */
+	cmd[0] = CHIP_ERASE_CMD;
+	ret = ps8640_spi_send_cmd(ps_bridge, cmd, 1);
+	if (ret) {
+		dev_err(dev, "fail disable all protection: %d\n", ret);
+		return ret;
+	}
+
+	ret = ps8640_wait_rom_idle(ps_bridge);
+	if (ret) {
+		dev_err(dev, "fail wait rom idle: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ps8640_check_chip_id(struct ps8640 *ps_bridge)
+{
+	struct i2c_client *client = ps_bridge->page[4];
+	u8 buf[4];
+
+	ps8640_read(client, PAGE4_REV_L, buf, 4);
+	return memcmp(buf, hw_chip_id, sizeof(buf));
+}
+
+static int ps8640_validate_firmware(struct ps8640 *ps_bridge,
+				    const struct firmware *fw)
+{
+	struct i2c_client *client = ps_bridge->page[0];
+	u16 fw_chip_id;
+
+	/*
+	 * Get the chip_id from the firmware. Make sure that it is the
+	 * right controller to do the firmware and config update.
+	 */
+	fw_chip_id = get_unaligned_le16(fw->data + FW_CHIP_ID_OFFSET);
+
+	if (fw_chip_id != 0x8640 && ps8640_check_chip_id(ps_bridge) == 0) {
+		dev_err(&client->dev,
+			"chip id mismatch: fw 0x%x vs. chip 0x8640\n",
+			fw_chip_id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ps8640_write_rom(struct ps8640 *ps_bridge, const struct firmware *fw)
+{
+	struct i2c_client *client = ps_bridge->page[0];
+	struct device *dev = &client->dev;
+	struct i2c_client *client2 = ps_bridge->page[2];
+	struct i2c_client *client7 = ps_bridge->page[7];
+	size_t pos;
+	u8 buf[257], rom_page_id_buf[3];
+	int ret;
+	u16 cpy_len;
+
+	ps8640_write_byte(client2, PAGE2_SPI_CFG3, I2C_TO_SPI_RESET);
+	msleep(100);
+	ps8640_write_byte(client2, PAGE2_SPI_CFG3, 0x00);
+
+	for (pos = 0; pos < fw->size; pos += cpy_len) {
+		rom_page_id_buf[0] = PAGE2_ROMADD_BYTE1;
+		rom_page_id_buf[1] = pos >> 8;
+		rom_page_id_buf[2] = pos >> 16;
+		ret = ps8640_write_bytes(client2, rom_page_id_buf, 3);
+		if (ret)
+			goto error;
+		cpy_len = fw->size >= 256 + pos ? 256 : fw->size - pos;
+		buf[0] = 0;
+		memcpy(buf + 1, fw->data + pos, cpy_len);
+		ret = ps8640_write_bytes(client7, buf, cpy_len + 1);
+		if (ret)
+			goto error;
+
+		dev_dbg(dev, "fw update completed %zu / %zu bytes\n", pos,
+			fw->size);
+	}
+	return 0;
+
+error:
+	dev_err(dev, "failed write external flash, %d\n", ret);
+	return ret;
+}
+
+static int ps8640_spi_normal_mode(struct ps8640 *ps_bridge)
+{
+	u8 cmd[2];
+	struct i2c_client *client = ps_bridge->page[2];
+
+	/* Enable-Write-Status-Register */
+	cmd[0] = WRITE_ENABLE_CMD;
+	ps8640_spi_send_cmd(ps_bridge, cmd, 1);
+
+	/* protect BPL/BP0/BP1 */
+	cmd[0] = WRITE_STATUS_REG_CMD;
+	cmd[1] = BLK_PROTECT_BITS | STATUS_REG_PROTECT;
+	ps8640_spi_send_cmd(ps_bridge, cmd, 2);
+
+	/* wait for SPI rom ready */
+	ps8640_wait_rom_idle(ps_bridge);
+
+	/* disable PS8640 mapping function */
+	ps8640_write_byte(client, PAGE2_ENCTLSPI_WR, 0x00);
+
+	if (ps_bridge->gpio_mode_sel_n)
+		gpiod_set_value(ps_bridge->gpio_mode_sel_n, 1);
+	return 0;
+}
+
+static int ps8640_enter_bl(struct ps8640 *ps_bridge)
+{
+	ps_bridge->in_fw_update = true;
+	return ps8640_spi_dl_mode(ps_bridge);
+}
+
+static void ps8640_exit_bl(struct ps8640 *ps_bridge, const struct firmware *fw)
+{
+	ps8640_spi_normal_mode(ps_bridge);
+	ps_bridge->in_fw_update = false;
+}
+
+static int ps8640_load_fw(struct ps8640 *ps_bridge, const struct firmware *fw)
+{
+	struct i2c_client *client = ps_bridge->page[0];
+	struct device *dev = &client->dev;
+	int ret;
+	bool ps8640_status_backup = ps_bridge->enabled;
+
+	ret = ps8640_validate_firmware(ps_bridge, fw);
+	if (ret)
+		return ret;
+
+	mutex_lock(&ps_bridge->fw_mutex);
+	if (!ps_bridge->in_fw_update) {
+		if (!ps8640_status_backup)
+			ps8640_pre_enable(&ps_bridge->bridge);
+
+		ret = ps8640_enter_bl(ps_bridge);
+		if (ret)
+			goto exit;
+	}
+
+	ret = ps8640_rom_prepare(ps_bridge);
+	if (ret)
+		goto exit;
+
+	ret = ps8640_write_rom(ps_bridge, fw);
+
+exit:
+	if (ret)
+		dev_err(dev, "Failed to load firmware, %d\n", ret);
+
+	ps8640_exit_bl(ps_bridge, fw);
+	if (!ps8640_status_backup)
+		ps8640_post_disable(&ps_bridge->bridge);
+	mutex_unlock(&ps_bridge->fw_mutex);
+	return ret;
+}
+
+static ssize_t ps8640_update_fw_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ps8640 *ps_bridge = i2c_get_clientdata(client);
+	const struct firmware *fw;
+	int error;
+
+	error = request_firmware(&fw, PS_FW_NAME, dev);
+	if (error) {
+		dev_err(dev, "Unable to open firmware %s: %d\n",
+			PS_FW_NAME, error);
+		return error;
+	}
+
+	error = ps8640_load_fw(ps_bridge, fw);
+	if (error)
+		dev_err(dev, "The firmware update failed(%d)\n", error);
+	else
+		dev_info(dev, "The firmware update succeeded\n");
+
+	release_firmware(fw);
+	return error ? error : count;
+}
+
+static DEVICE_ATTR(fw_version, S_IRUGO, ps8640_fw_version_show, NULL);
+static DEVICE_ATTR(hw_version, S_IRUGO, ps8640_hw_version_show, NULL);
+static DEVICE_ATTR(update_fw, S_IWUSR, NULL, ps8640_update_fw_store);
+
+static struct attribute *ps8640_attrs[] = {
+	&dev_attr_fw_version.attr,
+	&dev_attr_hw_version.attr,
+	&dev_attr_update_fw.attr,
+	NULL
+};
+
+static const struct attribute_group ps8640_attr_group = {
+	.attrs = ps8640_attrs,
+};
+
+static void ps8640_remove_sysfs_group(void *data)
+{
+	struct ps8640 *ps_bridge = data;
+
+	sysfs_remove_group(&ps_bridge->page[0]->dev.kobj, &ps8640_attr_group);
+}
+
+static int ps8640_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct ps8640 *ps_bridge;
+	struct device_node *np = dev->of_node;
+	struct device_node *port, *out_ep;
+	struct device_node *panel_node = NULL;
+	int ret;
+	u32 i;
+
+	ps_bridge = devm_kzalloc(dev, sizeof(*ps_bridge), GFP_KERNEL);
+	if (!ps_bridge)
+		return -ENOMEM;
+
+	/* port at 1 is ps8640 output port */
+	port = of_graph_get_port_by_id(np, 1);
+	if (port) {
+		out_ep = of_get_child_by_name(port, "endpoint");
+		of_node_put(port);
+		if (out_ep) {
+			panel_node = of_graph_get_remote_port_parent(out_ep);
+			of_node_put(out_ep);
+		}
+	}
+	if (panel_node) {
+		ps_bridge->panel = of_drm_find_panel(panel_node);
+		of_node_put(panel_node);
+		if (!ps_bridge->panel)
+			return -EPROBE_DEFER;
+	}
+
+	mutex_init(&ps_bridge->fw_mutex);
+	ps_bridge->v12 = devm_regulator_get(dev, "vdd12");
+	if (IS_ERR(ps_bridge->v12))
+		return PTR_ERR(ps_bridge->v12);
+
+	ps_bridge->v33 = devm_regulator_get(dev, "vdd33");
+	if (IS_ERR(ps_bridge->v33))
+		return PTR_ERR(ps_bridge->v33);
+
+	if (ret) {
+		dev_info(dev, "failed to get regulators: %d\n", ret);
+		return ret;
+	}
+
+	ps_bridge->gpio_mode_sel_n = devm_gpiod_get_optional(&client->dev,
+							     "mode-sel",
+							     GPIOD_OUT_HIGH);
+	if (IS_ERR(ps_bridge->gpio_mode_sel_n)) {
+		ret = PTR_ERR(ps_bridge->gpio_mode_sel_n);
+		dev_err(dev, "cannot get mode-sel %d\n", ret);
+		return ret;
+	}
+
+	ps_bridge->gpio_slp_n = devm_gpiod_get(&client->dev, "sleep",
+					       GPIOD_OUT_LOW);
+	if (IS_ERR(ps_bridge->gpio_slp_n)) {
+		ret = PTR_ERR(ps_bridge->gpio_slp_n);
+		dev_err(dev, "cannot get sleep: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Request the reset pin low to avoid the bridge being
+	 * initialized prematurely
+	 */
+	ps_bridge->gpio_rst_n = devm_gpiod_get(&client->dev, "reset",
+					       GPIOD_OUT_LOW);
+	if (IS_ERR(ps_bridge->gpio_rst_n)) {
+		ret = PTR_ERR(ps_bridge->gpio_rst_n);
+		dev_err(dev, "cannot get reset: %d\n", ret);
+		return ret;
+	}
+
+	ps_bridge->bridge.funcs = &ps8640_bridge_funcs;
+	ps_bridge->bridge.of_node = dev->of_node;
+
+	ps_bridge->page[0] = client;
+	ps_bridge->ddc_i2c = i2c_new_dummy(client->adapter, EDID_I2C_ADDR);
+	if (!ps_bridge->ddc_i2c) {
+		dev_err(dev, "failed ddc_i2c dummy device, address%02x\n",
+			EDID_I2C_ADDR);
+		return -EBUSY;
+	}
+	/*
+	 * ps8640 uses multiple addresses, use dummy devices for them
+	 * page[0]: for DP control
+	 * page[1]: for VIDEO Bridge
+	 * page[2]: for control top
+	 * page[3]: for DSI Link Control1
+	 * page[4]: for MIPI Phy
+	 * page[5]: for VPLL
+	 * page[6]: for DSI Link Control2
+	 * page[7]: for spi rom mapping
+	 */
+	for (i = 1; i < MAX_DEVS; i++) {
+		ps_bridge->page[i] = i2c_new_dummy(client->adapter,
+						   client->addr + i);
+		if (!ps_bridge->page[i]) {
+			dev_err(dev, "failed i2c dummy device, address%02x\n",
+				client->addr + i);
+			ret = -EBUSY;
+			goto exit_dummy;
+		}
+	}
+	i2c_set_clientdata(client, ps_bridge);
+
+	ret = sysfs_create_group(&client->dev.kobj, &ps8640_attr_group);
+	if (ret) {
+		dev_err(dev, "failed to create sysfs entries: %d\n", ret);
+		goto exit_dummy;
+	}
+
+	ret = devm_add_action(dev, ps8640_remove_sysfs_group, ps_bridge);
+	if (ret) {
+		dev_err(dev, "failed to add sysfs cleanup action: %d\n", ret);
+		goto exit_remove_sysfs;
+	}
+
+	ret = drm_bridge_add(&ps_bridge->bridge);
+	if (ret) {
+		dev_err(dev, "Failed to add bridge: %d\n", ret);
+		goto exit_remove_sysfs;
+	}
+	return 0;
+
+exit_remove_sysfs:
+	sysfs_remove_group(&ps_bridge->page[0]->dev.kobj, &ps8640_attr_group);
+exit_dummy:
+	while (--i)
+		i2c_unregister_device(ps_bridge->page[i]);
+	i2c_unregister_device(ps_bridge->ddc_i2c);
+	return ret;
+}
+
+static int ps8640_remove(struct i2c_client *client)
+{
+	struct ps8640 *ps_bridge = i2c_get_clientdata(client);
+	int i = MAX_DEVS;
+
+	drm_bridge_remove(&ps_bridge->bridge);
+	sysfs_remove_group(&ps_bridge->page[0]->dev.kobj, &ps8640_attr_group);
+	while (--i)
+			i2c_unregister_device(ps_bridge->page[i]);
+
+	i2c_unregister_device(ps_bridge->ddc_i2c);
+	return 0;
+}
+
+static const struct i2c_device_id ps8640_i2c_table[] = {
+	{ "parade,ps8640", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ps8640_i2c_table);
+
+static const struct of_device_id ps8640_match[] = {
+	{ .compatible = "parade,ps8640" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ps8640_match);
+
+static struct i2c_driver ps8640_driver = {
+	.id_table = ps8640_i2c_table,
+	.probe = ps8640_probe,
+	.remove = ps8640_remove,
+	.driver = {
+		.name = "parade,ps8640",
+		.of_match_table = ps8640_match,
+	},
+};
+module_i2c_driver(ps8640_driver);
+
+MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>");
+MODULE_AUTHOR("CK Hu <ck.hu@mediatek.com>");
+MODULE_DESCRIPTION("PARADE ps8640 DSI-eDP converter driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 4/8] drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (2 preceding siblings ...)
  2017-10-16 15:31 ` [RFC v2 3/8] drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 5/8] arm64: dts: mediatek: Add Elm Rev. 3 device tree Ulrich Hecht
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Ported from chromeos-3.18.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/gpu/drm/bridge/Kconfig            |   9 ++
 drivers/gpu/drm/bridge/Makefile           |   1 +
 drivers/gpu/drm/bridge/analogix-anx7688.c | 233 ++++++++++++++++++++++++++++++
 3 files changed, 243 insertions(+)
 create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index a1c0d95..712ac0a 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -38,6 +38,15 @@ config DRM_PARADE_PS8640
 	  The PS8640 is a high-performance and low-power
 	  MIPI DSI to eDP converter
 
+config DRM_ANALOGIX_ANX7688
+	tristate "Analogix ANX7688 bridge"
+	depends on DRM
+	select DRM_KMS_HELPER
+	---help---
+	  ANX7688 is a transmitter to support DisplayPort over USB-C for
+	  smartphone and tablets.
+	  This driver only supports the HDMI to DP component of the chip.
+
 config DRM_ANALOGIX_ANX78XX
 	tristate "Analogix ANX78XX bridge"
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index 6be8a9d..9cbf788 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -1,6 +1,7 @@
 ccflags-y := -Iinclude/drm
 
 obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o
+obj-$(CONFIG_DRM_ANALOGIX_ANX7688) += analogix-anx7688.o
 obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_GENERIC_GPIO_MUX) += generic-gpio-mux.o
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
diff --git a/drivers/gpu/drm/bridge/analogix-anx7688.c b/drivers/gpu/drm/bridge/analogix-anx7688.c
new file mode 100644
index 0000000..cc995c8
--- /dev/null
+++ b/drivers/gpu/drm/bridge/analogix-anx7688.c
@@ -0,0 +1,233 @@
+/*
+ * ANX7688 HDMI->DP bridge driver
+ *
+ * Copyright (C) 2016 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <drm/drm_crtc.h>
+
+/* Register addresses */
+#define VENDOR_ID_REG 0x00
+#define DEVICE_ID_REG 0x02
+
+#define FW_VERSION_REG 0x80
+
+#define DP_BANDWIDTH_REG 0x85
+#define DP_LANE_COUNT_REG 0x86
+
+#define VENDOR_ID 0x1f29
+#define DEVICE_ID 0x7688
+
+/* First supported firmware version (0.85) */
+#define MINIMUM_FW_VERSION 0x0085
+
+struct anx7688 {
+	struct drm_bridge bridge;
+	struct i2c_client *client;
+
+	bool filter;
+};
+
+static int anx7688_read(struct i2c_client *client, u8 reg, u8 *data,
+			u16 data_len)
+{
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = client->addr,
+		 .flags = 0,
+		 .len = 1,
+		 .buf = &reg,
+		 },
+		{
+		 .addr = client->addr,
+		 .flags = I2C_M_RD,
+		 .len = data_len,
+		 .buf = data,
+		 }
+	};
+
+	ret = i2c_transfer(client->adapter, msgs, 2);
+
+	if (ret == 2)
+		return 0;
+	if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static inline struct anx7688 *bridge_to_anx7688(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct anx7688, bridge);
+}
+
+static bool anx7688_bridge_mode_fixup(struct drm_bridge *bridge,
+				      const struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode)
+{
+	struct anx7688 *anx7688 = bridge_to_anx7688(bridge);
+	u8 regs[2];
+	u8 dpbw, lanecount;
+	int totalbw, requiredbw;
+	int ret;
+
+	if (!anx7688->filter)
+		return true;
+
+	/* Read both regs 0x85 (bandwidth) and 0x86 (lane count). */
+	ret = anx7688_read(anx7688->client, DP_BANDWIDTH_REG, regs, 2);
+	if (ret < 0) {
+		dev_err(&anx7688->client->dev,
+			"Failed to read bandwidth/lane count\n");
+		return false;
+	}
+	dpbw = regs[0];
+	lanecount = regs[1];
+
+	/* Maximum 0x19 bandwidth (6.75 Gbps Turbo mode), 2 lanes */
+	if (dpbw > 0x19 || lanecount > 2) {
+		dev_err(&anx7688->client->dev,
+			"Invalid bandwidth/lane count (%02x/%d)\n",
+			dpbw, lanecount);
+		return false;
+	}
+
+	/* Compute available bandwidth (kHz) */
+	totalbw = dpbw * lanecount * 270000 * 8 / 10;
+
+	/* Required bandwidth (8 bpc, kHz) */
+	requiredbw = mode->clock * 8 * 3;
+
+	dev_dbg(&anx7688->client->dev,
+		"DP bandwidth: %d kHz (%02x/%d); mode requires %d Khz\n",
+		totalbw, dpbw, lanecount, requiredbw);
+
+	if (totalbw == 0) {
+		dev_warn(&anx7688->client->dev,
+			 "Bandwidth/lane count are 0, not rejecting modes\n");
+		return true;
+	}
+
+	return totalbw >= requiredbw;
+}
+
+static const struct drm_bridge_funcs anx7688_bridge_funcs = {
+	.mode_fixup	= anx7688_bridge_mode_fixup,
+};
+
+static int anx7688_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct anx7688 *anx7688;
+	int ret;
+	u8 buffer[4];
+	u16 vendor, device, fwversion;
+
+	anx7688 = devm_kzalloc(&client->dev, sizeof(*anx7688), GFP_KERNEL);
+	if (!anx7688)
+		return -ENOMEM;
+
+#if IS_ENABLED(CONFIG_OF)
+	anx7688->bridge.of_node = client->dev.of_node;
+#endif
+
+	anx7688->client = client;
+	i2c_set_clientdata(client, anx7688);
+
+	/* Read both vendor and device id (4 bytes). */
+	ret = anx7688_read(client, VENDOR_ID_REG, buffer, 4);
+	if (ret) {
+		dev_err(&client->dev, "Failed to read chip vendor/device id\n");
+		return ret;
+	}
+
+	vendor = (u16)buffer[1] << 8 | buffer[0];
+	device = (u16)buffer[3] << 8 | buffer[2];
+	if (vendor != VENDOR_ID || device != DEVICE_ID) {
+		dev_err(&client->dev,
+			"Invalid vendor/device id %04x/%04x\n",
+			vendor, device);
+		return -ENODEV;
+	}
+
+	ret = anx7688_read(client, FW_VERSION_REG, buffer, 2);
+	if (ret) {
+		dev_err(&client->dev, "Failed to read firmware version\n");
+		return ret;
+	}
+
+	fwversion = (u16)buffer[0] << 8 | buffer[1];
+	dev_info(&client->dev, "ANX7688 firwmare version %02x.%02x\n",
+		 buffer[0], buffer[1]);
+
+	/* FW version >= 0.85 supports bandwidth/lane count registers */
+	if (fwversion >= MINIMUM_FW_VERSION) {
+		anx7688->filter = true;
+	} else {
+		/* Warn, but not fail, for backwards compatibility. */
+		dev_warn(&client->dev,
+			 "Old ANX7688 FW version (%02x.%02x), not filtering\n",
+			 buffer[0], buffer[1]);
+	}
+
+	anx7688->bridge.funcs = &anx7688_bridge_funcs;
+	ret = drm_bridge_add(&anx7688->bridge);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to add drm bridge\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int anx7688_i2c_remove(struct i2c_client *client)
+{
+	struct anx7688 *anx7688 = i2c_get_clientdata(client);
+
+	drm_bridge_remove(&anx7688->bridge);
+
+	return 0;
+}
+
+static const struct i2c_device_id anx7688_id[] = {
+	{ "anx7688", 0 },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(i2c, anx7688_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id anx7688_match_table[] = {
+	{ .compatible = "analogix,anx7688", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, anx7688_match_table);
+#endif
+
+static struct i2c_driver anx7688_driver = {
+	.driver = {
+		   .name = "anx7688",
+		   .of_match_table = of_match_ptr(anx7688_match_table),
+		  },
+	.probe = anx7688_i2c_probe,
+	.remove = anx7688_i2c_remove,
+	.id_table = anx7688_id,
+};
+
+module_i2c_driver(anx7688_driver);
+
+MODULE_DESCRIPTION("ANX7688 SlimPort Transmitter driver");
+MODULE_AUTHOR("Nicolas Boichat <drinkcat@chromium.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 5/8] arm64: dts: mediatek: Add Elm Rev. 3 device tree
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (3 preceding siblings ...)
  2017-10-16 15:31 ` [RFC v2 4/8] drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 6/8] hack: mediatek: get mmsys to register as both DRM and clock device Ulrich Hecht
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 arch/arm64/boot/dts/mediatek/Makefile            |    1 +
 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts |   21 +
 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi     |  210 +++++
 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi     | 1013 ++++++++++++++++++++++
 4 files changed, 1245 insertions(+)
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
 create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi

diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 151723b..0521e29 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-rev3.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts b/arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
new file mode 100644
index 0000000..68d4095
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016 MediaTek Inc.
+ * Author: Eddie Huang <eddie.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "mt8173-elm.dtsi"
+
+/ {
+	model = "Mediatek Elm rev3 board";
+	compatible = "google,elm-rev3", "google,elm", "mediatek,mt8173";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
new file mode 100644
index 0000000..850037f
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2016 MediaTek Inc.
+ * Author: Eddie Huang <eddie.huang@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mt8173-oak.dtsi"
+
+/ {
+	hdmicon: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&hdmi_mux_out_hdmi>;
+			};
+		};
+	};
+
+	hdmi_mux: hdmi_mux {
+		compatible = "gpio-display-mux";
+		status = "okay";
+		detect-gpios = <&pio 36 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_mux_pins>;
+		ddc-i2c-bus = <&hdmiddc0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port at 0 { /* input */
+				reg = <0>;
+
+				hdmi_mux_in: endpoint {
+					remote-endpoint = <&hdmi0_out>;
+				};
+			};
+
+			port at 1 { /* output */
+				reg = <1>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				hdmi_mux_out_anx: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&anx7688_in>;
+				};
+
+				hdmi_mux_out_hdmi: endpoint at 1 {
+					reg = <1>;
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+
+	sound: sound {
+		compatible = "mediatek,mt8173-rt5650";
+		mediatek,audio-codec = <&rt5650 &hdmi0>;
+		mediatek,mclk = <1>;
+		mediatek,platform = <&afe>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&aud_i2s2>;
+		codec-capture {
+			sound-dai = <&rt5650 1>;
+		};
+	};
+};
+
+&aud_i2s2 {
+	pins1 {
+		pinmux = <MT8173_PIN_128_I2S0_LRCK__FUNC_I2S1_WS>,
+			 <MT8173_PIN_129_I2S0_BCK__FUNC_I2S1_BCK>,
+			 <MT8173_PIN_130_I2S0_MCK__FUNC_I2S1_MCK>,
+			 <MT8173_PIN_131_I2S0_DATA0__FUNC_I2S1_DO_1>,
+			 <MT8173_PIN_12_EINT12__FUNC_I2S2_WS>,
+			 <MT8173_PIN_13_EINT13__FUNC_I2S2_BCK>,
+			 <MT8173_PIN_132_I2S0_DATA1__FUNC_I2S2_DI_2>;
+		bias-pull-down;
+	};
+};
+
+&cpu_thermal {
+	sustainable-power = <4500>; /* milliwatts */
+	trips {
+		threshold: trip-point at 0 {
+			temperature = <60000>;
+		};
+
+		target: trip-point at 1 {
+			temperature = <65000>;
+		};
+	};
+};
+
+&cros_ec {
+	i2c_tunnel_b: i2c-tunnel at 1 {
+		compatible = "google,cros-ec-i2c-tunnel";
+		google,remote-bus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		anx7688: anx7688 at 2c {
+			compatible = "analogix,anx7688";
+			status = "okay";
+			reg = <0x2c>;
+
+			port {
+				anx7688_in: endpoint {
+					remote-endpoint = <&hdmi_mux_out_anx>;
+				};
+			};
+		};
+	};
+};
+
+&hdmi0 {
+	status = "okay";
+
+	ports {
+		port at 1 {
+			reg = <1>;
+			hdmi0_out: endpoint {
+				remote-endpoint = <&hdmi_mux_in>;
+			};
+		};
+	};
+};
+
+&hdmi_phy {
+	status = "okay";
+	mediatek,ibias = <0xc>;
+};
+
+&i2c0 {
+	ps8640: edp-bridge at 8 {
+		compatible = "parade,ps8640";
+		reg = <0x8>;
+		sleep-gpios = <&pio 127 GPIO_ACTIVE_HIGH>;
+		reset-gpios = <&pio 115 GPIO_ACTIVE_HIGH>;
+		mode-sel-gpios = <&pio 92 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ps8640_pins>;
+		vdd12-supply = <&ps8640_fixed_1v2>;
+		vdd33-supply = <&mt6397_vgp2_reg>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 0 {
+			reg = <0>;
+
+			ps8640_in: endpoint {
+				remote-endpoint = <&dsi0_out>;
+			};
+		};
+
+		port at 1 {
+			reg = <1>;
+
+			ps8640_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
+
+&gpio_keys {
+	lid {
+		gpios = <&pio 69 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&mt6397_vgp6_reg {
+	regulator-always-on;
+};
+
+&pio {
+	hdmi_mux_pins: hdmi_mux_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_36_DAISYNC__FUNC_GPIO36>;
+		};
+	};
+};
+
+&ps8640_fixed_1v2 {
+	regulator-enable-ramp-delay = <2000>;
+};
+
+&rt5650 {
+	#sound-dai-cells = <1>;
+	realtek,dmic1-data-pin = <2>;
+	realtek,jd-mode = <2>;
+};
+
+
+&trackpad {
+	vcc-supply = <&mt6397_vgp6_reg>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
new file mode 100644
index 0000000..54a2500
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
@@ -0,0 +1,1013 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "mt8173.dtsi"
+#include "mt8173-pinfunc.h"
+
+/ {
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+	};
+
+	memory at 40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x80000000>;
+	};
+
+	backlight_lcd: backlight_lcd {
+		compatible = "pwm-backlight";
+		pwms = <&pwm0 0 1000000>;
+		brightness-levels = <
+			  0  16  32  48  64  80  96 112
+			128 144 160 176 192 208 224 240
+			255
+		>;
+		default-brightness-level = <9>;
+		power-supply = <&bl_fixed_reg>;
+		enable-gpios = <&pio 95 GPIO_ACTIVE_HIGH>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&disp_pwm0_pins>;
+		status = "okay";
+	};
+
+	bl_fixed_reg: fixedregulator at 2 {
+		compatible = "regulator-fixed";
+		regulator-name = "bl_fixed";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us = <1000>;
+		enable-active-high;
+		gpio = <&pio 32 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_fixed_pins>;
+	};
+
+	chosen {
+		linux,stdout-path = &uart0;
+	};
+
+	firmware {
+		chromeos {
+			pinctrl-names = "default";
+			pinctrl-0 = <&chromeos_write_protect>;
+			write-protect-gpio = <&pio 4 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio_keys: gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_keys_pins>;
+
+		lid {
+			label = "Lid";
+			gpios = <&pio 12 GPIO_ACTIVE_LOW>;
+			linux,code = <0>; /* SW_LID */
+			linux,input-type = <5>; /* EV_SW */
+			gpio-key,wakeup;
+		};
+
+		power {
+			label = "Power";
+			gpios = <&pio 14 GPIO_ACTIVE_HIGH>;
+			linux,code = <KEY_POWER>;
+			debounce-interval = <30>;
+			gpio-key,wakeup;
+		};
+
+		tablet_mode {
+			label = "Tablet_mode";
+			gpios = <&pio 121 GPIO_ACTIVE_HIGH>;
+			linux,code = <1>; /* SW_TABLET_MODE */
+			linux,input-type = <5>; /* EV_SW */
+			gpio-key,wakeup;
+		};
+
+		volume_down {
+			label = "Volume_down";
+			gpios = <&pio 123 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+
+		volume_up {
+			label = "Volume_up";
+			gpios = <&pio 124 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+	};
+
+	panel: panel {
+		compatible = "lg,lp120up1";
+		power-supply = <&panel_fixed_3v3>;
+		ddc-i2c-bus = <&i2c4>;
+		backlight = <&backlight_lcd>;
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&ps8640_out>;
+			};
+		};
+	};
+
+	panel_fixed_3v3: regulator at 1 {
+		compatible = "regulator-fixed";
+		regulator-name = "PANEL_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		gpio = <&pio 41 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&panel_fixed_pins>;
+	};
+
+	ps8640_fixed_1v2: regulator at 2 {
+		compatible = "regulator-fixed";
+		regulator-name = "PS8640_1V2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		enable-active-high;
+		regulator-boot-on;
+		gpio = <&pio 30 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ps8640_fixed_pins>;
+	};
+
+	sdio_fixed_3v3: fixedregulator at 0 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&pio 85 GPIO_ACTIVE_HIGH>;
+	};
+
+	usb_p1_vbus: regulator at 3 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	usb_p0_vbus: regulator at 4 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 9 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&cec {
+	status = "okay";
+};
+
+&cpu0 {
+	proc-supply = <&mt6397_vpca15_reg>;
+};
+
+&cpu1 {
+	proc-supply = <&mt6397_vpca15_reg>;
+};
+
+&cpu2 {
+	proc-supply = <&da9211_vcpu_reg>;
+	sram-supply = <&mt6397_vsramca7_reg>;
+};
+
+&cpu3 {
+	proc-supply = <&da9211_vcpu_reg>;
+	sram-supply = <&mt6397_vsramca7_reg>;
+};
+
+&cpu_thermal {
+	sustainable-power = <5000>; /* milliwatts */
+};
+
+&dsi0 {
+	status = "okay";
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port at 1 {
+			reg = <1>;
+
+			dsi0_out: endpoint {
+				remote-endpoint = <&ps8640_in>;
+			};
+		};
+	};
+};
+
+&dpi0 {
+	status = "okay";
+};
+
+&hdmi_phy {
+	status = "okay";
+	mediatek,ibias = <0x3f>;
+};
+
+&i2c0 {
+	status = "okay";
+
+	rt5650: audio-codec at 1a {
+		compatible = "realtek,rt5650";
+		reg = <0x1a>;
+		avdd-supply = <&mt6397_vgp1_reg>;
+		cpvdd-supply = <&mt6397_vcama_reg>;
+		interrupt-parent = <&pio>;
+		interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&rt5650_irq>;
+		realtek,jd-mode = <3>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <1500000>;
+	status = "okay";
+
+	da9211: da9211 at 68 {
+		compatible = "dlg,da9211";
+		reg = <0x68>;
+
+		regulators {
+			da9211_vcpu_reg: BUCKA {
+				regulator-name = "VBUCKA";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1310000>;
+				regulator-min-microamp  = <2000000>;
+				regulator-max-microamp  = <4400000>;
+				regulator-ramp-delay = <10000>;
+				regulator-always-on;
+/*				regulator-supported-modes =
+					<REGULATOR_OPERATION_MODE_FAST
+					 REGULATOR_OPERATION_MODE_NORMAL>;*/
+			};
+
+			da9211_vgpu_reg: BUCKB {
+				regulator-name = "VBUCKB";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1310000>;
+				regulator-min-microamp  = <2000000>;
+				regulator-max-microamp  = <3000000>;
+				regulator-ramp-delay = <10000>;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+
+	tpm: tpm at 20 {
+		compatible = "infineon,slb9645tt";
+		reg = <0x20>;
+		powered-while-suspended;
+	};
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	touchscreen: touchscreen at 10 {
+		compatible = "elan,ekth3500";
+		reg = <0x10>;
+		interrupt-parent = <&pio>;
+		interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c4 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	trackpad: trackpad at 15 {
+		compatible = "elan,ekth3000";
+		interrupt-parent = <&pio>;
+		interrupts = <117 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&trackpad_irq>;
+		reg = <0x15>;
+		wakeup-source;
+	};
+};
+
+&mipi_tx0 {
+	status = "okay";
+};
+
+&mmc0 {
+	status = "okay";
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc0_pins_default>;
+	pinctrl-1 = <&mmc0_pins_uhs>;
+	bus-width = <8>;
+	max-frequency = <50000000>;
+	cap-mmc-highspeed;
+	mediatek,hs200-cmd-int-delay=<26>;
+	mediatek,hs400-cmd-int-delay=<14>;
+	mediatek,hs400-cmd-resp-sel-rising;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	cap-mmc-hw-reset;
+	hs400-ds-delay = <0x14015>;
+	vmmc-supply = <&mt6397_vemc_3v3_reg>;
+	vqmmc-supply = <&mt6397_vio18_reg>;
+	assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>;
+	assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>;
+	non-removable;
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc1_pins_default>;
+	pinctrl-1 = <&mmc1_pins_uhs>;
+	bus-width = <4>;
+	max-frequency = <50000000>;
+	cap-sd-highspeed;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	vmmc-supply = <&mt6397_vmch_reg>;
+	vqmmc-supply = <&mt6397_vmc_reg>;
+};
+
+&mmc3 {
+	status = "okay";
+	pinctrl-names = "default", "state_uhs";
+	pinctrl-0 = <&mmc3_pins_default>;
+	pinctrl-1 = <&mmc3_pins_uhs>;
+	bus-width = <4>;
+	max-frequency = <200000000>;
+	cap-sd-highspeed;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
+	sdr104-clk-delay = <5>;
+	keep-power-in-suspend;
+	enable-sdio-wakeup;
+	cap-sdio-irq;
+	vmmc-supply = <&sdio_fixed_3v3>;
+	vqmmc-supply = <&mt6397_vgp3_reg>;
+	non-removable;
+	cap-power-off-card;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	btmrvl: btmrvl at 2 {
+		compatible = "marvell,sd8897-bt";
+		reg = <2>;
+		interrupt-parent = <&pio>;
+		interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
+		marvell,wakeup-pin = /bits/ 16 <0x0d>;
+		marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
+	};
+
+	mwifiex: mwifiex at 1 {
+		compatible = "marvell,sd8897";
+		reg = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
+		marvell,wakeup-pin = <3>;
+		marvell,caldata_ed_mac = /bits/ 8 <
+0x01 0x00 0x07 0x00 0x14 0x00 0x01 0x00 0x00 0x00 0x12 0x00 0x02 0x00 0x01 0x00
+0x01 0x00 0x00 0x00 0x12 0x00 0x02 0x00 0x01 0x00
+                >;
+	};
+};
+
+&nor_flash {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nor_gpio1_pins>;
+	bus-width = <8>;
+	max-frequency = <50000000>;
+	non-removable;
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+	};
+};
+
+&pio {
+	aud_i2s2: aud_i2s2 {
+		pins1 {
+			pinmux = <MT8173_PIN_128_I2S0_LRCK__FUNC_I2S1_WS>,
+				 <MT8173_PIN_129_I2S0_BCK__FUNC_I2S1_BCK>,
+				 <MT8173_PIN_130_I2S0_MCK__FUNC_I2S1_MCK>,
+				 <MT8173_PIN_131_I2S0_DATA0__FUNC_I2S1_DO_1>,
+				 <MT8173_PIN_116_UCTS0__FUNC_I2S2_DI_1>,
+				 <MT8173_PIN_132_I2S0_DATA1__FUNC_I2S2_DI_2>;
+			bias-pull-down;
+		};
+	};
+
+	bl_fixed_pins: bl_fixed_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_32_UTXD2__FUNC_GPIO32>;
+			output-low;
+		};
+	};
+
+	bt_wake_pins: bt_wake_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_119_KPROW0__FUNC_GPIO119>;
+			bias-pull-up;
+		};
+	};
+
+	chromeos_write_protect: chromeos_write_protect {
+		pins1 {
+			pinmux = <MT8173_PIN_4_EINT4__FUNC_GPIO4>;
+			bias-disable;
+		};
+	};
+
+	disp_pwm0_pins: disp_pwm0_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_87_DISP_PWM0__FUNC_DISP_PWM0>;
+			output-low;
+		};
+	};
+
+	gpio_keys_pins: gpio_keys_pins {
+		volume_pins {
+			pinmux = <MT8173_PIN_123_KPCOL1__FUNC_GPIO123>,
+				 <MT8173_PIN_124_KPCOL2__FUNC_GPIO124>;
+			bias-pull-up;
+		};
+
+		tablet_mode_pins {
+			pinmux = <MT8173_PIN_121_KPROW2__FUNC_GPIO121>;
+			bias-pull-up;
+		};
+	};
+
+	mmc0_pins_default: mmc0default {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_57_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
+				 <MT8173_PIN_58_MSDC0_DAT1__FUNC_MSDC0_DAT1>,
+				 <MT8173_PIN_59_MSDC0_DAT2__FUNC_MSDC0_DAT2>,
+				 <MT8173_PIN_60_MSDC0_DAT3__FUNC_MSDC0_DAT3>,
+				 <MT8173_PIN_61_MSDC0_DAT4__FUNC_MSDC0_DAT4>,
+				 <MT8173_PIN_62_MSDC0_DAT5__FUNC_MSDC0_DAT5>,
+				 <MT8173_PIN_63_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
+				 <MT8173_PIN_64_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
+				 <MT8173_PIN_66_MSDC0_CMD__FUNC_MSDC0_CMD>;
+				bias-pull-up;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_65_MSDC0_CLK__FUNC_MSDC0_CLK>;
+				bias-pull-down;
+		};
+
+		pins_rst {
+			pinmux = <MT8173_PIN_68_MSDC0_RST___FUNC_MSDC0_RSTB>;
+			bias-pull-up;
+		};
+	};
+
+	mmc1_pins_default: mmc1default {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_73_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+				 <MT8173_PIN_74_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+				 <MT8173_PIN_75_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+				 <MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+				 <MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK>;
+			bias-pull-down;
+			drive-strength = <MTK_DRIVE_4mA>;
+		};
+
+		pins_insert {
+			pinmux = <MT8173_PIN_1_EINT1__FUNC_GPIO1>;
+			bias-pull-up;
+		};
+	};
+
+	mmc3_pins_default: mmc3default {
+		pins_dat {
+			pinmux = <MT8173_PIN_22_MSDC3_DAT0__FUNC_MSDC3_DAT0>,
+				 <MT8173_PIN_23_MSDC3_DAT1__FUNC_MSDC3_DAT1>,
+				 <MT8173_PIN_24_MSDC3_DAT2__FUNC_MSDC3_DAT2>,
+				 <MT8173_PIN_25_MSDC3_DAT3__FUNC_MSDC3_DAT3>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_cmd {
+			pinmux = <MT8173_PIN_27_MSDC3_CMD__FUNC_MSDC3_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_26_MSDC3_CLK__FUNC_MSDC3_CLK>;
+			bias-pull-down;
+			drive-strength = <MTK_DRIVE_8mA>;
+		};
+
+		pins_pdn {
+			pinmux = <MT8173_PIN_85_AUD_DAT_MOSI__FUNC_GPIO85>;
+			output-low;
+		};
+	};
+
+	mmc0_pins_uhs: mmc0 {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_57_MSDC0_DAT0__FUNC_MSDC0_DAT0>,
+				 <MT8173_PIN_58_MSDC0_DAT1__FUNC_MSDC0_DAT1>,
+				 <MT8173_PIN_59_MSDC0_DAT2__FUNC_MSDC0_DAT2>,
+				 <MT8173_PIN_60_MSDC0_DAT3__FUNC_MSDC0_DAT3>,
+				 <MT8173_PIN_61_MSDC0_DAT4__FUNC_MSDC0_DAT4>,
+				 <MT8173_PIN_62_MSDC0_DAT5__FUNC_MSDC0_DAT5>,
+				 <MT8173_PIN_63_MSDC0_DAT6__FUNC_MSDC0_DAT6>,
+				 <MT8173_PIN_64_MSDC0_DAT7__FUNC_MSDC0_DAT7>,
+				 <MT8173_PIN_66_MSDC0_CMD__FUNC_MSDC0_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_65_MSDC0_CLK__FUNC_MSDC0_CLK>;
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		pins_ds {
+			pinmux = <MT8173_PIN_67_MSDC0_DSL__FUNC_MSDC0_DSL>;
+			drive-strength = <MTK_DRIVE_10mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
+		};
+
+		pins_rst {
+			pinmux = <MT8173_PIN_68_MSDC0_RST___FUNC_MSDC0_RSTB>;
+			bias-pull-up;
+		};
+	};
+
+	mmc1_pins_uhs: mmc1 {
+		pins_cmd_dat {
+			pinmux = <MT8173_PIN_73_MSDC1_DAT0__FUNC_MSDC1_DAT0>,
+				 <MT8173_PIN_74_MSDC1_DAT1__FUNC_MSDC1_DAT1>,
+				 <MT8173_PIN_75_MSDC1_DAT2__FUNC_MSDC1_DAT2>,
+				 <MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3>,
+				 <MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_6mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK>;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+	};
+
+	mmc3_pins_uhs: mmc3 {
+		pins_dat {
+			pinmux = <MT8173_PIN_22_MSDC3_DAT0__FUNC_MSDC3_DAT0>,
+				 <MT8173_PIN_23_MSDC3_DAT1__FUNC_MSDC3_DAT1>,
+				 <MT8173_PIN_24_MSDC3_DAT2__FUNC_MSDC3_DAT2>,
+				 <MT8173_PIN_25_MSDC3_DAT3__FUNC_MSDC3_DAT3>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_cmd {
+			pinmux = <MT8173_PIN_27_MSDC3_CMD__FUNC_MSDC3_CMD>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_26_MSDC3_CLK__FUNC_MSDC3_CLK>;
+			drive-strength = <MTK_DRIVE_8mA>;
+			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+		};
+	};
+
+	nor_gpio1_pins: nor {
+		pins1 {
+			pinmux = <MT8173_PIN_6_EINT6__FUNC_SFCS0>,
+				 <MT8173_PIN_7_EINT7__FUNC_SFHOLD>,
+				 <MT8173_PIN_8_EINT8__FUNC_SFIN>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up;
+		};
+
+		pins2 {
+			pinmux = <MT8173_PIN_5_EINT5__FUNC_SFOUT>;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up;
+		};
+
+		pins_clk {
+			pinmux = <MT8173_PIN_9_EINT9__FUNC_SFCK>;
+			input-enable;
+			drive-strength = <MTK_DRIVE_4mA>;
+			bias-pull-up;
+		};
+	};
+
+	panel_fixed_pins: panel_fixed_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_41_CMMCLK__FUNC_GPIO41>;
+		};
+	};
+
+	ps8640_pins: ps8640_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_92_PCM_CLK__FUNC_GPIO92>,
+				 <MT8173_PIN_115_URTS0__FUNC_GPIO115>,
+				 <MT8173_PIN_127_LCM_RST__FUNC_GPIO127>;
+		};
+	};
+
+	ps8640_fixed_pins: ps8640_fixed_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_30_URTS2__FUNC_GPIO30>;
+		};
+	};
+
+	rt5650_irq: rt5650_irq {
+		pins1 {
+			pinmux = <MT8173_PIN_3_EINT3__FUNC_GPIO3>;
+			bias-pull-down;
+		};
+	};
+
+	spi_pins_a: spi1 {
+		pins1 {
+			pinmux = <MT8173_PIN_0_EINT0__FUNC_GPIO0>;
+			bias-pull-up;
+		};
+
+		pins_spi {
+			pinmux = <MT8173_PIN_102_MSDC2_DAT2__FUNC_SPI_CK_1_>,
+				 <MT8173_PIN_103_MSDC2_DAT3__FUNC_SPI_MI_1_>,
+				 <MT8173_PIN_104_MSDC2_CLK__FUNC_SPI_MO_1_>,
+				 <MT8173_PIN_105_MSDC2_CMD__FUNC_SPI_CS_1_>;
+			bias-disable;
+		};
+	};
+
+	trackpad_irq: trackpad_irq {
+		pins1 {
+			pinmux = <MT8173_PIN_117_URXD3__FUNC_GPIO117>;
+			input-enable;
+			bias-pull-up;
+		};
+	};
+
+	usb_pins: usb at 0 {
+		pins1 {
+			pinmux = <MT8173_PIN_101_MSDC2_DAT1__FUNC_GPIO101>;
+			output-high;
+			bias-disable;
+		};
+	};
+
+	usb_id_pins_float: usb_iddig_pull_up {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-up;
+		};
+	};
+
+	usb_id_pins_ground: usb_iddig_pull_down {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-down;
+		};
+	};
+
+	wifi_wake_pins: wifi_wake_pins {
+		pins1 {
+			pinmux = <MT8173_PIN_38_CONN_RST__FUNC_GPIO38>;
+			bias-pull-up;
+		};
+	};
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&pwrap {
+	pmic: mt6397 {
+		compatible = "mediatek,mt6397";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <11 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		syscfg_pctl_pmic: syscfg_pctl_pmic at c000 {
+			compatible = "mediatek,mt6397-pctl-pmic-syscfg",
+				     "syscon";
+			reg = <0 0x0000c000 0 0x0108>;
+		};
+
+		pio6397: pinctrl at c000 {
+			compatible = "mediatek,mt6397-pinctrl";
+			pins-are-numbered;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		mt6397clock: mt6397clock {
+			compatible = "mediatek,mt6397-clk";
+			#clock-cells = <1>;
+		};
+
+		mt6397regulator: mt6397regulator {
+			compatible = "mediatek,mt6397-regulator";
+
+			mt6397_vpca15_reg: buck_vpca15 {
+				regulator-compatible = "buck_vpca15";
+				regulator-name = "vpca15";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+/*				regulator-supported-modes =
+					<REGULATOR_OPERATION_MODE_FAST
+					 REGULATOR_OPERATION_MODE_NORMAL>;*/
+			};
+
+			mt6397_vpca7_reg: buck_vpca7 {
+				regulator-compatible = "buck_vpca7";
+				regulator-name = "vpca7";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-enable-ramp-delay = <115>;
+				regulator-always-on;
+			};
+
+			mt6397_vsramca15_reg: buck_vsramca15 {
+				regulator-compatible = "buck_vsramca15";
+				regulator-name = "vsramca15";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vsramca7_reg: buck_vsramca7 {
+				regulator-compatible = "buck_vsramca7";
+				regulator-name = "vsramca7";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vcore_reg: buck_vcore {
+				regulator-compatible = "buck_vcore";
+				regulator-name = "vcore";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vgpu_reg: buck_vgpu {
+				regulator-compatible = "buck_vgpu";
+				regulator-name = "vgpu";
+				regulator-min-microvolt = < 700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-ramp-delay = <12500>;
+				regulator-enable-ramp-delay = <115>;
+			};
+
+			mt6397_vdrm_reg: buck_vdrm {
+				regulator-compatible = "buck_vdrm";
+				regulator-name = "vdrm";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vio18_reg: buck_vio18 {
+				regulator-compatible = "buck_vio18";
+				regulator-name = "vio18";
+				regulator-min-microvolt = <1620000>;
+				regulator-max-microvolt = <1980000>;
+				regulator-ramp-delay = <12500>;
+				regulator-always-on;
+			};
+
+			mt6397_vtcxo_reg: ldo_vtcxo {
+				regulator-compatible = "ldo_vtcxo";
+				regulator-name = "vtcxo";
+				regulator-always-on;
+			};
+
+			mt6397_va28_reg: ldo_va28 {
+				regulator-compatible = "ldo_va28";
+				regulator-name = "va28";
+			};
+
+			mt6397_vcama_reg: ldo_vcama {
+				regulator-compatible = "ldo_vcama";
+				regulator-name = "vcama";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vio28_reg: ldo_vio28 {
+				regulator-compatible = "ldo_vio28";
+				regulator-name = "vio28";
+				regulator-always-on;
+			};
+
+			mt6397_vusb_reg: ldo_vusb {
+				regulator-compatible = "ldo_vusb";
+				regulator-name = "vusb";
+			};
+
+			mt6397_vmc_reg: ldo_vmc {
+				regulator-compatible = "ldo_vmc";
+				regulator-name = "vmc";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vmch_reg: ldo_vmch {
+				regulator-compatible = "ldo_vmch";
+				regulator-name = "vmch";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vemc_3v3_reg: ldo_vemc3v3 {
+				regulator-compatible = "ldo_vemc3v3";
+				regulator-name = "vemc_3v3";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp1_reg: ldo_vgp1 {
+				regulator-compatible = "ldo_vgp1";
+				regulator-name = "vcamd";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-enable-ramp-delay = <240>;
+			};
+
+			mt6397_vgp2_reg: ldo_vgp2 {
+				regulator-compatible = "ldo_vgp2";
+				regulator-name = "vcamio";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp3_reg: ldo_vgp3 {
+				regulator-compatible = "ldo_vgp3";
+				regulator-name = "vcamaf";
+				regulator-min-microvolt = <1620000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp4_reg: ldo_vgp4 {
+				regulator-compatible = "ldo_vgp4";
+				regulator-name = "vgp4";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp5_reg: ldo_vgp5 {
+				regulator-compatible = "ldo_vgp5";
+				regulator-name = "vgp5";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vgp6_reg: ldo_vgp6 {
+				regulator-compatible = "ldo_vgp6";
+				regulator-name = "vgp6";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+
+			mt6397_vibr_reg: ldo_vibr {
+				regulator-compatible = "ldo_vibr";
+				regulator-name = "vibr";
+				regulator-min-microvolt = <1300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <218>;
+			};
+		};
+	};
+};
+
+&scpsys {
+	mfg_async-supply = <&da9211_vgpu_reg>;
+};
+
+&spi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi_pins_a>;
+	mediatek,pad-select = <1>;
+	status = "okay";
+	/* clients */
+	cros_ec: ec at 0 {
+		compatible = "google,cros-ec-spi";
+		reg = <0x0>;
+		spi-max-frequency = <12000000>;
+		interrupt-parent = <&pio>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		google,cros-ec-spi-msg-delay = <500>;
+
+		i2c_tunnel: i2c-tunnel at 0 {
+			compatible = "google,cros-ec-i2c-tunnel";
+			google,remote-bus = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			battery: sbs-battery at b {
+				compatible = "sbs,sbs-battery";
+				reg = <0xb>;
+				sbs,i2c-retry-count = <2>;
+				sbs,poll-retry-count = <1>;
+			};
+		};
+	};
+};
+
+&thermal {
+	bank0-supply = <&mt6397_vpca15_reg>;
+	bank1-supply = <&da9211_vcpu_reg>;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&ssusb {
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+//	extcon = <&extcon_usb>;
+	dr_mode = "host";
+	mediatek,enable-wakeup;
+	pinctrl-names = "default", "id_float", "id_ground";
+//	pinctrl-0 = <&usb_pins>;
+	pinctrl-0 = <&usb_id_pins_float>;
+	pinctrl-1 = <&usb_id_pins_float>;
+	pinctrl-2 = <&usb_id_pins_ground>;
+	status = "okay";
+};
+
+&usb_host {
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p1_vbus>;
+	status = "okay";
+};
+
+#include "../../../../arm/boot/dts/cros-ec-keyboard.dtsi"
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 6/8] hack: mediatek: get mmsys to register as both DRM and clock device
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (4 preceding siblings ...)
  2017-10-16 15:31 ` [RFC v2 5/8] arm64: dts: mediatek: Add Elm Rev. 3 device tree Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-16 15:31 ` [RFC v2 7/8] drm/mediatek: Add DRM-based framebuffer device Ulrich Hecht
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

"mediatek,mt8173-mmsys" is the compatible string for both a clock controller
and a DRM device. The assumption seems to be that all compatible strings
trigger, and that mmsys will be registered as two devices.
This does work in the 3.18 vendor kernel, but it is not what happens in
mainline: only the clock portion is probed.

This hack probes the clocks from mtk_drm_probe(), and has all drivers
that need these clocks defer instead of fail. Fixes DRM initialization
on Acer Chromebook R13.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/clk/mediatek/clk-mt8173.c      | 4 ++--
 drivers/gpu/drm/mediatek/mtk_dpi.c     | 5 +++--
 drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 5 +++--
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 7 +++++++
 drivers/gpu/drm/mediatek/mtk_hdmi.c    | 5 +++--
 5 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 96c292c..9339d2c 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -1152,7 +1152,7 @@ static void __init mtk_imgsys_init(struct device_node *node)
 }
 CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init);
 
-static void __init mtk_mmsys_init(struct device_node *node)
+/*static*/ void /*__init*/ mtk_mmsys_init(struct device_node *node)
 {
 	struct clk_onecell_data *clk_data;
 	int r;
@@ -1167,7 +1167,7 @@ static void __init mtk_mmsys_init(struct device_node *node)
 		pr_err("%s(): could not register clock provider: %d\n",
 			__func__, r);
 }
-CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt8173-mmsys", mtk_mmsys_init);
+//CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt8173-mmsys", mtk_mmsys_init);
 
 static void __init mtk_vdecsys_init(struct device_node *node)
 {
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index e80a603..ed999891 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -682,8 +682,9 @@ static int mtk_dpi_probe(struct platform_device *pdev)
 	dpi->engine_clk = devm_clk_get(dev, "engine");
 	if (IS_ERR(dpi->engine_clk)) {
 		ret = PTR_ERR(dpi->engine_clk);
-		dev_err(dev, "Failed to get engine clock: %d\n", ret);
-		return ret;
+		dev_err(dev, "Failed to get engine clock: %d, deferring\n", ret);
+		return -EPROBE_DEFER;
+		//return ret;
 	}
 
 	dpi->pixel_clk = devm_clk_get(dev, "pixel");
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 8130f3d..465ee60 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -382,8 +382,9 @@ static int mtk_ddp_probe(struct platform_device *pdev)
 
 	ddp->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(ddp->clk)) {
-		dev_err(dev, "Failed to get clock\n");
-		return PTR_ERR(ddp->clk);
+		dev_err(dev, "Failed to get clock, deferring\n");
+		return -EPROBE_DEFER;
+		//return PTR_ERR(ddp->clk);
 	}
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index a2ca90f..ce99921 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -381,6 +381,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
 	{ }
 };
 
+static int hack_mmsys_inited;
+void mtk_mmsys_init(struct device_node *node);
 static int mtk_drm_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -391,6 +393,11 @@ static int mtk_drm_probe(struct platform_device *pdev)
 	int ret;
 	int i;
 
+	if (!hack_mmsys_inited) {
+		mtk_mmsys_init(dev->of_node);
+		hack_mmsys_inited = 1;
+	}
+
 	private = devm_kzalloc(dev, sizeof(*private), GFP_KERNEL);
 	if (!private)
 		return -ENOMEM;
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 690c675..715c0e0 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1441,8 +1441,9 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
 
 	ret = mtk_hdmi_get_all_clk(hdmi, np);
 	if (ret) {
-		dev_err(dev, "Failed to get clocks: %d\n", ret);
-		return ret;
+		dev_err(dev, "Failed to get clocks: %d, deferring\n", ret);
+		return -EPROBE_DEFER;
+		//return ret;
 	}
 
 	/* The CEC module handles HDMI hotplug detection */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 7/8] drm/mediatek: Add DRM-based framebuffer device
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (5 preceding siblings ...)
  2017-10-16 15:31 ` [RFC v2 6/8] hack: mediatek: get mmsys to register as both DRM and clock device Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-17  9:04   ` Philipp Zabel
  2017-10-16 15:31 ` [RFC v2 8/8] drm: mediatek: Fix drm_of_find_panel_or_bridge conversion Ulrich Hecht
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Add fbdev support to the Mediatek DRM driver.

Signed-off-by: CK Hu <ck.hu@mediatek.com>
Signed-off-by: YT Shen <yt.shen@mediatek.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
[uli: Forward-ported from chromeos-3.18 vendor kernel.]
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/gpu/drm/mediatek/Makefile        |   2 +
 drivers/gpu/drm/mediatek/mtk_drm_drv.c   |   8 ++
 drivers/gpu/drm/mediatek/mtk_drm_drv.h   |   4 +-
 drivers/gpu/drm/mediatek/mtk_drm_fb.c    |  13 +++
 drivers/gpu/drm/mediatek/mtk_drm_fb.h    |   3 +
 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c | 181 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h |  32 ++++++
 7 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h

diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index e37b55a..8306fb5 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -12,6 +12,8 @@ mediatek-drm-y := mtk_disp_color.o \
 		  mtk_mipi_tx.o \
 		  mtk_dpi.o
 
+mediatek-drm-$(CONFIG_DRM_FBDEV_EMULATION) += mtk_drm_fbdev.o
+
 obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
 
 mediatek-drm-hdmi-objs := mtk_cec.o \
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index ce99921..636b8db 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -30,6 +30,7 @@
 #include "mtk_drm_ddp_comp.h"
 #include "mtk_drm_drv.h"
 #include "mtk_drm_fb.h"
+#include "mtk_drm_fbdev.h"
 #include "mtk_drm_gem.h"
 
 #define DRIVER_NAME "mediatek"
@@ -257,8 +258,14 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 	drm_kms_helper_poll_init(drm);
 	drm_mode_config_reset(drm);
 
+	ret = mtk_fbdev_init(drm);
+	if (ret)
+		goto err_kms_helper_poll_fini;
+
 	return 0;
 
+err_kms_helper_poll_fini:
+	drm_kms_helper_poll_fini(drm);
 err_component_unbind:
 	component_unbind_all(drm->dev, drm);
 err_config_cleanup:
@@ -269,6 +276,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
 
 static void mtk_drm_kms_deinit(struct drm_device *drm)
 {
+	mtk_fbdev_fini(drm);
 	drm_kms_helper_poll_fini(drm);
 
 	component_unbind_all(drm->dev, drm);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
index c3378c4..4edc002 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
@@ -14,6 +14,7 @@
 #ifndef MTK_DRM_DRV_H
 #define MTK_DRM_DRV_H
 
+#include <drm/drm_fb_helper.h>
 #include <linux/io.h>
 #include "mtk_drm_ddp_comp.h"
 
@@ -24,7 +25,6 @@ struct device;
 struct device_node;
 struct drm_crtc;
 struct drm_device;
-struct drm_fb_helper;
 struct drm_property;
 struct regmap;
 
@@ -56,6 +56,8 @@ struct mtk_drm_private {
 	} commit;
 
 	struct drm_atomic_state *suspend_state;
+	struct drm_fb_helper fb_helper;
+	struct drm_gem_object *fbdev_bo;
 };
 
 extern struct platform_driver mtk_ddp_driver;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
index 0d8d506..ac8561d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
@@ -96,6 +96,19 @@ static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev,
 	return mtk_fb;
 }
 
+struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev,
+		const struct drm_mode_fb_cmd2 *mode,
+		struct drm_gem_object *obj)
+{
+	struct mtk_drm_fb *mtk_fb;
+
+	mtk_fb = mtk_drm_framebuffer_init(dev, mode, obj);
+	if (IS_ERR(mtk_fb))
+		return ERR_CAST(mtk_fb);
+
+	return &mtk_fb->base;
+}
+
 /*
  * Wait for any exclusive fence in fb's gem object's reservation object.
  *
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.h b/drivers/gpu/drm/mediatek/mtk_drm_fb.h
index 9b2ae34..9ee1ac2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_fb.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.h
@@ -19,5 +19,8 @@ int mtk_fb_wait(struct drm_framebuffer *fb);
 struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
 					       struct drm_file *file,
 					       const struct drm_mode_fb_cmd2 *cmd);
+struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev,
+		const struct drm_mode_fb_cmd2 *mode,
+		struct drm_gem_object *obj);
 
 #endif /* MTK_DRM_FB_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
new file mode 100644
index 0000000..9193647
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+
+#include "mtk_drm_drv.h"
+#include "mtk_drm_fb.h"
+#include "mtk_drm_gem.h"
+
+#define to_drm_private(x) \
+		container_of(x, struct mtk_drm_private, fb_helper)
+
+#if 1
+static int mtk_drm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct drm_fb_helper *helper = info->par;
+	struct mtk_drm_private *private = helper->dev->dev_private;
+
+	return mtk_drm_gem_mmap_buf(private->fbdev_bo, vma);
+}
+#endif
+
+static struct fb_ops mtk_fbdev_ops = {
+	.owner = THIS_MODULE,
+	.fb_fillrect = drm_fb_helper_cfb_fillrect,
+	.fb_copyarea = drm_fb_helper_cfb_copyarea,
+	.fb_imageblit = drm_fb_helper_cfb_imageblit,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_setcmap = drm_fb_helper_setcmap,
+	.fb_mmap = mtk_drm_fbdev_mmap,
+};
+
+static int mtk_fbdev_probe(struct drm_fb_helper *helper,
+			   struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = helper->dev;
+	struct mtk_drm_private *private = helper->dev->dev_private;
+	struct drm_mode_fb_cmd2 mode = { 0 };
+	struct mtk_drm_gem_obj *mtk_gem;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	unsigned int bytes_per_pixel;
+	unsigned long offset;
+	size_t size;
+	int err;
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	mode.width = sizes->surface_width;
+	mode.height = sizes->surface_height;
+	mode.pitches[0] = sizes->surface_width * bytes_per_pixel;
+	mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+						      sizes->surface_depth);
+
+	size = mode.pitches[0] * mode.height;
+
+	mtk_gem = mtk_drm_gem_create(dev, size, true);
+	if (IS_ERR(mtk_gem))
+		return PTR_ERR(mtk_gem);
+
+	private->fbdev_bo = &mtk_gem->base;
+
+	info = drm_fb_helper_alloc_fbi(helper);
+	if (IS_ERR(info)) {
+		err = PTR_ERR(info);
+		dev_err(dev->dev, "failed to allocate framebuffer info, %d\n",
+			err);
+		goto err_gem_free_object;
+	}
+
+	fb = mtk_drm_framebuffer_create(dev, &mode, private->fbdev_bo);
+	if (IS_ERR(fb)) {
+		err = PTR_ERR(fb);
+		dev_err(dev->dev, "failed to allocate DRM framebuffer, %d\n",
+			err);
+		goto err_release_fbi;
+	}
+	helper->fb = fb;
+
+	info->par = helper;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &mtk_fbdev_ops;
+
+	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
+	drm_fb_helper_fill_var(info, helper, sizes->fb_width, sizes->fb_height);
+
+	offset = info->var.xoffset * bytes_per_pixel;
+	offset += info->var.yoffset * fb->pitches[0];
+
+	dev->mode_config.fb_base = 0;
+	info->screen_base = mtk_gem->kvaddr + offset;
+	info->screen_size = size;
+	info->fix.smem_len = size;
+
+	DRM_DEBUG_KMS("FB [%ux%u]-%u offset=%lu size=%zd\n",
+		      fb->width, fb->height, fb->format->depth, offset, size);
+
+	info->skip_vt_switch = true;
+
+	return 0;
+
+err_release_fbi:
+err_gem_free_object:
+	mtk_drm_gem_free_object(&mtk_gem->base);
+	return err;
+}
+
+static const struct drm_fb_helper_funcs mtk_drm_fb_helper_funcs = {
+	.fb_probe = mtk_fbdev_probe,
+};
+
+int mtk_fbdev_init(struct drm_device *dev)
+{
+	struct mtk_drm_private *priv = dev->dev_private;
+	struct drm_fb_helper *helper = &priv->fb_helper;
+	int ret;
+
+	if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
+		return -EINVAL;
+
+	drm_fb_helper_prepare(dev, helper, &mtk_drm_fb_helper_funcs);
+
+	ret = drm_fb_helper_init(dev, helper,
+				 dev->mode_config.num_connector);
+	if (ret) {
+		dev_err(dev->dev, "failed to initialize DRM FB helper, %d\n",
+			ret);
+		goto fini;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret) {
+		dev_err(dev->dev, "failed to add connectors, %d\n", ret);
+		goto fini;
+	}
+
+	ret = drm_fb_helper_initial_config(helper, 32);
+	if (ret) {
+		dev_err(dev->dev, "failed to set initial configuration, %d\n",
+			ret);
+		goto fini;
+	}
+
+	return 0;
+
+fini:
+	drm_fb_helper_fini(helper);
+
+	return ret;
+}
+
+void mtk_fbdev_fini(struct drm_device *dev)
+{
+	struct mtk_drm_private *priv = dev->dev_private;
+	struct drm_fb_helper *helper = &priv->fb_helper;
+
+	drm_fb_helper_unregister_fbi(helper);
+
+	if (helper->fb) {
+		drm_framebuffer_unregister_private(helper->fb);
+		drm_framebuffer_remove(helper->fb);
+	}
+
+	drm_fb_helper_fini(helper);
+}
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
new file mode 100644
index 0000000..f3e0949
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MTK_DRM_FBDEV_H
+#define MTK_DRM_FBDEV_H
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+int mtk_fbdev_init(struct drm_device *dev);
+void mtk_fbdev_fini(struct drm_device *dev);
+#else
+int mtk_fbdev_init(struct drm_device *dev)
+{
+	return 0;
+}
+
+void mtk_fbdev_fini(struct drm_device *dev)
+{
+
+}
+#endif /* CONFIG_DRM_FBDEV_EMULATION */
+
+#endif /* MTK_DRM_FBDEV_H */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 8/8] drm: mediatek: Fix drm_of_find_panel_or_bridge conversion
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (6 preceding siblings ...)
  2017-10-16 15:31 ` [RFC v2 7/8] drm/mediatek: Add DRM-based framebuffer device Ulrich Hecht
@ 2017-10-16 15:31 ` Ulrich Hecht
  2017-10-17 10:33 ` [RFC v2 0/8] Acer Chromebook R13 support Matthias Brugger
  2017-10-17 16:38 ` Laurent Pinchart
  9 siblings, 0 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-16 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

The port value should be 1 instead of 0; fixes DSI initialization on
MT8173 "Elm".

Fixes: ebc944613567 ("drm: convert drivers to use drm_of_find_panel_or_bridge")
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/gpu/drm/mediatek/mtk_dsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 7e5e24c..e5ec581 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -1105,7 +1105,7 @@ static int mtk_dsi_probe(struct platform_device *pdev)
 	dsi->host.ops = &mtk_dsi_ops;
 	dsi->host.dev = dev;
 
-	ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0,
 					  &dsi->panel, &dsi->bridge);
 	if (ret)
 		return ret;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [RFC v2 7/8] drm/mediatek: Add DRM-based framebuffer device
  2017-10-16 15:31 ` [RFC v2 7/8] drm/mediatek: Add DRM-based framebuffer device Ulrich Hecht
@ 2017-10-17  9:04   ` Philipp Zabel
  0 siblings, 0 replies; 18+ messages in thread
From: Philipp Zabel @ 2017-10-17  9:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ulrich,

On Mon, 2017-10-16 at 17:31 +0200, Ulrich Hecht wrote:
> Add fbdev support to the Mediatek DRM driver.
> 
> Signed-off-by: CK Hu <ck.hu@mediatek.com>
> Signed-off-by: YT Shen <yt.shen@mediatek.com>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> [uli: Forward-ported from chromeos-3.18 vendor kernel.]
> Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
> ---
>  drivers/gpu/drm/mediatek/Makefile        |   2 +
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c   |   8 ++
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h   |   4 +-
>  drivers/gpu/drm/mediatek/mtk_drm_fb.c    |  13 +++
>  drivers/gpu/drm/mediatek/mtk_drm_fb.h    |   3 +
>  drivers/gpu/drm/mediatek/mtk_drm_fbdev.c | 181 +++++++++++++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_drm_fbdev.h |  32 ++++++
>  7 files changed, 242 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
> 
> diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
> index e37b55a..8306fb5 100644
> --- a/drivers/gpu/drm/mediatek/Makefile
> +++ b/drivers/gpu/drm/mediatek/Makefile
> @@ -12,6 +12,8 @@ mediatek-drm-y := mtk_disp_color.o \
>  		  mtk_mipi_tx.o \
>  		  mtk_dpi.o
>  
> +mediatek-drm-$(CONFIG_DRM_FBDEV_EMULATION) += mtk_drm_fbdev.o
> +
>  obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
>  
>  mediatek-drm-hdmi-objs := mtk_cec.o \
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index ce99921..636b8db 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -30,6 +30,7 @@
>  #include "mtk_drm_ddp_comp.h"
>  #include "mtk_drm_drv.h"
>  #include "mtk_drm_fb.h"
> +#include "mtk_drm_fbdev.h"
>  #include "mtk_drm_gem.h"
>  
>  #define DRIVER_NAME "mediatek"
> @@ -257,8 +258,14 @@ static int mtk_drm_kms_init(struct drm_device *drm)
>  	drm_kms_helper_poll_init(drm);
>  	drm_mode_config_reset(drm);
>  
> +	ret = mtk_fbdev_init(drm);
> +	if (ret)
> +		goto err_kms_helper_poll_fini;
> +
>  	return 0;
>  
> +err_kms_helper_poll_fini:
> +	drm_kms_helper_poll_fini(drm);
>  err_component_unbind:
>  	component_unbind_all(drm->dev, drm);
>  err_config_cleanup:
> @@ -269,6 +276,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
>  
>  static void mtk_drm_kms_deinit(struct drm_device *drm)
>  {
> +	mtk_fbdev_fini(drm);
>  	drm_kms_helper_poll_fini(drm);
>  
>  	component_unbind_all(drm->dev, drm);
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> index c3378c4..4edc002 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h
> @@ -14,6 +14,7 @@
>  #ifndef MTK_DRM_DRV_H
>  #define MTK_DRM_DRV_H
>  
> +#include <drm/drm_fb_helper.h>
>  #include <linux/io.h>
>  #include "mtk_drm_ddp_comp.h"
>  
> @@ -24,7 +25,6 @@ struct device;
>  struct device_node;
>  struct drm_crtc;
>  struct drm_device;
> -struct drm_fb_helper;
>  struct drm_property;
>  struct regmap;
>  
> @@ -56,6 +56,8 @@ struct mtk_drm_private {
>  	} commit;
>  
>  	struct drm_atomic_state *suspend_state;
> +	struct drm_fb_helper fb_helper;
> +	struct drm_gem_object *fbdev_bo;
>  };
>  
>  extern struct platform_driver mtk_ddp_driver;
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
> index 0d8d506..ac8561d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c
> @@ -96,6 +96,19 @@ static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev,
>  	return mtk_fb;
>  }
>  
> +struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev,
> +		const struct drm_mode_fb_cmd2 *mode,
> +		struct drm_gem_object *obj)
> +{
> +	struct mtk_drm_fb *mtk_fb;
> +
> +	mtk_fb = mtk_drm_framebuffer_init(dev, mode, obj);
> +	if (IS_ERR(mtk_fb))
> +		return ERR_CAST(mtk_fb);
> +
> +	return &mtk_fb->base;
> +}
> +
>  /*
>   * Wait for any exclusive fence in fb's gem object's reservation object.
>   *
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.h b/drivers/gpu/drm/mediatek/mtk_drm_fb.h
> index 9b2ae34..9ee1ac2 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.h
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.h
> @@ -19,5 +19,8 @@ int mtk_fb_wait(struct drm_framebuffer *fb);
>  struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
>  					       struct drm_file *file,
>  					       const struct drm_mode_fb_cmd2 *cmd);
> +struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev,
> +		const struct drm_mode_fb_cmd2 *mode,
> +		struct drm_gem_object *obj);
>  
>  #endif /* MTK_DRM_FB_H */
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
> new file mode 100644
> index 0000000..9193647
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
> @@ -0,0 +1,181 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem.h>
> +
> +#include "mtk_drm_drv.h"
> +#include "mtk_drm_fb.h"

This should

#include "mtk_drm_fbdev.h"

as well, to avoid warnings (see below) and make sure the header
declarations match the implementation.

> +#include "mtk_drm_gem.h"
> +
> +#define to_drm_private(x) \
> +		container_of(x, struct mtk_drm_private, fb_helper)
> +
> +#if 1

This superfluous "#if 1" should be removed ...

> +static int mtk_drm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
> +{
> +	struct drm_fb_helper *helper = info->par;
> +	struct mtk_drm_private *private = helper->dev->dev_private;
> +
> +	return mtk_drm_gem_mmap_buf(private->fbdev_bo, vma);
> +}
> +#endif

... together with this "#endif".

> +
> +static struct fb_ops mtk_fbdev_ops = {
> +	.owner = THIS_MODULE,
> +	.fb_fillrect = drm_fb_helper_cfb_fillrect,
> +	.fb_copyarea = drm_fb_helper_cfb_copyarea,
> +	.fb_imageblit = drm_fb_helper_cfb_imageblit,
> +	.fb_check_var = drm_fb_helper_check_var,
> +	.fb_set_par = drm_fb_helper_set_par,
> +	.fb_blank = drm_fb_helper_blank,
> +	.fb_pan_display = drm_fb_helper_pan_display,
> +	.fb_setcmap = drm_fb_helper_setcmap,
> +	.fb_mmap = mtk_drm_fbdev_mmap,
> +};
> +
> +static int mtk_fbdev_probe(struct drm_fb_helper *helper,
> +			   struct drm_fb_helper_surface_size *sizes)
> +{
> +	struct drm_device *dev = helper->dev;
> +	struct mtk_drm_private *private = helper->dev->dev_private;
> +	struct drm_mode_fb_cmd2 mode = { 0 };
> +	struct mtk_drm_gem_obj *mtk_gem;
> +	struct fb_info *info;
> +	struct drm_framebuffer *fb;
> +	unsigned int bytes_per_pixel;
> +	unsigned long offset;
> +	size_t size;
> +	int err;
> +
> +	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
> +
> +	mode.width = sizes->surface_width;
> +	mode.height = sizes->surface_height;
> +	mode.pitches[0] = sizes->surface_width * bytes_per_pixel;
> +	mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
> +						      sizes->surface_depth);
> +
> +	size = mode.pitches[0] * mode.height;
> +
> +	mtk_gem = mtk_drm_gem_create(dev, size, true);
> +	if (IS_ERR(mtk_gem))
> +		return PTR_ERR(mtk_gem);
> +
> +	private->fbdev_bo = &mtk_gem->base;
> +
> +	info = drm_fb_helper_alloc_fbi(helper);
> +	if (IS_ERR(info)) {
> +		err = PTR_ERR(info);
> +		dev_err(dev->dev, "failed to allocate framebuffer info, %d\n",
> +			err);
> +		goto err_gem_free_object;
> +	}
> +
> +	fb = mtk_drm_framebuffer_create(dev, &mode, private->fbdev_bo);
> +	if (IS_ERR(fb)) {
> +		err = PTR_ERR(fb);
> +		dev_err(dev->dev, "failed to allocate DRM framebuffer, %d\n",
> +			err);
> +		goto err_release_fbi;
> +	}
> +	helper->fb = fb;
> +
> +	info->par = helper;
> +	info->flags = FBINFO_FLAG_DEFAULT;
> +	info->fbops = &mtk_fbdev_ops;
> +
> +	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
> +	drm_fb_helper_fill_var(info, helper, sizes->fb_width, sizes->fb_height);
> +
> +	offset = info->var.xoffset * bytes_per_pixel;
> +	offset += info->var.yoffset * fb->pitches[0];
> +
> +	dev->mode_config.fb_base = 0;
> +	info->screen_base = mtk_gem->kvaddr + offset;

To store non-__iomem pointers, there is info->screen_buffer instead of
info->screen_base, see commit 17a7b0b4d974 ("fb.h: Provide alternate
screen_base pointer").

> +	info->screen_size = size;
> +	info->fix.smem_len = size;
> +
> +	DRM_DEBUG_KMS("FB [%ux%u]-%u offset=%lu size=%zd\n",
> +		      fb->width, fb->height, fb->format->depth, offset, size);
> +
> +	info->skip_vt_switch = true;
> +
> +	return 0;
> +
> +err_release_fbi:
> +err_gem_free_object:
> +	mtk_drm_gem_free_object(&mtk_gem->base);
> +	return err;
> +}
> +
> +static const struct drm_fb_helper_funcs mtk_drm_fb_helper_funcs = {
> +	.fb_probe = mtk_fbdev_probe,
> +};
> +
> +int mtk_fbdev_init(struct drm_device *dev)

drivers/gpu/drm/mediatek/mtk_drm_fbdev.c:128:5: warning: symbol 'mtk_fbdev_init' was not declared. Should it be static?

> +{
> +	struct mtk_drm_private *priv = dev->dev_private;
> +	struct drm_fb_helper *helper = &priv->fb_helper;
> +	int ret;
> +
> +	if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
> +		return -EINVAL;
> +
> +	drm_fb_helper_prepare(dev, helper, &mtk_drm_fb_helper_funcs);
> +
> +	ret = drm_fb_helper_init(dev, helper,
> +				 dev->mode_config.num_connector);
> +	if (ret) {
> +		dev_err(dev->dev, "failed to initialize DRM FB helper, %d\n",
> +			ret);
> +		goto fini;
> +	}
> +
> +	ret = drm_fb_helper_single_add_all_connectors(helper);
> +	if (ret) {
> +		dev_err(dev->dev, "failed to add connectors, %d\n", ret);
> +		goto fini;
> +	}
> +
> +	ret = drm_fb_helper_initial_config(helper, 32);
> +	if (ret) {
> +		dev_err(dev->dev, "failed to set initial configuration, %d\n",
> +			ret);
> +		goto fini;
> +	}
> +
> +	return 0;
> +
> +fini:
> +	drm_fb_helper_fini(helper);
> +
> +	return ret;
> +}
> +
> +void mtk_fbdev_fini(struct drm_device *dev)

drivers/gpu/drm/mediatek/mtk_drm_fbdev.c:168:6: warning: symbol 'mtk_fbdev_fini' was not declared. Should it be static?

> +{
> +	struct mtk_drm_private *priv = dev->dev_private;
> +	struct drm_fb_helper *helper = &priv->fb_helper;
> +
> +	drm_fb_helper_unregister_fbi(helper);
> +
> +	if (helper->fb) {
> +		drm_framebuffer_unregister_private(helper->fb);
> +		drm_framebuffer_remove(helper->fb);
> +	}
> +
> +	drm_fb_helper_fini(helper);
> +}
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
> new file mode 100644
> index 0000000..f3e0949
> --- /dev/null
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (c) 2016 MediaTek Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef MTK_DRM_FBDEV_H
> +#define MTK_DRM_FBDEV_H
> +
> +#ifdef CONFIG_DRM_FBDEV_EMULATION
> +int mtk_fbdev_init(struct drm_device *dev);
> +void mtk_fbdev_fini(struct drm_device *dev);
> +#else
> +int mtk_fbdev_init(struct drm_device *dev)
[...]
> +void mtk_fbdev_fini(struct drm_device *dev)

These two should be static inline:

drivers/gpu/drm/mediatek/mtk_drm_fbdev.h:21:5: warning: symbol 'mtk_fbdev_init' was not declared. Should it be static?
drivers/gpu/drm/mediatek/mtk_drm_fbdev.h:26:6: warning: symbol 'mtk_fbdev_fini' was not declared. Should it be static?

regards
Philipp

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (7 preceding siblings ...)
  2017-10-16 15:31 ` [RFC v2 8/8] drm: mediatek: Fix drm_of_find_panel_or_bridge conversion Ulrich Hecht
@ 2017-10-17 10:33 ` Matthias Brugger
  2017-10-17 16:05   ` Sean Paul
  2017-10-17 16:38 ` Laurent Pinchart
  9 siblings, 1 reply; 18+ messages in thread
From: Matthias Brugger @ 2017-10-17 10:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ulrich,

On 10/16/2017 05:31 PM, Ulrich Hecht wrote:
> Hi!
> 
> This is a new revision of the Acer Chromebook R13 support series. It does
> not offer anything new in terms of functionality, but eliminates three out
> of four ugly hacks and adds a few minor cleanups; see below for details.
> Thanks to Robin Murphy and CK Hu for their comments and suggestions!
> 
> I'm still looking for advice on how to implement the dual-role mmsys device
> correctly; see "hack: mediatek: get mmsys to register as both DRM and clock
> device" for details on this.
> 
> Like the previous revision, you can find this series at
> https://github.com/uli/kernel/tree/elm-working, which also contains a config
> file and several ancillary bits that are required to build a kernel
> partition for the Chromebook. Instructions on how to do so (and various
> other things that have to be done to get it running on your device) are
> available at
> https://www.elinux.org/User:Uli/Acer_Chromebook_R13_GPU_test_system (These
> instructions have been written for the vendor kernel, but apply to mainline
> as well, except that you won't need any extra patches.)
> 

I appreciate your efforts to get this done. From what I understand you rebased 
the patches from the chromium kernel to mainline. So you should keep the 
signed-off-by from the original author and just add you signed-off-by below that.
Also it would be nice to CC these persons so that they are aware of your effort.

> CU
> Uli
> 
> Changes since RFC v1:
> - cmdq: remove obsolete driver; not currently used anyway

Are you sure about this? I remember that Dan (CC'ed) told me that this is one of 
the requirements to get upstream working.

Dan, can you clarify please?

Regards,
Matthias

> - dt: remove CD GPIO from mmc1, does not seem to be correct
> - mmc: remove mtk-sd.c revert hack (works fine without the CD pin)
> - dsi: fix port number for drm_of_find_panel_or_bridge(), remove hack
> - fbdev: add missing Signed-off-bys
> - iommu: remove io-pgtable sanity check hack, has been properly fixed
> - minor style fixes
> 
> 
> Ulrich Hecht (8):
>    drm/bridge: GPIO-controlled display multiplexer driver
>    platform/chrome: ChromeOS firmware interface driver
>    drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver
>    drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver
>    arm64: dts: mediatek: Add Elm Rev. 3 device tree
>    hack: mediatek: get mmsys to register as both DRM and clock device
>    drm/mediatek: Add DRM-based framebuffer device
>    drm: mediatek: Fix drm_of_find_panel_or_bridge conversion
> 
>   arch/arm64/boot/dts/mediatek/Makefile            |    1 +
>   arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts |   21 +
>   arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi     |  210 ++++
>   arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi     | 1013 ++++++++++++++++++++
>   drivers/clk/mediatek/clk-mt8173.c                |    4 +-
>   drivers/gpu/drm/bridge/Kconfig                   |   32 +
>   drivers/gpu/drm/bridge/Makefile                  |    5 +
>   drivers/gpu/drm/bridge/analogix-anx7688.c        |  233 +++++
>   drivers/gpu/drm/bridge/generic-gpio-mux.c        |  316 +++++++
>   drivers/gpu/drm/bridge/parade-ps8640.c           | 1104 ++++++++++++++++++++++
>   drivers/gpu/drm/mediatek/Makefile                |    2 +
>   drivers/gpu/drm/mediatek/mtk_dpi.c               |    5 +-
>   drivers/gpu/drm/mediatek/mtk_drm_ddp.c           |    5 +-
>   drivers/gpu/drm/mediatek/mtk_drm_drv.c           |   15 +
>   drivers/gpu/drm/mediatek/mtk_drm_drv.h           |    4 +-
>   drivers/gpu/drm/mediatek/mtk_drm_fb.c            |   13 +
>   drivers/gpu/drm/mediatek/mtk_drm_fb.h            |    3 +
>   drivers/gpu/drm/mediatek/mtk_drm_fbdev.c         |  181 ++++
>   drivers/gpu/drm/mediatek/mtk_drm_fbdev.h         |   32 +
>   drivers/gpu/drm/mediatek/mtk_dsi.c               |    2 +-
>   drivers/gpu/drm/mediatek/mtk_hdmi.c              |    5 +-
>   drivers/platform/chrome/Kconfig                  |   18 +
>   drivers/platform/chrome/Makefile                 |    2 +
>   drivers/platform/chrome/chromeos.c               |  120 +++
>   drivers/platform/chrome/chromeos.h               |   61 ++
>   drivers/platform/chrome/chromeos_arm.c           |  264 ++++++
>   drivers/platform/chrome/elog.h                   |  186 ++++
>   include/linux/chromeos_platform.h                |   27 +
>   28 files changed, 3874 insertions(+), 10 deletions(-)
>   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
>   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
>   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
>   create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c
>   create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c
>   create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c
>   create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
>   create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
>   create mode 100644 drivers/platform/chrome/chromeos.c
>   create mode 100644 drivers/platform/chrome/chromeos.h
>   create mode 100644 drivers/platform/chrome/chromeos_arm.c
>   create mode 100644 drivers/platform/chrome/elog.h
>   create mode 100644 include/linux/chromeos_platform.h
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-17 10:33 ` [RFC v2 0/8] Acer Chromebook R13 support Matthias Brugger
@ 2017-10-17 16:05   ` Sean Paul
  2017-10-18 14:53     ` Ulrich Hecht
  0 siblings, 1 reply; 18+ messages in thread
From: Sean Paul @ 2017-10-17 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 12:33:09PM +0200, Matthias Brugger wrote:
> Hi Ulrich,
> 
> On 10/16/2017 05:31 PM, Ulrich Hecht wrote:
> > Hi!
> > 
> > This is a new revision of the Acer Chromebook R13 support series. It does
> > not offer anything new in terms of functionality, but eliminates three out
> > of four ugly hacks and adds a few minor cleanups; see below for details.
> > Thanks to Robin Murphy and CK Hu for their comments and suggestions!
> > 
> > I'm still looking for advice on how to implement the dual-role mmsys device
> > correctly; see "hack: mediatek: get mmsys to register as both DRM and clock
> > device" for details on this.
> > 
> > Like the previous revision, you can find this series at
> > https://github.com/uli/kernel/tree/elm-working, which also contains a config
> > file and several ancillary bits that are required to build a kernel
> > partition for the Chromebook. Instructions on how to do so (and various
> > other things that have to be done to get it running on your device) are
> > available at
> > https://www.elinux.org/User:Uli/Acer_Chromebook_R13_GPU_test_system (These
> > instructions have been written for the vendor kernel, but apply to mainline
> > as well, except that you won't need any extra patches.)
> > 
> 
> I appreciate your efforts to get this done. 

Agreed, thanks for doing this work and posting it! 

> From what I understand you
> rebased the patches from the chromium kernel to mainline. So you should keep
> the signed-off-by from the original author and just add you signed-off-by
> below that.
> Also it would be nice to CC these persons so that they are aware of your effort.
> 

Additionally, make sure the author and commit messages are preserved when you send
patches. You can add your own message in addition to your SoB, but please try to
preserve history.

Sean


> > CU
> > Uli
> > 
> > Changes since RFC v1:
> > - cmdq: remove obsolete driver; not currently used anyway
> 
> Are you sure about this? I remember that Dan (CC'ed) told me that this is
> one of the requirements to get upstream working.
> 
> Dan, can you clarify please?
> 
> Regards,
> Matthias
> 
> > - dt: remove CD GPIO from mmc1, does not seem to be correct
> > - mmc: remove mtk-sd.c revert hack (works fine without the CD pin)
> > - dsi: fix port number for drm_of_find_panel_or_bridge(), remove hack
> > - fbdev: add missing Signed-off-bys
> > - iommu: remove io-pgtable sanity check hack, has been properly fixed
> > - minor style fixes
> > 
> > 
> > Ulrich Hecht (8):
> >    drm/bridge: GPIO-controlled display multiplexer driver
> >    platform/chrome: ChromeOS firmware interface driver
> >    drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver
> >    drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver
> >    arm64: dts: mediatek: Add Elm Rev. 3 device tree
> >    hack: mediatek: get mmsys to register as both DRM and clock device
> >    drm/mediatek: Add DRM-based framebuffer device
> >    drm: mediatek: Fix drm_of_find_panel_or_bridge conversion
> > 
> >   arch/arm64/boot/dts/mediatek/Makefile            |    1 +
> >   arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts |   21 +
> >   arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi     |  210 ++++
> >   arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi     | 1013 ++++++++++++++++++++
> >   drivers/clk/mediatek/clk-mt8173.c                |    4 +-
> >   drivers/gpu/drm/bridge/Kconfig                   |   32 +
> >   drivers/gpu/drm/bridge/Makefile                  |    5 +
> >   drivers/gpu/drm/bridge/analogix-anx7688.c        |  233 +++++
> >   drivers/gpu/drm/bridge/generic-gpio-mux.c        |  316 +++++++
> >   drivers/gpu/drm/bridge/parade-ps8640.c           | 1104 ++++++++++++++++++++++
> >   drivers/gpu/drm/mediatek/Makefile                |    2 +
> >   drivers/gpu/drm/mediatek/mtk_dpi.c               |    5 +-
> >   drivers/gpu/drm/mediatek/mtk_drm_ddp.c           |    5 +-
> >   drivers/gpu/drm/mediatek/mtk_drm_drv.c           |   15 +
> >   drivers/gpu/drm/mediatek/mtk_drm_drv.h           |    4 +-
> >   drivers/gpu/drm/mediatek/mtk_drm_fb.c            |   13 +
> >   drivers/gpu/drm/mediatek/mtk_drm_fb.h            |    3 +
> >   drivers/gpu/drm/mediatek/mtk_drm_fbdev.c         |  181 ++++
> >   drivers/gpu/drm/mediatek/mtk_drm_fbdev.h         |   32 +
> >   drivers/gpu/drm/mediatek/mtk_dsi.c               |    2 +-
> >   drivers/gpu/drm/mediatek/mtk_hdmi.c              |    5 +-
> >   drivers/platform/chrome/Kconfig                  |   18 +
> >   drivers/platform/chrome/Makefile                 |    2 +
> >   drivers/platform/chrome/chromeos.c               |  120 +++
> >   drivers/platform/chrome/chromeos.h               |   61 ++
> >   drivers/platform/chrome/chromeos_arm.c           |  264 ++++++
> >   drivers/platform/chrome/elog.h                   |  186 ++++
> >   include/linux/chromeos_platform.h                |   27 +
> >   28 files changed, 3874 insertions(+), 10 deletions(-)
> >   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
> >   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
> >   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
> >   create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c
> >   create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c
> >   create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c
> >   create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
> >   create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
> >   create mode 100644 drivers/platform/chrome/chromeos.c
> >   create mode 100644 drivers/platform/chrome/chromeos.h
> >   create mode 100644 drivers/platform/chrome/chromeos_arm.c
> >   create mode 100644 drivers/platform/chrome/elog.h
> >   create mode 100644 include/linux/chromeos_platform.h
> > 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Sean Paul, Software Engineer, Google / Chromium OS

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
                   ` (8 preceding siblings ...)
  2017-10-17 10:33 ` [RFC v2 0/8] Acer Chromebook R13 support Matthias Brugger
@ 2017-10-17 16:38 ` Laurent Pinchart
  2017-10-18 14:20   ` Matthias Brugger
  9 siblings, 1 reply; 18+ messages in thread
From: Laurent Pinchart @ 2017-10-17 16:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ulrich,

(CC'ing Matthias Brugger and Daniel Kurtz)

On Monday, 16 October 2017 18:31:32 EEST Ulrich Hecht wrote:
> Hi!
> 
> This is a new revision of the Acer Chromebook R13 support series. It does
> not offer anything new in terms of functionality, but eliminates three out
> of four ugly hacks and adds a few minor cleanups; see below for details.
> Thanks to Robin Murphy and CK Hu for their comments and suggestions!
> 
> I'm still looking for advice on how to implement the dual-role mmsys device
> correctly; see "hack: mediatek: get mmsys to register as both DRM and clock
> device" for details on this.

What I'd really like to find out is what the mmsys device is. Its DT binding 
documents it as "The Mediatek mmsys controller provides various clocks to the 
system". Even if it provides clocks to the display engine, it shouldn't be 
used as the root device in the display complex. There could of course be 
information I'm lacking as the datasheet isn't public. Hopefully someone from 
Mediatek and/or Google will be able to comment on this.

> Like the previous revision, you can find this series at
> https://github.com/uli/kernel/tree/elm-working, which also contains a config
> file and several ancillary bits that are required to build a kernel
> partition for the Chromebook. Instructions on how to do so (and various
> other things that have to be done to get it running on your device) are
> available at
> https://www.elinux.org/User:Uli/Acer_Chromebook_R13_GPU_test_system (These
> instructions have been written for the vendor kernel, but apply to mainline
> as well, except that you won't need any extra patches.)
> 
> CU
> Uli
> 
> Changes since RFC v1:
> - cmdq: remove obsolete driver; not currently used anyway
> - dt: remove CD GPIO from mmc1, does not seem to be correct
> - mmc: remove mtk-sd.c revert hack (works fine without the CD pin)
> - dsi: fix port number for drm_of_find_panel_or_bridge(), remove hack
> - fbdev: add missing Signed-off-bys
> - iommu: remove io-pgtable sanity check hack, has been properly fixed
> - minor style fixes
> 
> 
> Ulrich Hecht (8):
>   drm/bridge: GPIO-controlled display multiplexer driver
>   platform/chrome: ChromeOS firmware interface driver
>   drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver
>   drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver
>   arm64: dts: mediatek: Add Elm Rev. 3 device tree
>   hack: mediatek: get mmsys to register as both DRM and clock device
>   drm/mediatek: Add DRM-based framebuffer device
>   drm: mediatek: Fix drm_of_find_panel_or_bridge conversion
> 
>  arch/arm64/boot/dts/mediatek/Makefile            |    1 +
>  arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts |   21 +
>  arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi     |  210 ++++
>  arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi     | 1013 +++++++++++++++++++
>  drivers/clk/mediatek/clk-mt8173.c                |    4 +-
>  drivers/gpu/drm/bridge/Kconfig                   |   32 +
>  drivers/gpu/drm/bridge/Makefile                  |    5 +
>  drivers/gpu/drm/bridge/analogix-anx7688.c        |  233 +++++
>  drivers/gpu/drm/bridge/generic-gpio-mux.c        |  316 +++++++
>  drivers/gpu/drm/bridge/parade-ps8640.c           | 1104 +++++++++++++++++++
>  drivers/gpu/drm/mediatek/Makefile                |    2 +
>  drivers/gpu/drm/mediatek/mtk_dpi.c               |    5 +-
>  drivers/gpu/drm/mediatek/mtk_drm_ddp.c           |    5 +-
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c           |   15 +
>  drivers/gpu/drm/mediatek/mtk_drm_drv.h           |    4 +-
>  drivers/gpu/drm/mediatek/mtk_drm_fb.c            |   13 +
>  drivers/gpu/drm/mediatek/mtk_drm_fb.h            |    3 +
>  drivers/gpu/drm/mediatek/mtk_drm_fbdev.c         |  181 ++++
>  drivers/gpu/drm/mediatek/mtk_drm_fbdev.h         |   32 +
>  drivers/gpu/drm/mediatek/mtk_dsi.c               |    2 +-
>  drivers/gpu/drm/mediatek/mtk_hdmi.c              |    5 +-
>  drivers/platform/chrome/Kconfig                  |   18 +
>  drivers/platform/chrome/Makefile                 |    2 +
>  drivers/platform/chrome/chromeos.c               |  120 +++
>  drivers/platform/chrome/chromeos.h               |   61 ++
>  drivers/platform/chrome/chromeos_arm.c           |  264 ++++++
>  drivers/platform/chrome/elog.h                   |  186 ++++
>  include/linux/chromeos_platform.h                |   27 +
>  28 files changed, 3874 insertions(+), 10 deletions(-)
>  create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
>  create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
>  create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
>  create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c
>  create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c
>  create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
>  create mode 100644 drivers/platform/chrome/chromeos.c
>  create mode 100644 drivers/platform/chrome/chromeos.h
>  create mode 100644 drivers/platform/chrome/chromeos_arm.c
>  create mode 100644 drivers/platform/chrome/elog.h
>  create mode 100644 include/linux/chromeos_platform.h


-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-17 16:38 ` Laurent Pinchart
@ 2017-10-18 14:20   ` Matthias Brugger
  0 siblings, 0 replies; 18+ messages in thread
From: Matthias Brugger @ 2017-10-18 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Laurent,

On 10/17/2017 06:38 PM, Laurent Pinchart wrote:
> Hi Ulrich,
> 
> (CC'ing Matthias Brugger and Daniel Kurtz)
> 
> On Monday, 16 October 2017 18:31:32 EEST Ulrich Hecht wrote:
>> Hi!
>>
>> This is a new revision of the Acer Chromebook R13 support series. It does
>> not offer anything new in terms of functionality, but eliminates three out
>> of four ugly hacks and adds a few minor cleanups; see below for details.
>> Thanks to Robin Murphy and CK Hu for their comments and suggestions!
>>
>> I'm still looking for advice on how to implement the dual-role mmsys device
>> correctly; see "hack: mediatek: get mmsys to register as both DRM and clock
>> device" for details on this.
> 
> What I'd really like to find out is what the mmsys device is. Its DT binding
> documents it as "The Mediatek mmsys controller provides various clocks to the
> system". Even if it provides clocks to the display engine, it shouldn't be
> used as the root device in the display complex. There could of course be
> information I'm lacking as the datasheet isn't public. Hopefully someone from
> Mediatek and/or Google will be able to comment on this.
> 

Apart from enabling clock gates (in the clock driver) it provides the register 
space (config_regs) to other parts of the drm system, namely:
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp.c

You can find the register table for mmsys in Part II here:
https://www.96boards.org/documentation/ConsumerEdition/MediaTekX20/AdditionalDocs/

Beware this document is for mt6797. Register offsets and values have changed (I 
just had a quick glance), but it gives you an idea what the driver does.

In the code path:
mtk_drm_crtc_atomic_enable -> mtk_crtc_ddp_hw_init -> mtk_ddp_add_comp_to_path
mtk_drm_ddp.c set's some bits in mmsys to enable the components. Which uses 
writel/readl_relaxed. This looks wrong, as mmsys is syscon and the driver should 
use regmap here.

I think we should add a new compatible for the display subsystem which accesses 
mmsys via a phandle and the correct regmap accessors. I'll try to submit a RFC 
to illustrate what I mean.

Regards,
Matthias

>> Like the previous revision, you can find this series at
>> https://github.com/uli/kernel/tree/elm-working, which also contains a config
>> file and several ancillary bits that are required to build a kernel
>> partition for the Chromebook. Instructions on how to do so (and various
>> other things that have to be done to get it running on your device) are
>> available at
>> https://www.elinux.org/User:Uli/Acer_Chromebook_R13_GPU_test_system (These
>> instructions have been written for the vendor kernel, but apply to mainline
>> as well, except that you won't need any extra patches.)
>>
>> CU
>> Uli
>>
>> Changes since RFC v1:
>> - cmdq: remove obsolete driver; not currently used anyway
>> - dt: remove CD GPIO from mmc1, does not seem to be correct
>> - mmc: remove mtk-sd.c revert hack (works fine without the CD pin)
>> - dsi: fix port number for drm_of_find_panel_or_bridge(), remove hack
>> - fbdev: add missing Signed-off-bys
>> - iommu: remove io-pgtable sanity check hack, has been properly fixed
>> - minor style fixes
>>
>>
>> Ulrich Hecht (8):
>>    drm/bridge: GPIO-controlled display multiplexer driver
>>    platform/chrome: ChromeOS firmware interface driver
>>    drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver
>>    drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver
>>    arm64: dts: mediatek: Add Elm Rev. 3 device tree
>>    hack: mediatek: get mmsys to register as both DRM and clock device
>>    drm/mediatek: Add DRM-based framebuffer device
>>    drm: mediatek: Fix drm_of_find_panel_or_bridge conversion
>>
>>   arch/arm64/boot/dts/mediatek/Makefile            |    1 +
>>   arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts |   21 +
>>   arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi     |  210 ++++
>>   arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi     | 1013 +++++++++++++++++++
>>   drivers/clk/mediatek/clk-mt8173.c                |    4 +-
>>   drivers/gpu/drm/bridge/Kconfig                   |   32 +
>>   drivers/gpu/drm/bridge/Makefile                  |    5 +
>>   drivers/gpu/drm/bridge/analogix-anx7688.c        |  233 +++++
>>   drivers/gpu/drm/bridge/generic-gpio-mux.c        |  316 +++++++
>>   drivers/gpu/drm/bridge/parade-ps8640.c           | 1104 +++++++++++++++++++
>>   drivers/gpu/drm/mediatek/Makefile                |    2 +
>>   drivers/gpu/drm/mediatek/mtk_dpi.c               |    5 +-
>>   drivers/gpu/drm/mediatek/mtk_drm_ddp.c           |    5 +-
>>   drivers/gpu/drm/mediatek/mtk_drm_drv.c           |   15 +
>>   drivers/gpu/drm/mediatek/mtk_drm_drv.h           |    4 +-
>>   drivers/gpu/drm/mediatek/mtk_drm_fb.c            |   13 +
>>   drivers/gpu/drm/mediatek/mtk_drm_fb.h            |    3 +
>>   drivers/gpu/drm/mediatek/mtk_drm_fbdev.c         |  181 ++++
>>   drivers/gpu/drm/mediatek/mtk_drm_fbdev.h         |   32 +
>>   drivers/gpu/drm/mediatek/mtk_dsi.c               |    2 +-
>>   drivers/gpu/drm/mediatek/mtk_hdmi.c              |    5 +-
>>   drivers/platform/chrome/Kconfig                  |   18 +
>>   drivers/platform/chrome/Makefile                 |    2 +
>>   drivers/platform/chrome/chromeos.c               |  120 +++
>>   drivers/platform/chrome/chromeos.h               |   61 ++
>>   drivers/platform/chrome/chromeos_arm.c           |  264 ++++++
>>   drivers/platform/chrome/elog.h                   |  186 ++++
>>   include/linux/chromeos_platform.h                |   27 +
>>   28 files changed, 3874 insertions(+), 10 deletions(-)
>>   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm-rev3.dts
>>   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
>>   create mode 100644 arch/arm64/boot/dts/mediatek/mt8173-oak.dtsi
>>   create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c
>>   create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c
>>   create mode 100644 drivers/gpu/drm/bridge/parade-ps8640.c
>>   create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c
>>   create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h
>>   create mode 100644 drivers/platform/chrome/chromeos.c
>>   create mode 100644 drivers/platform/chrome/chromeos.h
>>   create mode 100644 drivers/platform/chrome/chromeos_arm.c
>>   create mode 100644 drivers/platform/chrome/elog.h
>>   create mode 100644 include/linux/chromeos_platform.h
> 
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-17 16:05   ` Sean Paul
@ 2017-10-18 14:53     ` Ulrich Hecht
  2017-10-18 15:57       ` Laurent Pinchart
  2017-10-18 15:58       ` Matthias Brugger
  0 siblings, 2 replies; 18+ messages in thread
From: Ulrich Hecht @ 2017-10-18 14:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 17, 2017 at 6:05 PM, Sean Paul <seanpaul@chromium.org> wrote:
> On Tue, Oct 17, 2017 at 12:33:09PM +0200, Matthias Brugger wrote:
>> From what I understand you
>> rebased the patches from the chromium kernel to mainline. So you should keep
>> the signed-off-by from the original author and just add you signed-off-by
>> below that.
>> Also it would be nice to CC these persons so that they are aware of your effort.
>>
> Additionally, make sure the author and commit messages are preserved when you send
> patches. You can add your own message in addition to your SoB, but please try to
> preserve history.

Fair enough, but I'm not sure what exactly to include. The chromium
commits include, among other things:

- bugtracker numbers and test cases
- "Change-Id" and "Commit-Ready" (no idea what those are)
- "Reviewed-on", containing links to chromium-review.googlesource.com

With all changes to the PS8640 driver concatenated and non-standard
tags removed, the commit message would look like this:

=============================
    CHROMIUM: drm/bridge: Add I2C based driver for ps8640 bridge

    This patch adds drm_bridge driver for parade DSI to eDP bridge chip.

    Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
    (am from https://patchwork.kernel.org/patch/8357851/)
    Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
    Tested-by: cawa cheng <cawa.cheng@mediatek.com>
    Tested-by: Daniel Kurtz <djkurtz@chromium.org>
    Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>


    FIXUP: FROMLIST: drm/bridge: Add I2C based driver for ps8640 bridge

    chromeos-3.18 currently has FROMLIST v15 of the PS8640 driver.
    This version is incompatible with UPSTREAM version of the Mediatek
    DRM driver.

    To quote Philipp Zabel:
    "The main DRM driver mtk_drm_drv now calls
    drm_connector_register_all() after drm_dev_register() in the
    mtk_drm_bind() function. That function should iterate over all
    connectors and call drm_connector_register() for each of them.
    The call to drm_connector_init() from mtk_hdmi_bridge_attach()
    should be enough to make this happen.

    The drm_connector_(un)register calls also have to be removed
    from the ps8640 driver."

    Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
    Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
    Tested-by: PC Liao <pc.liao@mediatek.com>
    Tested-by: Daniel Kurtz <djkurtz@chromium.org>
    Tested-by: Nicolas Boichat <drinkcat@chromium.org>
    Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>


    CHROMIUM: drm/bridge: ps8640: Add a 3 ms delay before unmuting output

    For current ps8640 firmware, the PS_GPIO9 signal only indicates the bridge
    has seen the attached panel's HPD signal and read its EDID.  Unfortunately,
    the bridge may not yet be ready to properly handle DSI/eDP traffic yet.

    For now, Paradetech has recommended adding a 3 ms delay after PS_GPIO9
    before starting video signal transmission.

    Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
    Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>

    Tested-by: cawa cheng <cawa.cheng@mediatek.com>
    Tested-by: Daniel Kurtz <djkurtz@chromium.org>
    Tested-by: jitao shi <jitao.shi@mediatek.com>
    Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
    Reviewed-by: jitao shi <jitao.shi@mediatek.com>


    CHROMIUM: drm/bridge: ps8640: disable MIPI MCS

    Disable PS8640 MIPI MCS commands to workaround an issue where normal
    MIPI DSI signals are sometimes recognized as an MSC command that can,
    for example, disable the bridge output.

    Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
    Tested-by: Daniel Kurtz <djkurtz@chromium.org>
    Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>


    CHROMIUM: drm/bridge: ps8640: Use individual regulators instead of bulk

    According to the latest information from Parade, the PS8640 1.2 V
    supply must be enabled before 3.3 V.
    So, split the bulk regulator into separate individual regulators that
    can be enabled independently.

    Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>

    Tested-by: Daniel Kurtz <djkurtz@chromium.org>
    Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>


    CHROMIUM: drm/bridge: ps8640: add 5ms delay between v12 and v33

    According to Parade, the PS8640 1.2V must be enabled 5 ms before its
    3.3V. Otherwise, the PS8650 MCU may hang, and its settings cannot be
    written correctly, leading to a black screen.

    Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
    Tested-by: Daniel Kurtz <djkurtz@chromium.org>
    Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
=============================

That keeps chronology and attribution intact, but is somewhat
redundant. Any suggestions on how to digest it? Or should I just add
it as is?

CU
Uli

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-18 14:53     ` Ulrich Hecht
@ 2017-10-18 15:57       ` Laurent Pinchart
  2017-10-18 16:07         ` Laurent Pinchart
  2017-10-18 15:58       ` Matthias Brugger
  1 sibling, 1 reply; 18+ messages in thread
From: Laurent Pinchart @ 2017-10-18 15:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ulrich,

On Wednesday, 18 October 2017 17:53:54 EEST Ulrich Hecht wrote:
> On Tue, Oct 17, 2017 at 6:05 PM, Sean Paul <seanpaul@chromium.org> wrote:
> > On Tue, Oct 17, 2017 at 12:33:09PM +0200, Matthias Brugger wrote:
> >> From what I understand you
> >> rebased the patches from the chromium kernel to mainline. So you should
> >> keep the signed-off-by from the original author and just add you
> >> signed-off-by below that.
> >> Also it would be nice to CC these persons so that they are aware of your
> >> effort.> 
> > Additionally, make sure the author and commit messages are preserved when
> > you send patches. You can add your own message in addition to your SoB,
> > but please try to preserve history.
> 
> Fair enough, but I'm not sure what exactly to include. The chromium
> commits include, among other things:
> 
> - bugtracker numbers and test cases
> - "Change-Id" and "Commit-Ready" (no idea what those are)
> - "Reviewed-on", containing links to chromium-review.googlesource.com
> 
> With all changes to the PS8640 driver concatenated and non-standard
> tags removed, the commit message would look like this:
> 
> =============================
>     CHROMIUM: drm/bridge: Add I2C based driver for ps8640 bridge
> 
>     This patch adds drm_bridge driver for parade DSI to eDP bridge chip.
> 
>     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>     (am from https://patchwork.kernel.org/patch/8357851/)
>     Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
>     Tested-by: cawa cheng <cawa.cheng@mediatek.com>
>     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>     Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
> 
> 
>     FIXUP: FROMLIST: drm/bridge: Add I2C based driver for ps8640 bridge
> 
>     chromeos-3.18 currently has FROMLIST v15 of the PS8640 driver.
>     This version is incompatible with UPSTREAM version of the Mediatek
>     DRM driver.
> 
>     To quote Philipp Zabel:
>     "The main DRM driver mtk_drm_drv now calls
>     drm_connector_register_all() after drm_dev_register() in the
>     mtk_drm_bind() function. That function should iterate over all
>     connectors and call drm_connector_register() for each of them.
>     The call to drm_connector_init() from mtk_hdmi_bridge_attach()
>     should be enough to make this happen.
> 
>     The drm_connector_(un)register calls also have to be removed
>     from the ps8640 driver."
> 
>     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>     Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
>     Tested-by: PC Liao <pc.liao@mediatek.com>
>     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>     Tested-by: Nicolas Boichat <drinkcat@chromium.org>
>     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> 
> 
>     CHROMIUM: drm/bridge: ps8640: Add a 3 ms delay before unmuting output
> 
>     For current ps8640 firmware, the PS_GPIO9 signal only indicates the
> bridge has seen the attached panel's HPD signal and read its EDID. 
> Unfortunately, the bridge may not yet be ready to properly handle DSI/eDP
> traffic yet.
> 
>     For now, Paradetech has recommended adding a 3 ms delay after PS_GPIO9
>     before starting video signal transmission.
> 
>     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>     Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> 
>     Tested-by: cawa cheng <cawa.cheng@mediatek.com>
>     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>     Tested-by: jitao shi <jitao.shi@mediatek.com>
>     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
>     Reviewed-by: jitao shi <jitao.shi@mediatek.com>
> 
> 
>     CHROMIUM: drm/bridge: ps8640: disable MIPI MCS
> 
>     Disable PS8640 MIPI MCS commands to workaround an issue where normal
>     MIPI DSI signals are sometimes recognized as an MSC command that can,
>     for example, disable the bridge output.
> 
>     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> 
> 
>     CHROMIUM: drm/bridge: ps8640: Use individual regulators instead of bulk
> 
>     According to the latest information from Parade, the PS8640 1.2 V
>     supply must be enabled before 3.3 V.
>     So, split the bulk regulator into separate individual regulators that
>     can be enabled independently.
> 
>     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> 
>     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> 
> 
>     CHROMIUM: drm/bridge: ps8640: add 5ms delay between v12 and v33
> 
>     According to Parade, the PS8640 1.2V must be enabled 5 ms before its
>     3.3V. Otherwise, the PS8650 MCU may hang, and its settings cannot be
>     written correctly, leading to a black screen.
> 
>     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> =============================
> 
> That keeps chronology and attribution intact, but is somewhat
> redundant. Any suggestions on how to digest it? Or should I just add
> it as is?

I would keep all the SoB lines, but apart from that I don't think there's a 
need to copy all commit messages. You can extract relevant information for a 
digest, but there's no point in copying the whole history.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-18 14:53     ` Ulrich Hecht
  2017-10-18 15:57       ` Laurent Pinchart
@ 2017-10-18 15:58       ` Matthias Brugger
  1 sibling, 0 replies; 18+ messages in thread
From: Matthias Brugger @ 2017-10-18 15:58 UTC (permalink / raw)
  To: linux-arm-kernel



On 10/18/2017 04:53 PM, Ulrich Hecht wrote:
> On Tue, Oct 17, 2017 at 6:05 PM, Sean Paul <seanpaul@chromium.org> wrote:
>> On Tue, Oct 17, 2017 at 12:33:09PM +0200, Matthias Brugger wrote:
>>>  From what I understand you
>>> rebased the patches from the chromium kernel to mainline. So you should keep
>>> the signed-off-by from the original author and just add you signed-off-by
>>> below that.
>>> Also it would be nice to CC these persons so that they are aware of your effort.
>>>
>> Additionally, make sure the author and commit messages are preserved when you send
>> patches. You can add your own message in addition to your SoB, but please try to
>> preserve history.
> 
> Fair enough, but I'm not sure what exactly to include. The chromium
> commits include, among other things:
> 
> - bugtracker numbers and test cases
> - "Change-Id" and "Commit-Ready" (no idea what those are)
> - "Reviewed-on", containing links to chromium-review.googlesource.com
> 
> With all changes to the PS8640 driver concatenated and non-standard
> tags removed, the commit message would look like this:
> 
> =============================
>      CHROMIUM: drm/bridge: Add I2C based driver for ps8640 bridge

The ones that have a FROMLIST are actually backports taken from the mailinglist, 
so please search for them. Good starting point is linux-mediatek and 
linux-arm-kernel newsgroups.

For this patch the latest submission is these:
https://patchwork.kernel.org/patch/9427541/
https://patchwork.kernel.org/patch/9427543/

Please take up this patches and resubmit with the comments addressed by the 
reviewers.

Keep up the good work!
Matthias

> 
>      This patch adds drm_bridge driver for parade DSI to eDP bridge chip.
> 
>      Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>      (am from https://patchwork.kernel.org/patch/8357851/)
>      Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
>      Tested-by: cawa cheng <cawa.cheng@mediatek.com>
>      Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>      Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
> 
> 
>      FIXUP: FROMLIST: drm/bridge: Add I2C based driver for ps8640 bridge
> 
>      chromeos-3.18 currently has FROMLIST v15 of the PS8640 driver.
>      This version is incompatible with UPSTREAM version of the Mediatek
>      DRM driver.
> 
>      To quote Philipp Zabel:
>      "The main DRM driver mtk_drm_drv now calls
>      drm_connector_register_all() after drm_dev_register() in the
>      mtk_drm_bind() function. That function should iterate over all
>      connectors and call drm_connector_register() for each of them.
>      The call to drm_connector_init() from mtk_hdmi_bridge_attach()
>      should be enough to make this happen.
> 
>      The drm_connector_(un)register calls also have to be removed
>      from the ps8640 driver."
> 
>      Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>      Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
>      Tested-by: PC Liao <pc.liao@mediatek.com>
>      Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>      Tested-by: Nicolas Boichat <drinkcat@chromium.org>
>      Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> 
> 
>      CHROMIUM: drm/bridge: ps8640: Add a 3 ms delay before unmuting output
> 
>      For current ps8640 firmware, the PS_GPIO9 signal only indicates the bridge
>      has seen the attached panel's HPD signal and read its EDID.  Unfortunately,
>      the bridge may not yet be ready to properly handle DSI/eDP traffic yet.
> 
>      For now, Paradetech has recommended adding a 3 ms delay after PS_GPIO9
>      before starting video signal transmission.
> 
>      Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>      Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> 
>      Tested-by: cawa cheng <cawa.cheng@mediatek.com>
>      Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>      Tested-by: jitao shi <jitao.shi@mediatek.com>
>      Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
>      Reviewed-by: jitao shi <jitao.shi@mediatek.com>
> 
> 
>      CHROMIUM: drm/bridge: ps8640: disable MIPI MCS
> 
>      Disable PS8640 MIPI MCS commands to workaround an issue where normal
>      MIPI DSI signals are sometimes recognized as an MSC command that can,
>      for example, disable the bridge output.
> 
>      Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>      Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>      Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> 
> 
>      CHROMIUM: drm/bridge: ps8640: Use individual regulators instead of bulk
> 
>      According to the latest information from Parade, the PS8640 1.2 V
>      supply must be enabled before 3.3 V.
>      So, split the bulk regulator into separate individual regulators that
>      can be enabled independently.
> 
>      Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> 
>      Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>      Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> 
> 
>      CHROMIUM: drm/bridge: ps8640: add 5ms delay between v12 and v33
> 
>      According to Parade, the PS8640 1.2V must be enabled 5 ms before its
>      3.3V. Otherwise, the PS8650 MCU may hang, and its settings cannot be
>      written correctly, leading to a black screen.
> 
>      Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
>      Tested-by: Daniel Kurtz <djkurtz@chromium.org>
>      Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> =============================
> 
> That keeps chronology and attribution intact, but is somewhat
> redundant. Any suggestions on how to digest it? Or should I just add
> it as is?
> 
> CU
> Uli
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [RFC v2 0/8] Acer Chromebook R13 support
  2017-10-18 15:57       ` Laurent Pinchart
@ 2017-10-18 16:07         ` Laurent Pinchart
  0 siblings, 0 replies; 18+ messages in thread
From: Laurent Pinchart @ 2017-10-18 16:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Ulrich,

On Wednesday, 18 October 2017 18:57:14 EEST Laurent Pinchart wrote:
> On Wednesday, 18 October 2017 17:53:54 EEST Ulrich Hecht wrote:
> > On Tue, Oct 17, 2017 at 6:05 PM, Sean Paul <seanpaul@chromium.org> wrote:
> > > On Tue, Oct 17, 2017 at 12:33:09PM +0200, Matthias Brugger wrote:
> > >> From what I understand you
> > >> rebased the patches from the chromium kernel to mainline. So you should
> > >> keep the signed-off-by from the original author and just add you
> > >> signed-off-by below that.
> > >> Also it would be nice to CC these persons so that they are aware of
> > >> your
> > >> effort.>
> > > 
> > > Additionally, make sure the author and commit messages are preserved
> > > when
> > > you send patches. You can add your own message in addition to your SoB,
> > > but please try to preserve history.
> > 
> > Fair enough, but I'm not sure what exactly to include. The chromium
> > commits include, among other things:
> > 
> > - bugtracker numbers and test cases
> > - "Change-Id" and "Commit-Ready" (no idea what those are)
> > - "Reviewed-on", containing links to chromium-review.googlesource.com
> > 
> > With all changes to the PS8640 driver concatenated and non-standard
> > tags removed, the commit message would look like this:
> > 
> > =============================
> > 
> >     CHROMIUM: drm/bridge: Add I2C based driver for ps8640 bridge
> >     
> >     This patch adds drm_bridge driver for parade DSI to eDP bridge chip.
> >     
> >     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> >     (am from https://patchwork.kernel.org/patch/8357851/)
> >     Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Tested-by: cawa cheng <cawa.cheng@mediatek.com>
> >     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
> >     
> >     
> >     FIXUP: FROMLIST: drm/bridge: Add I2C based driver for ps8640 bridge
> >     
> >     chromeos-3.18 currently has FROMLIST v15 of the PS8640 driver.
> >     This version is incompatible with UPSTREAM version of the Mediatek
> >     DRM driver.
> >     
> >     To quote Philipp Zabel:
> >     "The main DRM driver mtk_drm_drv now calls
> >     drm_connector_register_all() after drm_dev_register() in the
> >     mtk_drm_bind() function. That function should iterate over all
> >     connectors and call drm_connector_register() for each of them.
> >     The call to drm_connector_init() from mtk_hdmi_bridge_attach()
> >     should be enough to make this happen.
> >     
> >     The drm_connector_(un)register calls also have to be removed
> >     from the ps8640 driver."
> >     
> >     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> >     Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Tested-by: PC Liao <pc.liao@mediatek.com>
> >     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Tested-by: Nicolas Boichat <drinkcat@chromium.org>
> >     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> >     
> >     
> >     CHROMIUM: drm/bridge: ps8640: Add a 3 ms delay before unmuting output
> >     
> >     For current ps8640 firmware, the PS_GPIO9 signal only indicates the
> > 
> > bridge has seen the attached panel's HPD signal and read its EDID.
> > Unfortunately, the bridge may not yet be ready to properly handle DSI/eDP
> > traffic yet.
> > 
> >     For now, Paradetech has recommended adding a 3 ms delay after PS_GPIO9
> >     before starting video signal transmission.
> >     
> >     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> >     Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
> >     
> >     Tested-by: cawa cheng <cawa.cheng@mediatek.com>
> >     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Tested-by: jitao shi <jitao.shi@mediatek.com>
> >     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Reviewed-by: jitao shi <jitao.shi@mediatek.com>
> >     
> >     
> >     CHROMIUM: drm/bridge: ps8640: disable MIPI MCS
> >     
> >     Disable PS8640 MIPI MCS commands to workaround an issue where normal
> >     MIPI DSI signals are sometimes recognized as an MSC command that can,
> >     for example, disable the bridge output.
> >     
> >     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> >     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> >     
> >     
> >     CHROMIUM: drm/bridge: ps8640: Use individual regulators instead of
> >     bulk
> >     
> >     According to the latest information from Parade, the PS8640 1.2 V
> >     supply must be enabled before 3.3 V.
> >     So, split the bulk regulator into separate individual regulators that
> >     can be enabled independently.
> >     
> >     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> >     
> >     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> >     
> >     
> >     CHROMIUM: drm/bridge: ps8640: add 5ms delay between v12 and v33
> >     
> >     According to Parade, the PS8640 1.2V must be enabled 5 ms before its
> >     3.3V. Otherwise, the PS8650 MCU may hang, and its settings cannot be
> >     written correctly, leading to a black screen.
> >     
> >     Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
> >     Tested-by: Daniel Kurtz <djkurtz@chromium.org>
> >     Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> > 
> > =============================
> > 
> > That keeps chronology and attribution intact, but is somewhat
> > redundant. Any suggestions on how to digest it? Or should I just add
> > it as is?
> 
> I would keep all the SoB lines, but apart from that I don't think there's a
> need to copy all commit messages. You can extract relevant information for a
> digest, but there's no point in copying the whole history.

My comment obviously referred only to patches that add a new driver. For 
fixes, you should indeed not squash them all but submit them as individual 
patches. Some of them can be squashed as needed, for instance a change that is 
later reverted can be omitted completely.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2017-10-18 16:07 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-16 15:31 [RFC v2 0/8] Acer Chromebook R13 support Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 1/8] drm/bridge: GPIO-controlled display multiplexer driver Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 2/8] platform/chrome: ChromeOS firmware interface driver Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 3/8] drm/bridge: Parade PS8640 MIPI DSI -> eDP converter driver Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 4/8] drm/bridge: Analogix ANX7688 HDMI -> DP bridge driver Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 5/8] arm64: dts: mediatek: Add Elm Rev. 3 device tree Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 6/8] hack: mediatek: get mmsys to register as both DRM and clock device Ulrich Hecht
2017-10-16 15:31 ` [RFC v2 7/8] drm/mediatek: Add DRM-based framebuffer device Ulrich Hecht
2017-10-17  9:04   ` Philipp Zabel
2017-10-16 15:31 ` [RFC v2 8/8] drm: mediatek: Fix drm_of_find_panel_or_bridge conversion Ulrich Hecht
2017-10-17 10:33 ` [RFC v2 0/8] Acer Chromebook R13 support Matthias Brugger
2017-10-17 16:05   ` Sean Paul
2017-10-18 14:53     ` Ulrich Hecht
2017-10-18 15:57       ` Laurent Pinchart
2017-10-18 16:07         ` Laurent Pinchart
2017-10-18 15:58       ` Matthias Brugger
2017-10-17 16:38 ` Laurent Pinchart
2017-10-18 14:20   ` Matthias Brugger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).