linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [path v2 0/7] Add DRM driver for Hisilicon Hibmc
@ 2016-05-29  9:40 Rongrong Zou
  2016-05-29  9:40 ` [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver Rongrong Zou
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
base board management controller, usually it is used on server for
Out-of-band management purpose. In this patch set, we just support basic
function for Hibmc display subsystem. Hibmc display subsystem is connected
to host CPU by PCIe as blow:

+----------+       +----------+
|          | PCIe  |  Hibmc   |
|host CPU( |<----->| display  |
|arm64,x86)|       |subsystem |
+----------+       +----------+

Hardware Detail for Hibmc display subsystem
-----------

  The display subsystem of Hibmc is show as bellow:
  +----+      +----+      +----+     +--------+
  |    |      |    |      |    |     |        |
  | FB |----->| DE |----->|VDAC|---->|external|
  |    |      |    |      |    |     | VGA    |
  +----+      +----+      +----+     +--------+

  -DE(Display Engine) is the display controller.
  -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
  stream from DE to VGA analog signals.

Change History
------------

Changes in v2:
  -Remove self-defined macros for bit operations.
  -Remove unused register.
  -Replace those deprecated functions with new version of them.
  -use drm_connector_register_all() to register connector after
   drm_dev_register().

The patch v1 is at
https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
Sorry for too late sending.


Rongrong Zou (7):
  idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  drm/hisilicon/hibmc: Add plane for DE
  drm/hisilicon/hibmc: Add crtc for DE
  drm/hisilicon/hibmc: Add encoder for VDAC
  drm/hisilicon/hibmc: Add connector for VDAC
  drm/hisilicon/hibmc: Add support for frame buffer
  drm/hisilicon/hibmc: Add maintainer for Hibmc DRM

 MAINTAINERS                                       |   7 +
 drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
 drivers/gpu/drm/hisilicon/Makefile                |   3 +-
 drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
 drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c    | 477 ++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h    |  29 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 ++++++++
 14 files changed, 1789 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c

-- 
1.9.1

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

* [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-30  9:03   ` Daniel Vetter
  2016-05-29  9:40 ` [path v2 2/7] drm/hisilicon/hibmc: Add plane for DE Rongrong Zou
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Add DRM master driver for Hisilicon Hibmc SoC which used for
Out-of-band management. Blow is the general hardware connection,
both the Hibmc and the host CPU are on the same mother board.

+----------+       +----------+
|          | PCIe  |  Hibmc   |
|host CPU( |<----->| display  |
|arm64,x86)|       |subsystem |
+----------+       +----------+

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
 drivers/gpu/drm/hisilicon/Makefile                |   3 +-
 drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
 drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
 9 files changed, 699 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h

diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
index 558c61b..2fd2724 100644
--- a/drivers/gpu/drm/hisilicon/Kconfig
+++ b/drivers/gpu/drm/hisilicon/Kconfig
@@ -2,4 +2,5 @@
 # hisilicon drm device configuration.
 # Please keep this list sorted alphabetically
 
+source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
 source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
index e3f6d49..4d7185c 100644
--- a/drivers/gpu/drm/hisilicon/Makefile
+++ b/drivers/gpu/drm/hisilicon/Makefile
@@ -2,4 +2,5 @@
 # Makefile for hisilicon drm drivers.
 # Please keep this list sorted alphabetically
 
-obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
+obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
\ No newline at end of file
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
new file mode 100644
index 0000000..1e7810d
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -0,0 +1,13 @@
+config DRM_HISI_HIBMC
+	tristate "DRM Support for Hisilicon Hibmc"
+	depends on DRM && PCI
+	select DRM_KMS_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	help
+	  Choose this option if you have a Hisilicon Hibmc soc chipset.
+	  If M is selected the module will be called hibmc-drm.
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
new file mode 100644
index 0000000..533f9ed
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -0,0 +1,4 @@
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+
+obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
+#obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
new file mode 100644
index 0000000..7eaacd8
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -0,0 +1,307 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/console.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drmP.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+static const struct file_operations hibmc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+};
+
+static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	return 0;
+}
+
+static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+}
+
+static struct drm_driver hibmc_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
+	.fops			= &hibmc_fops,
+	.name			= "hibmc",
+	.desc			= "hibmc drm driver",
+	.major			= 1,
+	.minor			= 0,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.enable_vblank		= hibmc_enable_vblank,
+	.disable_vblank	= hibmc_disable_vblank,
+	.gem_free_object        = drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.dumb_create            = drm_gem_cma_dumb_create,
+	.dumb_map_offset        = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy           = drm_gem_dumb_destroy,
+};
+
+static int hibmc_pm_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	drm_kms_helper_poll_disable(drm_dev);
+
+	return 0;
+}
+
+static int hibmc_pm_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+
+	drm_helper_resume_force_mode(drm_dev);
+	drm_kms_helper_poll_enable(drm_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops hibmc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
+				hibmc_pm_resume)
+};
+
+static const struct drm_mode_config_funcs mode_config_funcs = {
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+
+static int hibmc_hw_config(struct hibmc_drm_device *hidev)
+{
+	unsigned int reg;
+
+	/* On hardware reset, power mode 0 is default. */
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+
+	hibmc_set_current_gate(hidev, reg);
+
+	/* Reset the memory controller. If the memory controller
+	 * is not reset in chip,the system might hang when sw accesses
+	 * the memory.The memory should be resetted after
+	 * changing the MXCLK.
+	 */
+	reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
+	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
+	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
+
+	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
+
+	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
+
+	/* We can add more initialization as needed. */
+
+	return 0;
+}
+
+static int hibmc_hw_map(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct pci_dev *pdev = dev->pdev;
+	resource_size_t addr, size, ioaddr, iosize;
+
+	ioaddr = pci_resource_start(pdev, 1);
+	iosize = MB(2);
+
+	hidev->mmio = ioremap_nocache(ioaddr, iosize);
+
+	if (!hidev->mmio) {
+		DRM_ERROR("Cannot map mmio region\n");
+		return -ENOMEM;
+	}
+
+	addr = pci_resource_start(pdev, 0);
+	size = MB(16);
+
+	hidev->fb_map = ioremap(addr, size);
+	if (!hidev->fb_map) {
+		DRM_ERROR("Cannot map framebuffer\n");
+		return -ENOMEM;
+	}
+	hidev->fb_base = addr;
+	hidev->fb_size = size;
+
+	return 0;
+}
+
+static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
+{
+	if (hidev->mmio)
+		iounmap(hidev->mmio);
+	if (hidev->fb_map)
+		iounmap(hidev->fb_map);
+}
+
+static int hibmc_hw_init(struct hibmc_drm_device *hidev)
+{
+	int ret;
+
+	ret = hibmc_hw_map(hidev);
+	if (ret)
+		return ret;
+
+	hibmc_hw_config(hidev);
+
+	return 0;
+}
+
+static int hibmc_unload(struct drm_device *dev)
+{
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	hibmc_hw_fini(hidev);
+	dev->dev_private = NULL;
+	return 0;
+}
+
+static int hibmc_load(struct drm_device *dev, unsigned long flags)
+{
+	struct hibmc_drm_device *hidev;
+	int ret;
+
+	hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
+	if (!hidev)
+		return -ENOMEM;
+	dev->dev_private = hidev;
+	hidev->dev = dev;
+
+	ret = hibmc_hw_init(hidev);
+	if (ret)
+		goto err;
+
+
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+	if (ret) {
+		DRM_ERROR("failed to initialize vblank.\n");
+		return ret;
+	}
+	/* reset all the states of crtc/plane/encoder/connector */
+	drm_mode_config_reset(dev);
+
+	return 0;
+
+err:
+	hibmc_unload(dev);
+	DRM_ERROR("failed to initialize drm driver.\n");
+	return ret;
+}
+
+
+static int hibmc_pci_probe(struct pci_dev *pdev,
+			   const struct pci_device_id *ent)
+{
+	struct drm_device *dev;
+	int ret;
+
+	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->pdev = pdev;
+	pci_set_drvdata(pdev, dev);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto err_free;
+
+	ret = hibmc_load(dev, 0);
+	if (ret)
+		goto err_disable;
+
+	ret = drm_dev_register(dev, 0);
+	if (ret)
+		goto err_unload;
+
+	return 0;
+
+err_unload:
+	hibmc_unload(dev);
+err_disable:
+	pci_disable_device(pdev);
+err_free:
+	drm_dev_unref(dev);
+
+	return ret;
+}
+
+static void hibmc_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_dev_unregister(dev);
+	hibmc_unload(dev);
+	drm_dev_unref(dev);
+}
+
+static struct pci_device_id hibmc_pci_table[] = {
+	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+static struct pci_driver hibmc_pci_driver = {
+	.name =		"hibmc-drm",
+	.id_table =	hibmc_pci_table,
+	.probe =	hibmc_pci_probe,
+	.remove =	hibmc_pci_remove,
+	.driver.pm =    &hibmc_pm_ops,
+};
+
+static int __init hibmc_init(void)
+{
+	return pci_register_driver(&hibmc_pci_driver);
+}
+
+static void __exit hibmc_exit(void)
+{
+	return pci_unregister_driver(&hibmc_pci_driver);
+}
+
+module_init(hibmc_init);
+module_exit(hibmc_exit);
+
+MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
+MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
+MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
new file mode 100644
index 0000000..a072ea9
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -0,0 +1,39 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DRV_H
+#define HIBMC_DRM_DRV_H
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+struct hibmc_drm_device {
+	/* hw */
+	void __iomem   *mmio;
+	void __iomem   *fb_map;
+	unsigned long  fb_base;
+	unsigned long  fb_size;
+
+	/* drm */
+	struct drm_device  *dev;
+	bool mode_config_initialized;
+};
+
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
new file mode 100644
index 0000000..673be10
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
@@ -0,0 +1,91 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/io.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+/*
+ * It can operate in one of three modes: 0, 1 or Sleep.
+ */
+void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
+				 unsigned int power_mode)
+{
+	unsigned int control_value = 0;
+	void __iomem   *mmio = hidev->mmio;
+
+	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
+		return;
+
+	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
+	control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
+
+	control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
+			 HIBMC_PW_MODE_CTL_MODE_MASK;
+
+
+    /* Set up other fields in Power Control Register */
+	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
+		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
+				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+	} else {
+		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
+				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
+
+	}
+    /* Program new power mode. */
+	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
+}
+
+static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
+{
+	void __iomem   *mmio = hidev->mmio;
+
+	return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
+		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
+}
+
+void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
+{
+	unsigned int gate_reg;
+	unsigned int mode;
+	void __iomem   *mmio = hidev->mmio;
+
+	/* Get current power mode. */
+	mode = hibmc_get_power_mode(hidev);
+
+	switch (mode) {
+	case HIBMC_PW_MODE_CTL_MODE_MODE0:
+		gate_reg = HIBMC_MODE0_GATE;
+		break;
+
+	case HIBMC_PW_MODE_CTL_MODE_MODE1:
+		gate_reg = HIBMC_MODE1_GATE;
+		break;
+
+	default:
+		gate_reg = HIBMC_MODE0_GATE;
+		break;
+	}
+	writel(gate, mmio + gate_reg);
+}
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
new file mode 100644
index 0000000..39f7a17
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
@@ -0,0 +1,28 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_POWER_H
+#define HIBMC_DRM_POWER_H
+
+#include "hibmc_drm_drv.h"
+
+extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
+				 unsigned int power_mode);
+extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
+				   unsigned int gate);
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
new file mode 100644
index 0000000..4966c42
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
@@ -0,0 +1,214 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_HW_H
+#define HIBMC_DRM_HW_H
+
+#define OFF 0
+#define ON  1
+#define DISABLE               0
+#define ENABLE                1
+
+
+
+/* register definition */
+#define HIBMC_MISC_CTRL				0x4
+
+#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
+#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
+
+#define RESET                0
+#define NORMAL               1
+
+#define HIBMC_CURRENT_GATE			0x000040
+#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
+#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
+
+#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
+#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
+
+#define HIBMC_MODE0_GATE			0x000044
+#define HIBMC_MODE1_GATE			0x000048
+#define HIBMC_POWER_MODE_CTRL			0x00004C
+
+#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
+#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
+
+#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
+#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
+#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
+
+
+#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
+#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
+#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
+
+#define HIBMC_PANEL_PLL_CTRL			0x00005C
+#define HIBMC_CRT_PLL_CTRL			0x000060
+
+#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
+#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
+
+#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
+#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
+
+#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
+#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
+
+#define OSC					0
+#define TESTCLK					1
+
+#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
+#define HIBMC_PLL_CTRL_POD_MASK			0xC000
+
+#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
+#define HIBMC_PLL_CTRL_OD_MASK			0x3000
+
+#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
+#define HIBMC_PLL_CTRL_N_MASK			0xF00
+
+#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
+#define HIBMC_PLL_CTRL_M_MASK			0xFF
+
+
+#define HIBMC_CRT_DISP_CTL			0x80200
+
+#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
+#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
+
+#define CRTSELECT_VGA                0
+#define CRTSELECT_CRT                1
+
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
+
+#define PHASE_ACTIVE_HIGH      0
+#define PHASE_ACTIVE_LOW       1
+
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
+
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
+
+#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
+#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
+
+
+#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
+#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
+
+#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
+#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
+
+
+
+#define HIBMC_CRT_FB_ADDRESS			0x080204
+
+#define HIBMC_CRT_FB_WIDTH			0x080208
+#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
+#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
+#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
+#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
+
+
+#define HIBMC_CRT_HORZ_TOTAL			0x08020C
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
+
+
+#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)	((x) << 0)
+#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK	0xFFF
+
+#define HIBMC_CRT_HORZ_SYNC			0x080210
+#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
+#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
+
+#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
+#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
+
+#define HIBMC_CRT_VERT_TOTAL			0x080214
+#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
+#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
+
+#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)	((x) << 0)
+#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK	0x7FF
+
+#define HIBMC_CRT_VERT_SYNC			0x080218
+#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
+#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
+
+
+#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
+#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
+
+/* Auto Centering */
+#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK	0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK	0x7FF
+
+#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
+
+/* register to control panel output */
+#define DISPLAY_CONTROL_HISILE			0x80288
+
+/* register and values for PLL control */
+#define CRT_PLL1_HS				0x802a8
+#define CRT_PLL1_HS_25MHZ			0x23d40f02
+#define CRT_PLL1_HS_40MHZ			0x23940801
+#define CRT_PLL1_HS_65MHZ			0x23940d01
+#define CRT_PLL1_HS_78MHZ			0x23540F82
+#define CRT_PLL1_HS_74MHZ			0x23941dc2
+#define CRT_PLL1_HS_80MHZ			0x23941001
+#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
+#define CRT_PLL1_HS_108MHZ			0x23b41b01
+#define CRT_PLL1_HS_162MHZ			0x23480681
+#define CRT_PLL1_HS_148MHZ			0x23541dc2
+#define CRT_PLL1_HS_193MHZ			0x234807c1
+
+#define CRT_PLL2_HS				0x802ac
+#define CRT_PLL2_HS_25MHZ			0x206B851E
+#define CRT_PLL2_HS_40MHZ			0x30000000
+#define CRT_PLL2_HS_65MHZ			0x40000000
+#define CRT_PLL2_HS_78MHZ			0x50E147AE
+#define CRT_PLL2_HS_74MHZ			0x602B6AE7
+#define CRT_PLL2_HS_80MHZ			0x70000000
+#define CRT_PLL2_HS_108MHZ			0x80000000
+#define CRT_PLL2_HS_162MHZ			0xA0000000
+#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
+#define CRT_PLL2_HS_193MHZ			0xC0872B02
+
+/* Global macros */
+#define RGB(r, g, b) \
+( \
+	(unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
+)
+
+#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
+
+#define MB(x) ((x) << 20)
+
+#endif
-- 
1.9.1

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

* [path v2 2/7] drm/hisilicon/hibmc: Add plane for DE
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
  2016-05-29  9:40 ` [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-29  9:40 ` [path v2 3/7] drm/hisilicon/hibmc: Add crtc " Rongrong Zou
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Add plane funcs and helper funcs for DE.

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile        |   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  | 170 ++++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |  41 +++++-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |   3 +
 4 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 533f9ed..faa7e64 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o
 
 obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
 #obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
new file mode 100644
index 0000000..e8e5853
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -0,0 +1,170 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+#include "hibmc_drm_power.h"
+
+/* ---------------------------------------------------------------------- */
+
+static int hibmc_plane_prepare_fb(struct drm_plane *plane,
+		       const struct drm_plane_state *new_state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static void hibmc_plane_cleanup_fb(struct drm_plane *plane,
+				   const struct drm_plane_state *old_state)
+{
+	/* do nothing */
+}
+
+static int hibmc_plane_atomic_check(struct drm_plane *plane,
+				    struct drm_plane_state *state)
+{
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	u32 src_x = state->src_x >> 16;
+	u32 src_y = state->src_y >> 16;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+	int crtc_x = state->crtc_x;
+	int crtc_y = state->crtc_y;
+	u32 crtc_w = state->crtc_w;
+	u32 crtc_h = state->crtc_h;
+
+	if (!crtc || !fb)
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	if (src_w != crtc_w || src_h != crtc_h) {
+		DRM_ERROR("Scale not support!!!\n");
+		return -EINVAL;
+	}
+
+	if (src_x + src_w > fb->width ||
+	    src_y + src_h > fb->height)
+		return -EINVAL;
+
+	if (crtc_x < 0 || crtc_y < 0)
+		return -EINVAL;
+
+	if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+	    crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void hibmc_plane_atomic_update(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
+{
+	struct drm_plane_state	*state	= plane->state;
+	u32 reg;
+	unsigned int line_l;
+	struct hibmc_drm_device *hidev =
+		(struct hibmc_drm_device *)plane->dev->dev_private;
+
+	/* now just support one plane */
+	writel(0, hidev->mmio + HIBMC_CRT_FB_ADDRESS);
+	reg = state->fb->width * (state->fb->bits_per_pixel >> 3);
+	/* now line_pad is 16 */
+	reg = PADDING(16, reg);
+
+	line_l = state->fb->width * state->fb->bits_per_pixel / 8;
+	line_l = PADDING(16, line_l);
+	writel((HIBMC_CRT_FB_WIDTH_WIDTH(reg) & HIBMC_CRT_FB_WIDTH_WIDTH_MASK) |
+	       (HIBMC_CRT_FB_WIDTH_OFFS(line_l) & HIBMC_CRT_FB_WIDTH_OFFS_MASK),
+	       hidev->mmio + HIBMC_CRT_FB_WIDTH);
+
+	/* SET PIXEL FORMAT */
+	reg = readl(hidev->mmio + HIBMC_CRT_DISP_CTL);
+	reg = reg & ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
+	reg = reg | (HIBMC_CRT_DISP_CTL_FORMAT(state->fb->bits_per_pixel >> 4) &
+		     HIBMC_CRT_DISP_CTL_FORMAT_MASK);
+	writel(reg, hidev->mmio + HIBMC_CRT_DISP_CTL);
+}
+
+static void hibmc_plane_atomic_disable(struct drm_plane *plane,
+				       struct drm_plane_state *old_state)
+{
+}
+
+static const u32 channel_formats1[] = {
+	DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888
+};
+
+static struct drm_plane_funcs hibmc_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
+	.prepare_fb = hibmc_plane_prepare_fb,
+	.cleanup_fb = hibmc_plane_cleanup_fb,
+	.atomic_check = hibmc_plane_atomic_check,
+	.atomic_update = hibmc_plane_atomic_update,
+	.atomic_disable = hibmc_plane_atomic_disable,
+};
+
+int hibmc_plane_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_plane *plane = &hidev->plane;
+	int ret = 0;
+
+	/*
+	 * plane init
+	 * TODO: Now only support primary plane, overlay planes
+	 * need to do.
+	 */
+	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
+				       channel_formats1,
+				       ARRAY_SIZE(channel_formats1),
+				       DRM_PLANE_TYPE_PRIMARY,
+				       NULL);
+	if (ret) {
+		DRM_ERROR("fail to init plane!!!\n");
+		return ret;
+	}
+
+	drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 7eaacd8..794250a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -51,7 +51,8 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
 }
 
 static struct drm_driver hibmc_driver = {
-	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
+						DRIVER_ATOMIC,
 	.fops			= &hibmc_fops,
 	.name			= "hibmc",
 	.desc			= "hibmc drm driver",
@@ -98,6 +99,40 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
+static int hibmc_kms_init(struct hibmc_drm_device *hidev)
+{
+	int ret;
+
+	drm_mode_config_init(hidev->dev);
+	hidev->mode_config_initialized = true;
+
+	hidev->dev->mode_config.min_width = 0;
+	hidev->dev->mode_config.min_height = 0;
+	hidev->dev->mode_config.max_width = 1920;
+	hidev->dev->mode_config.max_height = 1440;
+
+	hidev->dev->mode_config.fb_base = hidev->fb_base;
+	hidev->dev->mode_config.preferred_depth = 24;
+	hidev->dev->mode_config.prefer_shadow = 0;
+
+	hidev->dev->mode_config.funcs = (void *)&mode_config_funcs;
+
+	ret = hibmc_plane_init(hidev);
+	if (ret) {
+		DRM_ERROR("fail to init plane!!!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void hibmc_kms_fini(struct hibmc_drm_device *hidev)
+{
+	if (hidev->mode_config_initialized) {
+		drm_mode_config_cleanup(hidev->dev);
+		hidev->mode_config_initialized = false;
+	}
+}
 
 static int hibmc_hw_config(struct hibmc_drm_device *hidev)
 {
@@ -190,6 +225,7 @@ static int hibmc_unload(struct drm_device *dev)
 {
 	struct hibmc_drm_device *hidev = dev->dev_private;
 
+	hibmc_kms_fini(hidev);
 	hibmc_hw_fini(hidev);
 	dev->dev_private = NULL;
 	return 0;
@@ -210,6 +246,9 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
 	if (ret)
 		goto err;
 
+	ret = hibmc_kms_init(hidev);
+	if (ret)
+		goto err;
 
 	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 	if (ret) {
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index a072ea9..6c7985d 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -32,8 +32,11 @@ struct hibmc_drm_device {
 
 	/* drm */
 	struct drm_device  *dev;
+	struct drm_plane plane;
 	bool mode_config_initialized;
 };
 
+int hibmc_plane_init(struct hibmc_drm_device *hidev);
+
 
 #endif
-- 
1.9.1

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

* [path v2 3/7] drm/hisilicon/hibmc: Add crtc for DE
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
  2016-05-29  9:40 ` [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver Rongrong Zou
  2016-05-29  9:40 ` [path v2 2/7] drm/hisilicon/hibmc: Add plane for DE Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-29  9:40 ` [path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC Rongrong Zou
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Add crtc funcs and helper funcs for DE.

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c  | 307 ++++++++++++++++++++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h  |  29 +++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c |   6 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h |   2 +
 4 files changed, 344 insertions(+)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
index e8e5853..87a7e52 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
@@ -26,6 +26,7 @@
 
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
+#include "hibmc_drm_de.h"
 #include "hibmc_drm_power.h"
 
 /* ---------------------------------------------------------------------- */
@@ -168,3 +169,309 @@ int hibmc_plane_init(struct hibmc_drm_device *hidev)
 	return 0;
 }
 
+static void hibmc_crtc_enable(struct drm_crtc *crtc)
+{
+	unsigned int reg;
+	/* power mode 0 is default. */
+	struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+	hibmc_set_current_gate(hidev, reg);
+}
+
+static void hibmc_crtc_disable(struct drm_crtc *crtc)
+{
+	unsigned int reg;
+	struct hibmc_drm_device *hidev = crtc->dev->dev_private;
+
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_SLEEP);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg |= HIBMC_CURR_GATE_LOCALMEM(OFF);
+	reg |= HIBMC_CURR_GATE_DISPLAY(OFF);
+	hibmc_set_current_gate(hidev, reg);
+}
+
+static int hibmc_crtc_atomic_check(struct drm_crtc *crtc,
+			    struct drm_crtc_state *state)
+{
+	return 0;
+}
+
+static unsigned int format_pll_reg(void)
+{
+	unsigned int pllreg = 0;
+	struct panel_pll pll = {0};
+
+	/* Note that all PLL's have the same format. Here,
+	* we just use Panel PLL parameter to work out the bit
+	* fields in the register.On returning a 32 bit number, the value can
+	* be applied to any PLL in the calling function.
+	*/
+	pllreg |= HIBMC_PLL_CTRL_BYPASS(OFF) & HIBMC_PLL_CTRL_BYPASS_MASK;
+	pllreg |= HIBMC_PLL_CTRL_POWER(ON) & HIBMC_PLL_CTRL_POWER_MASK;
+	pllreg |= HIBMC_PLL_CTRL_INPUT(OSC) & HIBMC_PLL_CTRL_INPUT_MASK;
+	pllreg |= HIBMC_PLL_CTRL_POD(pll.POD) & HIBMC_PLL_CTRL_POD_MASK;
+	pllreg |= HIBMC_PLL_CTRL_OD(pll.OD) & HIBMC_PLL_CTRL_OD_MASK;
+	pllreg |= HIBMC_PLL_CTRL_N(pll.N) & HIBMC_PLL_CTRL_N_MASK;
+	pllreg |= HIBMC_PLL_CTRL_M(pll.M) & HIBMC_PLL_CTRL_M_MASK;
+
+	return pllreg;
+}
+
+static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll)
+{
+	unsigned long tmp0, tmp1;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+    /* 1. outer_bypass_n=0 */
+	tmp0 = readl(hidev->mmio + CRT_PLL1_HS);
+	tmp0 &= 0xBFFFFFFF;
+	writel(tmp0, hidev->mmio + CRT_PLL1_HS);
+
+	/* 2. pll_pd=1?inter_bypass=1 */
+	writel(0x21000000, hidev->mmio + CRT_PLL1_HS);
+
+	/* 3. config pll */
+	writel(pll, hidev->mmio + CRT_PLL1_HS);
+
+	/* 4. delay  */
+	mdelay(1);
+
+	/* 5. pll_pd =0 */
+	tmp1 = pll & ~0x01000000;
+	writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+	/* 6. delay  */
+	mdelay(1);
+
+	/* 7. inter_bypass=0 */
+	tmp1 &= ~0x20000000;
+	writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+
+	/* 8. delay  */
+	mdelay(1);
+
+	/* 9. outer_bypass_n=1 */
+	tmp1 |= 0x40000000;
+	writel(tmp1, hidev->mmio + CRT_PLL1_HS);
+}
+
+/* This function takes care the extra registers and bit fields required to
+*setup a mode in board.
+*Explanation about Display Control register:
+*FPGA only supports 7 predefined pixel clocks, and clock select is
+*in bit 4:0 of new register 0x802a8.
+*/
+static unsigned int display_ctrl_adjust(struct drm_device *dev,
+				struct drm_display_mode *mode,
+				unsigned int ctrl)
+{
+	unsigned long x, y;
+	unsigned long pll1; /* bit[31:0] of PLL */
+	unsigned long pll2; /* bit[63:32] of PLL */
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	x = mode->hdisplay;
+	y = mode->vdisplay;
+
+	/* Hisilicon has to set up a new register for PLL control
+	 *(CRT_PLL1_HS & CRT_PLL2_HS).
+	 */
+	if (x == 800 && y == 600) {
+		pll1 = CRT_PLL1_HS_40MHZ;
+		pll2 = CRT_PLL2_HS_40MHZ;
+	} else if (x == 1024 && y == 768) {
+		pll1 = CRT_PLL1_HS_65MHZ;
+		pll2 = CRT_PLL2_HS_65MHZ;
+	} else if (x == 1152 && y == 864) {
+		pll1 = CRT_PLL1_HS_80MHZ_1152;
+		pll2 = CRT_PLL2_HS_80MHZ;
+	} else if (x == 1280 && y == 768) {
+		pll1 = CRT_PLL1_HS_80MHZ;
+		pll2 = CRT_PLL2_HS_80MHZ;
+	} else if (x == 1280 && y == 720) {
+		pll1 = CRT_PLL1_HS_74MHZ;
+		pll2 = CRT_PLL2_HS_74MHZ;
+	} else if (x == 1280 && y == 960) {
+		pll1 = CRT_PLL1_HS_108MHZ;
+		pll2 = CRT_PLL2_HS_108MHZ;
+	} else if (x == 1280 && y == 1024) {
+		pll1 = CRT_PLL1_HS_108MHZ;
+		pll2 = CRT_PLL2_HS_108MHZ;
+	} else if (x == 1600 && y == 1200) {
+		pll1 = CRT_PLL1_HS_162MHZ;
+		pll2 = CRT_PLL2_HS_162MHZ;
+	} else if (x == 1920 && y == 1080) {
+		pll1 = CRT_PLL1_HS_148MHZ;
+		pll2 = CRT_PLL2_HS_148MHZ;
+	} else if (x == 1920 && y == 1200) {
+		pll1 = CRT_PLL1_HS_193MHZ;
+		pll2 = CRT_PLL2_HS_193MHZ;
+	} else /* default to VGA clock */ {
+		pll1 = CRT_PLL1_HS_25MHZ;
+		pll2 = CRT_PLL2_HS_25MHZ;
+	}
+
+	writel(pll2, hidev->mmio + CRT_PLL2_HS);
+	set_vclock_hisilicon(dev, pll1);
+
+	/* Hisilicon has to set up the top-left and bottom-right
+	 * registers as well.
+	 * Note that normal chip only use those two register for
+	 * auto-centering mode.
+	 */
+	writel((HIBMC_CRT_AUTO_CENTERING_TL_TOP(0) &
+		HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK) |
+	       (HIBMC_CRT_AUTO_CENTERING_TL_LEFT(0) &
+		HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK),
+	       hidev->mmio + HIBMC_CRT_AUTO_CENTERING_TL);
+
+	writel((HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(y - 1) &
+		HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK) |
+	       (HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x - 1) &
+		HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK),
+		hidev->mmio + HIBMC_CRT_AUTO_CENTERING_BR);
+
+	/* Assume common fields in ctrl have been properly set before
+	 * calling this function.
+	 * This function only sets the extra fields in ctrl.
+	 */
+
+	/* Set bit 25 of display controller: Select CRT or VGA clock */
+	ctrl &= ~HIBMC_CRT_DISP_CTL_CRTSELECT_MASK;
+	ctrl &= ~HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK;
+
+	ctrl |= HIBMC_CRT_DISP_CTL_CRTSELECT(CRTSELECT_CRT);
+
+	/*ctrl = FIELD_SET(ctrl, HIBMC_CRT_DISP_CTL, CRTSELECT, CRT);*/
+
+	/* Set bit 14 of display controller */
+	/*ctrl &= FIELD_CLEAR(HIBMC_CRT_DISP_CTL, CLOCK_PHASE);*/
+
+	/* clock_phase_polarity is 0 */
+	ctrl |= HIBMC_CRT_DISP_CTL_CLOCK_PHASE(PHASE_ACTIVE_HIGH);
+	/*ctrl = FIELD_SET(ctrl, HIBMC_CRT_DISP_CTL,*/
+	/*CLOCK_PHASE, ACTIVE_HIGH);*/
+
+	writel(ctrl, hidev->mmio + HIBMC_CRT_DISP_CTL);
+
+	return ctrl;
+}
+
+static void hibmc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	unsigned int val;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	struct drm_device *dev = crtc->dev;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	writel(format_pll_reg(), hidev->mmio + HIBMC_CRT_PLL_CTRL);
+	writel((HIBMC_CRT_HORZ_TOTAL_TOTAL(mode->htotal - 1) &
+		HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK) |
+		(HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(mode->hdisplay - 1) &
+		HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK),
+		hidev->mmio + HIBMC_CRT_HORZ_TOTAL);
+
+	writel((HIBMC_CRT_HORZ_SYNC_WIDTH(mode->hsync_end - mode->hsync_start)
+		& HIBMC_CRT_HORZ_SYNC_WIDTH_MASK) |
+		(HIBMC_CRT_HORZ_SYNC_START(mode->hsync_start - 1)
+		& HIBMC_CRT_HORZ_SYNC_START_MASK),
+		hidev->mmio + HIBMC_CRT_HORZ_SYNC);
+
+	writel((HIBMC_CRT_VERT_TOTAL_TOTAL(mode->vtotal - 1) &
+		HIBMC_CRT_VERT_TOTAL_TOTAL_MASK) |
+		(HIBMC_CRT_VERT_TOTAL_DISPLAY_END(mode->vdisplay - 1) &
+		HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK),
+		hidev->mmio + HIBMC_CRT_VERT_TOTAL);
+
+	writel((HIBMC_CRT_VERT_SYNC_HEIGHT(mode->vsync_end - mode->vsync_start)
+		& HIBMC_CRT_VERT_SYNC_HEIGHT_MASK) |
+	       (HIBMC_CRT_VERT_SYNC_START(mode->vsync_start - 1) &
+		HIBMC_CRT_VERT_SYNC_START_MASK),
+		hidev->mmio + HIBMC_CRT_VERT_SYNC);
+
+	val = HIBMC_CRT_DISP_CTL_VSYNC_PHASE(0) &
+	      HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK;
+	val |= HIBMC_CRT_DISP_CTL_HSYNC_PHASE(0) &
+	       HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK;
+	val |= HIBMC_CRT_DISP_CTL_TIMING(ENABLE);
+	val |= HIBMC_CRT_DISP_CTL_PLANE(ENABLE);
+
+	display_ctrl_adjust(dev, mode, val);
+}
+
+static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	unsigned int reg;
+	struct drm_device *dev = crtc->dev;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
+	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
+	hibmc_set_current_gate(hidev, reg);
+
+	/* We can add more initialization as needed. */
+}
+
+static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+
+{
+}
+
+/* These provide the minimum set of functions required to handle a CRTC */
+static const struct drm_crtc_funcs hibmc_crtc_funcs = {
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_atomic_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state =  drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
+	.enable		= hibmc_crtc_enable,
+	.disable	= hibmc_crtc_disable,
+	.mode_set_nofb	= hibmc_crtc_mode_set_nofb,
+	.atomic_check	= hibmc_crtc_atomic_check,
+	.atomic_begin	= hibmc_crtc_atomic_begin,
+	.atomic_flush	= hibmc_crtc_atomic_flush,
+};
+
+int hibmc_crtc_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_crtc *crtc = &hidev->crtc;
+	struct drm_plane *plane = &hidev->plane;
+	int ret;
+
+	ret = drm_crtc_init_with_planes(dev, crtc, plane,
+					NULL, &hibmc_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init crtc.\n");
+		return ret;
+	}
+
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+	drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs);
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
new file mode 100644
index 0000000..c22f0a4
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
@@ -0,0 +1,29 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef HIBMC_DRM_DE_H
+#define HIBMC_DRM_DE_H
+
+struct panel_pll {
+	unsigned long M;
+	unsigned long N;
+	unsigned long OD;
+	unsigned long POD;
+};
+
+#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 794250a..f7837cc 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -123,6 +123,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
 		return ret;
 	}
 
+	ret = hibmc_crtc_init(hidev);
+	if (ret) {
+		DRM_ERROR("failed to init crtc.\n");
+		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 6c7985d..e64ec8d 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -33,10 +33,12 @@ struct hibmc_drm_device {
 	/* drm */
 	struct drm_device  *dev;
 	struct drm_plane plane;
+	struct drm_crtc crtc;
 	bool mode_config_initialized;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
+int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 
 
 #endif
-- 
1.9.1

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

* [path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
                   ` (2 preceding siblings ...)
  2016-05-29  9:40 ` [path v2 3/7] drm/hisilicon/hibmc: Add crtc " Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-29  9:40 ` [path v2 5/7] drm/hisilicon/hibmc: Add connector " Rongrong Zou
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Add encoder funcs and helpers for VDAC.

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile         |  2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c  |  6 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  |  2 +
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 85 ++++++++++++++++++++++++
 4 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index faa7e64..4e7797a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_power.o
 
 obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
 #obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index f7837cc..962072f 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -129,6 +129,12 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
 		return ret;
 	}
 
+	ret = hibmc_encoder_init(hidev);
+	if (ret) {
+		DRM_ERROR("failed to init encoder\n");
+		return ret;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index e64ec8d..d0c5982 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -34,11 +34,13 @@ struct hibmc_drm_device {
 	struct drm_device  *dev;
 	struct drm_plane plane;
 	struct drm_crtc crtc;
+	struct drm_encoder encoder;
 	bool mode_config_initialized;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
+int hibmc_encoder_init(struct hibmc_drm_device *hidev);
 
 
 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
new file mode 100644
index 0000000..cb9a130
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -0,0 +1,85 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drmP.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+
+static void hibmc_encoder_disable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_enable(struct drm_encoder *encoder)
+{
+}
+
+static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adj_mode)
+{
+	u32 reg;
+	struct drm_device *dev = encoder->dev;
+	struct hibmc_drm_device *hidev = dev->dev_private;
+
+	/* just open DISPLAY_CONTROL_HISILE register bit 3:0*/
+	reg = readl(hidev->mmio + DISPLAY_CONTROL_HISILE);
+	reg |= 0xf;
+	writel(reg, hidev->mmio + DISPLAY_CONTROL_HISILE);
+}
+
+static int hibmc_encoder_atomic_check(struct drm_encoder *encoder,
+				      struct drm_crtc_state *crtc_state,
+				      struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
+	.mode_set = hibmc_encoder_mode_set,
+	.disable = hibmc_encoder_disable,
+	.enable = hibmc_encoder_enable,
+	.atomic_check = hibmc_encoder_atomic_check,
+};
+
+static const struct drm_encoder_funcs hibmc_encoder_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int hibmc_encoder_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_encoder *encoder = &hidev->encoder;
+	int ret;
+
+	encoder->possible_crtcs = 0x1;
+	ret = drm_encoder_init(dev, encoder, &hibmc_encoder_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init encoder\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
+	return 0;
+}
+
-- 
1.9.1

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

* [path v2 5/7] drm/hisilicon/hibmc: Add connector for VDAC
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
                   ` (3 preceding siblings ...)
  2016-05-29  9:40 ` [path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-29  9:40 ` [path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer Rongrong Zou
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Add connector funcs and helper funcs for VDAC.

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c  | 21 ++++++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h  |  3 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 89 ++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 962072f..70d79d2 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -135,6 +135,14 @@ static int hibmc_kms_init(struct hibmc_drm_device *hidev)
 		return ret;
 	}
 
+	ret = hibmc_connector_init(hidev);
+	if (ret) {
+		DRM_ERROR("failed to init connector\n");
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&hidev->connector,
+					  &hidev->encoder);
 	return 0;
 }
 
@@ -278,6 +286,12 @@ err:
 	return ret;
 }
 
+static void hibmc_connector_unplug_all(struct drm_device *dev)
+{
+	mutex_lock(&dev->mode_config.mutex);
+	drm_connector_unregister_all(dev);
+	mutex_unlock(&dev->mode_config.mutex);
+}
 
 static int hibmc_pci_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
@@ -304,8 +318,14 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
 	if (ret)
 		goto err_unload;
 
+	ret = drm_connector_register_all(dev);
+	if (ret)
+		goto err_unregister;
+
 	return 0;
 
+err_unregister:
+	drm_dev_unregister(dev);
 err_unload:
 	hibmc_unload(dev);
 err_disable:
@@ -320,6 +340,7 @@ static void hibmc_pci_remove(struct pci_dev *pdev)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
 
+	hibmc_connector_unplug_all(dev);
 	drm_dev_unregister(dev);
 	hibmc_unload(dev);
 	drm_dev_unref(dev);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index d0c5982..eb5a892 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -35,12 +35,13 @@ struct hibmc_drm_device {
 	struct drm_plane plane;
 	struct drm_crtc crtc;
 	struct drm_encoder encoder;
+	struct drm_connector connector;
 	bool mode_config_initialized;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 int hibmc_encoder_init(struct hibmc_drm_device *hidev);
-
+int hibmc_connector_init(struct hibmc_drm_device *hidev);
 
 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index cb9a130..b39ec65 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -24,6 +24,13 @@
 #include "hibmc_drm_drv.h"
 #include "hibmc_drm_regs.h"
 
+static int defx = 800;
+static int defy = 600;
+
+module_param(defx, int, 0444);
+module_param(defy, int, 0444);
+MODULE_PARM_DESC(defx, "default x resolution");
+MODULE_PARM_DESC(defy, "default y resolution");
 
 static void hibmc_encoder_disable(struct drm_encoder *encoder)
 {
@@ -83,3 +90,85 @@ int hibmc_encoder_init(struct hibmc_drm_device *hidev)
 	return 0;
 }
 
+static int hibmc_connector_get_modes(struct drm_connector *connector)
+{
+	int count;
+
+	count = drm_add_modes_noedid(connector, 800, 600);
+	drm_set_preferred_mode(connector, defx, defy);
+	return count;
+}
+
+static int hibmc_connector_mode_valid(struct drm_connector *connector,
+				      struct drm_display_mode *mode)
+{
+	struct hibmc_drm_device *hiprivate =
+	 container_of(connector, struct hibmc_drm_device, connector);
+	unsigned long size = mode->hdisplay * mode->vdisplay * 4;
+
+	/*
+	* Make sure we can fit two framebuffers into video memory.
+	* This allows up to 1600x1200 with 16 MB (default size).
+	* If you want more try this:
+	* 'qemu -vga std -global VGA.vgamem_mb=32 $otherargs'
+	*/
+	if (size * 2 > hiprivate->fb_size)
+		return MODE_BAD;
+
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+hibmc_connector_best_encoder(struct drm_connector *connector)
+{
+	int enc_id = connector->encoder_ids[0];
+
+	/* pick the encoder ids */
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
+
+	return NULL;
+}
+
+static enum drm_connector_status hibmc_connector_detect(struct drm_connector
+						 *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_helper_funcs
+	hibmc_connector_connector_helper_funcs = {
+	.get_modes = hibmc_connector_get_modes,
+	.mode_valid = hibmc_connector_mode_valid,
+	.best_encoder = hibmc_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs hibmc_connector_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = hibmc_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.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 hibmc_connector_init(struct hibmc_drm_device *hidev)
+{
+	struct drm_device *dev = hidev->dev;
+	struct drm_connector *connector = &hidev->connector;
+	int ret;
+
+	ret = drm_connector_init(dev, connector,
+				 &hibmc_connector_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("failed to init connector\n");
+		return ret;
+	}
+	drm_connector_helper_add(connector,
+				 &hibmc_connector_connector_helper_funcs);
+
+	return 0;
+}
+
-- 
1.9.1

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

* [path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
                   ` (4 preceding siblings ...)
  2016-05-29  9:40 ` [path v2 5/7] drm/hisilicon/hibmc: Add connector " Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-29  9:40 ` [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM Rongrong Zou
  2016-05-30  3:01 ` [path v2 0/7] Add DRM driver for Hisilicon Hibmc Xinliang Liu
  7 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Add support for fbdev.

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 drivers/gpu/drm/hisilicon/hibmc/Makefile          |   2 +-
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   |  20 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  17 ++
 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 ++++++++++++++++++++++
 4 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c

diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 4e7797a..92e7b33 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,4 +1,4 @@
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_power.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_drm_power.o
 
 obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
 #obj-y	+= hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index 70d79d2..e36a7ec 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -72,9 +72,16 @@ static int hibmc_pm_suspend(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct hibmc_drm_device *hidev = drm_dev->dev_private;
 
 	drm_kms_helper_poll_disable(drm_dev);
 
+	if (hidev->fbdev.initialized) {
+		console_lock();
+		drm_fb_helper_set_suspend(&hidev->fbdev.helper, 1);
+		console_unlock();
+	}
+
 	return 0;
 }
 
@@ -82,8 +89,16 @@ static int hibmc_pm_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct hibmc_drm_device *hidev = drm_dev->dev_private;
 
 	drm_helper_resume_force_mode(drm_dev);
+
+	if (hidev->fbdev.initialized) {
+		console_lock();
+		drm_fb_helper_set_suspend(&hidev->fbdev.helper, 0);
+		console_unlock();
+	}
+
 	drm_kms_helper_poll_enable(drm_dev);
 
 	return 0;
@@ -245,6 +260,7 @@ static int hibmc_unload(struct drm_device *dev)
 {
 	struct hibmc_drm_device *hidev = dev->dev_private;
 
+	hibmc_fbdev_fini(hidev);
 	hibmc_kms_fini(hidev);
 	hibmc_hw_fini(hidev);
 	dev->dev_private = NULL;
@@ -278,6 +294,10 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
 	/* reset all the states of crtc/plane/encoder/connector */
 	drm_mode_config_reset(dev);
 
+	ret = hibmc_fbdev_init(hidev);
+	if (ret)
+		goto err;
+
 	return 0;
 
 err:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index eb5a892..1f32f2e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -23,6 +23,18 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
+struct hibmc_framebuffer {
+	struct drm_framebuffer fb;
+	struct drm_gem_cma_object *obj;
+	bool is_fbdev_fb;
+};
+
+struct hibmc_fbdev {
+	struct hibmc_framebuffer fb;
+	struct drm_fb_helper helper;
+	bool initialized;
+};
+
 struct hibmc_drm_device {
 	/* hw */
 	void __iomem   *mmio;
@@ -37,11 +49,16 @@ struct hibmc_drm_device {
 	struct drm_encoder encoder;
 	struct drm_connector connector;
 	bool mode_config_initialized;
+
+	/* fbdev */
+	struct hibmc_fbdev fbdev;
 };
 
 int hibmc_plane_init(struct hibmc_drm_device *hidev);
 int hibmc_crtc_init(struct hibmc_drm_device *hidev);
 int hibmc_encoder_init(struct hibmc_drm_device *hidev);
 int hibmc_connector_init(struct hibmc_drm_device *hidev);
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
 
 #endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
new file mode 100644
index 0000000..774bfb0
--- /dev/null
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
@@ -0,0 +1,286 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.com>
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "hibmc_drm_drv.h"
+
+/* ---------------------------------------------------------------------- */
+
+static void hibmc_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct hibmc_drm_device *hidev =
+		container_of(fb, struct hibmc_drm_device, fbdev.fb.fb);
+	struct drm_gem_object *base = &hidev->fbdev.fb.obj->base;
+
+	if (hidev->fbdev.fb.obj)
+		drm_gem_object_unreference_unlocked(base);
+	drm_framebuffer_cleanup(fb);
+	kfree(fb);
+}
+
+static struct drm_framebuffer_funcs hibmc_drm_fb_funcs = {
+	.destroy	= hibmc_drm_fb_destroy,
+};
+
+static int hibmc_drm_fb_init(struct drm_device *dev,
+		      struct hibmc_framebuffer *gfb,
+		      struct drm_mode_fb_cmd2 *mode_cmd,
+		      struct drm_gem_cma_object *obj)
+{
+	int ret;
+
+	drm_helper_mode_fill_fb_struct(&gfb->fb, mode_cmd);
+	gfb->obj = obj;
+	gfb->is_fbdev_fb = true;
+	ret = drm_framebuffer_init(dev, &gfb->fb, &hibmc_drm_fb_funcs);
+	if (ret) {
+		DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static struct drm_gem_cma_object *hibmc_drm_gem_create_object(
+						struct hibmc_drm_device *hidev,
+						size_t size)
+{
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
+	struct drm_device *drm = hidev->dev;
+	int ret;
+
+	cma_obj = devm_kzalloc(drm->dev, sizeof(*cma_obj), GFP_KERNEL);
+	if (!cma_obj)
+		return ERR_PTR(-ENOMEM);
+
+	gem_obj = &cma_obj->base;
+
+	ret = drm_gem_object_init(drm, gem_obj, size);
+	if (ret)
+		return ERR_PTR(ret);
+
+	cma_obj->vaddr = hidev->fb_map;
+	cma_obj->paddr = hidev->fb_base;
+	return cma_obj;
+}
+
+static void hibmc_drm_gem_free_object(struct drm_gem_object *gem_obj)
+{
+	struct drm_gem_cma_object *cma_obj;
+
+	cma_obj = to_drm_gem_cma_obj(gem_obj);
+	drm_gem_object_release(gem_obj);
+}
+
+static struct fb_ops hibmc_drm_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_fillrect = drm_fb_helper_sys_fillrect,
+	.fb_copyarea = drm_fb_helper_sys_copyarea,
+	.fb_imageblit = drm_fb_helper_sys_imageblit,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int hibmc_drm_fb_probe(struct drm_fb_helper *helper,
+			      struct drm_fb_helper_surface_size *sizes)
+{
+	struct hibmc_drm_device *hidev =
+		container_of(helper, struct hibmc_drm_device, fbdev.helper);
+	struct drm_device *dev = hidev->dev;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_gem_cma_object *obj = NULL;
+	int ret = 0;
+	size_t size;
+	unsigned int bytes_per_pixel;
+	unsigned long offset;
+
+	DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
+			 sizes->surface_width, sizes->surface_height,
+			 sizes->surface_bpp);
+	sizes->surface_depth = 32;
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.pitches[0] = mode_cmd.width * bytes_per_pixel;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
+
+	size = roundup(mode_cmd.pitches[0] * mode_cmd.height, PAGE_SIZE);
+
+	obj = hibmc_drm_gem_create_object(hidev, size);
+	if (IS_ERR(obj)) {
+		DRM_ERROR("can't allocate gem object\n");
+		return -ENOMEM;
+	}
+
+
+	/* init fb device */
+	/*info = framebuffer_alloc(0, device);*/
+	info = drm_fb_helper_alloc_fbi(helper);
+	if (!info) {
+		DRM_ERROR("can't allocate fb info\n");
+		goto err_drm_gem_cma_free_object;
+	}
+
+	ret = hibmc_drm_fb_init(hidev->dev,
+				&hidev->fbdev.fb, &mode_cmd, obj);
+	if (ret) {
+		DRM_ERROR("framebuffer init error\n");
+		goto err_drm_gem_cma_free_object;
+	}
+
+	/* setup helper */
+	fb = &hidev->fbdev.fb.fb;
+	hidev->fbdev.helper.fb = fb;
+	hidev->fbdev.helper.fbdev = info;
+
+	strcpy(info->fix.id, "hibmcdrmfb");
+	info->par = &hidev->fbdev.helper;
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &hibmc_drm_fb_ops;
+
+	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_var(info, &hidev->fbdev.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 = (resource_size_t)obj->paddr;
+	info->screen_base = obj->vaddr + offset;
+	info->fix.smem_start = (unsigned long)(obj->paddr + offset);
+	info->screen_size = size;
+	info->fix.smem_len = size;
+
+	return 0;
+
+err_drm_gem_cma_free_object:
+	hibmc_drm_gem_free_object(&obj->base);
+	return ret;
+}
+
+static int hibmc_fbdev_destroy(struct hibmc_drm_device *hidev)
+{
+	struct hibmc_framebuffer *gfb = &hidev->fbdev.fb;
+	struct drm_fb_helper *fbh = &hidev->fbdev.helper;
+
+	DRM_DEBUG_DRIVER("hibmc_fbdev_destroy\n");
+
+	drm_fb_helper_unregister_fbi(fbh);
+	drm_fb_helper_release_fbi(fbh);
+
+	drm_framebuffer_unregister_private(&gfb->fb);
+	if (gfb->obj) {
+		drm_gem_object_unreference_unlocked(&gfb->obj->base);
+		gfb->obj = NULL;
+	}
+
+	drm_framebuffer_cleanup(&gfb->fb);
+	drm_fb_helper_fini(&hidev->fbdev.helper);
+
+	return 0;
+}
+
+static const struct drm_fb_helper_funcs hibmc_fbdev_helper_funcs = {
+	.fb_probe = hibmc_drm_fb_probe,
+};
+
+int hibmc_fbdev_init(struct hibmc_drm_device *hidev)
+{
+	int ret;
+	struct fb_var_screeninfo *var;
+	struct fb_fix_screeninfo *fix;
+
+	drm_fb_helper_prepare(hidev->dev, &hidev->fbdev.helper,
+			      &hibmc_fbdev_helper_funcs);
+
+	/* Now just one crtc and one channel */
+	ret = drm_fb_helper_init(hidev->dev,
+				 &hidev->fbdev.helper, 1, 1);
+	if (ret)
+		return ret;
+
+	ret = drm_fb_helper_single_add_all_connectors(&hidev->fbdev.helper);
+	if (ret)
+		goto fini;
+
+	drm_helper_disable_unused_functions(hidev->dev);
+
+	ret = drm_fb_helper_initial_config(&hidev->fbdev.helper, 16);
+	if (ret)
+		goto fini;
+
+	hidev->fbdev.initialized = true;
+
+	var = &hidev->fbdev.helper.fbdev->var;
+	fix = &hidev->fbdev.helper.fbdev->fix;
+
+	DRM_DEBUG("Member of info->var is :\n"
+		 "xres=%d\n"
+		 "yres=%d\n"
+		 "xres_virtual=%d\n"
+		 "yres_virtual=%d\n"
+		 "xoffset=%d\n"
+		 "yoffset=%d\n"
+		 "bits_per_pixel=%d\n"
+		 "...\n", var->xres, var->yres, var->xres_virtual,
+		 var->yres_virtual, var->xoffset, var->yoffset,
+		 var->bits_per_pixel);
+	DRM_DEBUG("Member of info->fix is :\n"
+		 "smem_start=%lx\n"
+		 "smem_len=%d\n"
+		 "type=%d\n"
+		 "type_aux=%d\n"
+		 "visual=%d\n"
+		 "xpanstep=%d\n"
+		 "ypanstep=%d\n"
+		 "ywrapstep=%d\n"
+		 "line_length=%d\n"
+		 "accel=%d\n"
+		 "capabilities=%d\n"
+		 "...\n", fix->smem_start, fix->smem_len, fix->type,
+		 fix->type_aux, fix->visual, fix->xpanstep,
+		 fix->ypanstep, fix->ywrapstep, fix->line_length,
+		 fix->accel, fix->capabilities);
+
+	return 0;
+
+fini:
+	drm_fb_helper_fini(&hidev->fbdev.helper);
+	return ret;
+}
+
+void hibmc_fbdev_fini(struct hibmc_drm_device *hidev)
+{
+	if (!hidev->fbdev.initialized)
+		return;
+
+	hibmc_fbdev_destroy(hidev);
+	hidev->fbdev.initialized = false;
+}
-- 
1.9.1

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

* [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
                   ` (5 preceding siblings ...)
  2016-05-29  9:40 ` [path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer Rongrong Zou
@ 2016-05-29  9:40 ` Rongrong Zou
  2016-05-30  2:31   ` Xinliang Liu
  2016-05-30  3:01 ` [path v2 0/7] Add DRM driver for Hisilicon Hibmc Xinliang Liu
  7 siblings, 1 reply; 15+ messages in thread
From: Rongrong Zou @ 2016-05-29  9:40 UTC (permalink / raw)
  To: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu
  Cc: dri-devel, guohanjun, majun258, linuxarm, linux-arm-kernel,
	linux-kernel, linux-fbdev

Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
Signed-off-by: Jianhua Li <lijianhua@huawei.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f466673..a8a62e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3957,6 +3957,13 @@ T:	git git://github.com/patjak/drm-gma500
 S:	Maintained
 F:	drivers/gpu/drm/gma500/
 
+DRM DRIVERS FOR HIBMC
+M:	lijianhua <lijianhua@huawei.com>
+M:	Rongrong Zou <zourongrong@gmail.com>
+L:	dri-devel@lists.freedesktop.org
+S:	Maintained
+F:	drivers/gpu/drm/hisilicon/hibmc
+
 DRM DRIVERS FOR HISILICON
 M:	Xinliang Liu <z.liuxinliang@hisilicon.com>
 R:	Xinwei Kong <kong.kongxinwei@hisilicon.com>
-- 
1.9.1

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

* Re: [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
  2016-05-29  9:40 ` [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM Rongrong Zou
@ 2016-05-30  2:31   ` Xinliang Liu
  2016-05-30  3:21     ` Rongrong Zou
  0 siblings, 1 reply; 15+ messages in thread
From: Xinliang Liu @ 2016-05-30  2:31 UTC (permalink / raw)
  To: Rongrong Zou
  Cc: Rongrong Zou, David Airlie, Emil Velikov, lijianhua, dri-devel,
	Hanjun Guo, majun258, Linuxarm, LAKML, Linux Kernel Mailing List,
	linux-fbdev

On 29 May 2016 at 17:40, Rongrong Zou <zourongrong@gmail.com> wrote:
> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
> Signed-off-by: Jianhua Li <lijianhua@huawei.com>
> ---
>  MAINTAINERS | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f466673..a8a62e0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3957,6 +3957,13 @@ T:       git git://github.com/patjak/drm-gma500
>  S:     Maintained
>  F:     drivers/gpu/drm/gma500/
>
> +DRM DRIVERS FOR HIBMC
> +M:     lijianhua <lijianhua@huawei.com>
> +M:     Rongrong Zou <zourongrong@gmail.com>
> +L:     dri-devel@lists.freedesktop.org
> +S:     Maintained
> +F:     drivers/gpu/drm/hisilicon/hibmc

Please add a "/" ad the end of this line.
And move this part into DRM DRIVERS FOR HISILICON

Thanks,
-xinliang

> +
>  DRM DRIVERS FOR HISILICON
>  M:     Xinliang Liu <z.liuxinliang@hisilicon.com>
>  R:     Xinwei Kong <kong.kongxinwei@hisilicon.com>
> --
> 1.9.1
>

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

* Re: [path v2 0/7] Add DRM driver for Hisilicon Hibmc
  2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
                   ` (6 preceding siblings ...)
  2016-05-29  9:40 ` [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM Rongrong Zou
@ 2016-05-30  3:01 ` Xinliang Liu
  2016-05-30  3:11   ` Rongrong Zou
  7 siblings, 1 reply; 15+ messages in thread
From: Xinliang Liu @ 2016-05-30  3:01 UTC (permalink / raw)
  To: Rongrong Zou
  Cc: Rongrong Zou, David Airlie, Emil Velikov, lijianhua, dri-devel,
	Hanjun Guo, majun258, Linuxarm, LAKML, Linux Kernel Mailing List,
	linux-fbdev

Hi Rongrong,

It seems that you haven't run the checkpatch script.
Please run this script to check your patches before you send them. Like bellow:
$ cd yourkerneldir
$ ./scripts/checkpatch.pl --strict yourpatches

Thanks,
-xinliang

On 29 May 2016 at 17:40, Rongrong Zou <zourongrong@gmail.com> wrote:
> This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
> base board management controller, usually it is used on server for
> Out-of-band management purpose. In this patch set, we just support basic
> function for Hibmc display subsystem. Hibmc display subsystem is connected
> to host CPU by PCIe as blow:
>
> +----------+       +----------+
> |          | PCIe  |  Hibmc   |
> |host CPU( |<----->| display  |
> |arm64,x86)|       |subsystem |
> +----------+       +----------+
>
> Hardware Detail for Hibmc display subsystem
> -----------
>
>   The display subsystem of Hibmc is show as bellow:
>   +----+      +----+      +----+     +--------+
>   |    |      |    |      |    |     |        |
>   | FB |----->| DE |----->|VDAC|---->|external|
>   |    |      |    |      |    |     | VGA    |
>   +----+      +----+      +----+     +--------+
>
>   -DE(Display Engine) is the display controller.
>   -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
>   stream from DE to VGA analog signals.
>
> Change History
> ------------
>
> Changes in v2:
>   -Remove self-defined macros for bit operations.
>   -Remove unused register.
>   -Replace those deprecated functions with new version of them.
>   -use drm_connector_register_all() to register connector after
>    drm_dev_register().
>
> The patch v1 is at
> https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
> Sorry for too late sending.
>
>
> Rongrong Zou (7):
>   idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
>   drm/hisilicon/hibmc: Add plane for DE
>   drm/hisilicon/hibmc: Add crtc for DE
>   drm/hisilicon/hibmc: Add encoder for VDAC
>   drm/hisilicon/hibmc: Add connector for VDAC
>   drm/hisilicon/hibmc: Add support for frame buffer
>   drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
>
>  MAINTAINERS                                       |   7 +
>  drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>  drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>  drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>  drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c    | 477 ++++++++++++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h    |  29 ++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++++++++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 ++++++++
>  14 files changed, 1789 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>
> --
> 1.9.1
>

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

* Re: [path v2 0/7] Add DRM driver for Hisilicon Hibmc
  2016-05-30  3:01 ` [path v2 0/7] Add DRM driver for Hisilicon Hibmc Xinliang Liu
@ 2016-05-30  3:11   ` Rongrong Zou
  0 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-30  3:11 UTC (permalink / raw)
  To: Xinliang Liu, Rongrong Zou
  Cc: David Airlie, Emil Velikov, lijianhua, dri-devel, Hanjun Guo,
	majun258, Linuxarm, LAKML, Linux Kernel Mailing List,
	linux-fbdev

Hi Xinliang

在 2016/5/30 11:01, Xinliang Liu 写道:
> Hi Rongrong,
>
> It seems that you haven't run the checkpatch script.
> Please run this script to check your patches before you send them. Like bellow:
> $ cd yourkerneldir
> $ ./scripts/checkpatch.pl --strict yourpatches

I run checkpatch.pl without "--strict", and i'll check again with
this parameter, thanks!

>
> Thanks,
> -xinliang
>
> On 29 May 2016 at 17:40, Rongrong Zou <zourongrong@gmail.com> wrote:
>> This patch set adds a new drm driver for Hisilicon Hibmc. Hibmc is a
>> base board management controller, usually it is used on server for
>> Out-of-band management purpose. In this patch set, we just support basic
>> function for Hibmc display subsystem. Hibmc display subsystem is connected
>> to host CPU by PCIe as blow:
>>
>> +----------+       +----------+
>> |          | PCIe  |  Hibmc   |
>> |host CPU( |<----->| display  |
>> |arm64,x86)|       |subsystem |
>> +----------+       +----------+
>>
>> Hardware Detail for Hibmc display subsystem
>> -----------
>>
>>    The display subsystem of Hibmc is show as bellow:
>>    +----+      +----+      +----+     +--------+
>>    |    |      |    |      |    |     |        |
>>    | FB |----->| DE |----->|VDAC|---->|external|
>>    |    |      |    |      |    |     | VGA    |
>>    +----+      +----+      +----+     +--------+
>>
>>    -DE(Display Engine) is the display controller.
>>    -VDAC(Video Digital-to-Analog converter) converts the RGB diaital data
>>    stream from DE to VGA analog signals.
>>
>> Change History
>> ------------
>>
>> Changes in v2:
>>    -Remove self-defined macros for bit operations.
>>    -Remove unused register.
>>    -Replace those deprecated functions with new version of them.
>>    -use drm_connector_register_all() to register connector after
>>     drm_dev_register().
>>
>> The patch v1 is at
>> https://lists.freedesktop.org/archives/dri-devel/2016-February/101921.html
>> Sorry for too late sending.
>>
>>
>> Rongrong Zou (7):
>>    idrm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
>>    drm/hisilicon/hibmc: Add plane for DE
>>    drm/hisilicon/hibmc: Add crtc for DE
>>    drm/hisilicon/hibmc: Add encoder for VDAC
>>    drm/hisilicon/hibmc: Add connector for VDAC
>>    drm/hisilicon/hibmc: Add support for frame buffer
>>    drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
>>
>>   MAINTAINERS                                       |   7 +
>>   drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>>   drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>>   drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>>   drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c    | 477 ++++++++++++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h    |  29 ++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 399 ++++++++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  64 +++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c | 286 +++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 ++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c  | 174 ++++++++
>>   14 files changed, 1789 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
>>
>> --
>> 1.9.1
>>
>
> .
>


-- 
Regards,
Rongrong

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

* Re: [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM
  2016-05-30  2:31   ` Xinliang Liu
@ 2016-05-30  3:21     ` Rongrong Zou
  0 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-30  3:21 UTC (permalink / raw)
  To: Xinliang Liu, Rongrong Zou
  Cc: David Airlie, Emil Velikov, lijianhua, dri-devel, Hanjun Guo,
	majun258, Linuxarm, LAKML, Linux Kernel Mailing List,
	linux-fbdev

Hi Xinliang,

在 2016/5/30 10:31, Xinliang Liu 写道:
> On 29 May 2016 at 17:40, Rongrong Zou <zourongrong@gmail.com> wrote:
>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>> Signed-off-by: Jianhua Li <lijianhua@huawei.com>
>> ---
>>   MAINTAINERS | 7 +++++++
>>   1 file changed, 7 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index f466673..a8a62e0 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -3957,6 +3957,13 @@ T:       git git://github.com/patjak/drm-gma500
>>   S:     Maintained
>>   F:     drivers/gpu/drm/gma500/
>>
>> +DRM DRIVERS FOR HIBMC
>> +M:     lijianhua <lijianhua@huawei.com>
>> +M:     Rongrong Zou <zourongrong@gmail.com>
>> +L:     dri-devel@lists.freedesktop.org
>> +S:     Maintained
>> +F:     drivers/gpu/drm/hisilicon/hibmc
>
> Please add a "/" ad the end of this line.

OK, thanks!

> And move this part into DRM DRIVERS FOR HISILICON

Can it be placed as below:

DRM DRIVERS FOR HISILICON HIBMC
M:     lijianhua <lijianhua@huawei.com>
M:     Rongrong Zou <zourongrong@gmail.com>
...

DRM DRIVERS FOR HISILICON KIRIN
M:     Xinliang Liu <z.liuxinliang@hisilicon.com>
R:     Xinwei Kong <kong.kongxinwei@hisilicon.com>
...
>
> Thanks,
> -xinliang
>
>> +
>>   DRM DRIVERS FOR HISILICON
>>   M:     Xinliang Liu <z.liuxinliang@hisilicon.com>
>>   R:     Xinwei Kong <kong.kongxinwei@hisilicon.com>
>> --
>> 1.9.1
>>
>
> .
>


-- 
Regards,
Rongrong

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

* Re: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  2016-05-29  9:40 ` [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver Rongrong Zou
@ 2016-05-30  9:03   ` Daniel Vetter
  2016-05-30 12:09     ` Rongrong Zou
  0 siblings, 1 reply; 15+ messages in thread
From: Daniel Vetter @ 2016-05-30  9:03 UTC (permalink / raw)
  To: Rongrong Zou
  Cc: zourongrong, airlied, emil.l.velikov, lijianhua, xinliang.liu,
	linux-fbdev, linux-kernel, dri-devel, linuxarm, guohanjun,
	linux-arm-kernel, majun258

On Sun, May 29, 2016 at 05:40:49PM +0800, Rongrong Zou wrote:
> Add DRM master driver for Hisilicon Hibmc SoC which used for
> Out-of-band management. Blow is the general hardware connection,
> both the Hibmc and the host CPU are on the same mother board.
> 
> +----------+       +----------+
> |          | PCIe  |  Hibmc   |
> |host CPU( |<----->| display  |
> |arm64,x86)|       |subsystem |
> +----------+       +----------+
> 
> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
> Signed-off-by: Jianhua Li <lijianhua@huawei.com>
> ---
>  drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>  drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>  drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>  drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>  drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
>  9 files changed, 699 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>  create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
> 
> diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
> index 558c61b..2fd2724 100644
> --- a/drivers/gpu/drm/hisilicon/Kconfig
> +++ b/drivers/gpu/drm/hisilicon/Kconfig
> @@ -2,4 +2,5 @@
>  # hisilicon drm device configuration.
>  # Please keep this list sorted alphabetically
>  
> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
>  source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
> diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
> index e3f6d49..4d7185c 100644
> --- a/drivers/gpu/drm/hisilicon/Makefile
> +++ b/drivers/gpu/drm/hisilicon/Makefile
> @@ -2,4 +2,5 @@
>  # Makefile for hisilicon drm drivers.
>  # Please keep this list sorted alphabetically
>  
> -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
> +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
> \ No newline at end of file
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
> new file mode 100644
> index 0000000..1e7810d
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
> @@ -0,0 +1,13 @@
> +config DRM_HISI_HIBMC
> +	tristate "DRM Support for Hisilicon Hibmc"
> +	depends on DRM && PCI
> +	select DRM_KMS_HELPER
> +	select DRM_KMS_FB_HELPER
> +	select DRM_GEM_CMA_HELPER
> +	select DRM_KMS_CMA_HELPER
> +	select FB_SYS_FILLRECT
> +	select FB_SYS_COPYAREA
> +	select FB_SYS_IMAGEBLIT
> +	help
> +	  Choose this option if you have a Hisilicon Hibmc soc chipset.
> +	  If M is selected the module will be called hibmc-drm.
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
> new file mode 100644
> index 0000000..533f9ed
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
> @@ -0,0 +1,4 @@
> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
> +
> +obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
> +#obj-y	+= hibmc-drm.o
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> new file mode 100644
> index 0000000..7eaacd8
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
> @@ -0,0 +1,307 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong@huawei>
> + *	Rongrong Zou <zourongrong@gmail.com>
> + *	Jianhua Li <lijianhua@huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/console.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drmP.h>
> +
> +#include "hibmc_drm_drv.h"
> +#include "hibmc_drm_regs.h"
> +#include "hibmc_drm_power.h"
> +
> +static const struct file_operations hibmc_fops = {
> +	.owner		= THIS_MODULE,
> +	.open		= drm_open,
> +	.release	= drm_release,
> +	.unlocked_ioctl	= drm_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl	= drm_compat_ioctl,
> +#endif
> +	.poll		= drm_poll,
> +	.read		= drm_read,
> +	.llseek		= no_llseek,
> +};
> +
> +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
> +{
> +	return 0;
> +}
> +
> +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
> +{
> +}
> +
> +static struct drm_driver hibmc_driver = {
> +	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
> +	.fops			= &hibmc_fops,
> +	.name			= "hibmc",
> +	.desc			= "hibmc drm driver",
> +	.major			= 1,
> +	.minor			= 0,
> +	.get_vblank_counter = drm_vblank_no_hw_counter,
> +	.enable_vblank		= hibmc_enable_vblank,
> +	.disable_vblank	= hibmc_disable_vblank,
> +	.gem_free_object        = drm_gem_cma_free_object,

gem_free_object_unlocked pls.

> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
> +	.dumb_create            = drm_gem_cma_dumb_create,
> +	.dumb_map_offset        = drm_gem_cma_dumb_map_offset,
> +	.dumb_destroy           = drm_gem_dumb_destroy,
> +};
> +
> +static int hibmc_pm_suspend(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
> +
> +	drm_kms_helper_poll_disable(drm_dev);
> +
> +	return 0;
> +}
> +
> +static int hibmc_pm_resume(struct device *dev)
> +{
> +	struct pci_dev *pdev = to_pci_dev(dev);
> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
> +
> +	drm_helper_resume_force_mode(drm_dev);
> +	drm_kms_helper_poll_enable(drm_dev);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops hibmc_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
> +				hibmc_pm_resume)
> +};
> +
> +static const struct drm_mode_config_funcs mode_config_funcs = {
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,

So how exactly does nonblocking commit work for you? Please run the igt
validation suit on your new driver, a bunch of collabora engineers are
working hard to make it run on non-intel drivers too. Ping Tomeu and
Robert Foss for more info on this please.

Lucky for you I'm working on generic nonblocking support in the atomic
helpers, patches are on the mailing list.

> +};
> +
> +
> +static int hibmc_hw_config(struct hibmc_drm_device *hidev)
> +{
> +	unsigned int reg;
> +
> +	/* On hardware reset, power mode 0 is default. */
> +	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
> +
> +	/* Enable display power gate & LOCALMEM power gate*/
> +	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
> +	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
> +	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
> +	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
> +	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
> +
> +	hibmc_set_current_gate(hidev, reg);
> +
> +	/* Reset the memory controller. If the memory controller
> +	 * is not reset in chip,the system might hang when sw accesses
> +	 * the memory.The memory should be resetted after
> +	 * changing the MXCLK.
> +	 */
> +	reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
> +
> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
> +
> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
> +
> +	/* We can add more initialization as needed. */
> +
> +	return 0;
> +}
> +
> +static int hibmc_hw_map(struct hibmc_drm_device *hidev)
> +{
> +	struct drm_device *dev = hidev->dev;
> +	struct pci_dev *pdev = dev->pdev;
> +	resource_size_t addr, size, ioaddr, iosize;
> +
> +	ioaddr = pci_resource_start(pdev, 1);
> +	iosize = MB(2);
> +
> +	hidev->mmio = ioremap_nocache(ioaddr, iosize);
> +
> +	if (!hidev->mmio) {
> +		DRM_ERROR("Cannot map mmio region\n");
> +		return -ENOMEM;
> +	}
> +
> +	addr = pci_resource_start(pdev, 0);
> +	size = MB(16);
> +
> +	hidev->fb_map = ioremap(addr, size);
> +	if (!hidev->fb_map) {
> +		DRM_ERROR("Cannot map framebuffer\n");
> +		return -ENOMEM;
> +	}
> +	hidev->fb_base = addr;
> +	hidev->fb_size = size;
> +
> +	return 0;
> +}
> +
> +static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
> +{
> +	if (hidev->mmio)
> +		iounmap(hidev->mmio);
> +	if (hidev->fb_map)
> +		iounmap(hidev->fb_map);
> +}
> +
> +static int hibmc_hw_init(struct hibmc_drm_device *hidev)
> +{
> +	int ret;
> +
> +	ret = hibmc_hw_map(hidev);
> +	if (ret)
> +		return ret;
> +
> +	hibmc_hw_config(hidev);
> +
> +	return 0;
> +}
> +
> +static int hibmc_unload(struct drm_device *dev)
> +{
> +	struct hibmc_drm_device *hidev = dev->dev_private;
> +
> +	hibmc_hw_fini(hidev);
> +	dev->dev_private = NULL;
> +	return 0;
> +}
> +
> +static int hibmc_load(struct drm_device *dev, unsigned long flags)
> +{
> +	struct hibmc_drm_device *hidev;
> +	int ret;
> +
> +	hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
> +	if (!hidev)
> +		return -ENOMEM;
> +	dev->dev_private = hidev;
> +	hidev->dev = dev;
> +
> +	ret = hibmc_hw_init(hidev);
> +	if (ret)
> +		goto err;
> +
> +
> +	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
> +	if (ret) {
> +		DRM_ERROR("failed to initialize vblank.\n");
> +		return ret;
> +	}
> +	/* reset all the states of crtc/plane/encoder/connector */
> +	drm_mode_config_reset(dev);
> +
> +	return 0;
> +
> +err:
> +	hibmc_unload(dev);
> +	DRM_ERROR("failed to initialize drm driver.\n");
> +	return ret;
> +}
> +
> +
> +static int hibmc_pci_probe(struct pci_dev *pdev,
> +			   const struct pci_device_id *ent)
> +{
> +	struct drm_device *dev;
> +	int ret;
> +
> +	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->pdev = pdev;
> +	pci_set_drvdata(pdev, dev);
> +
> +	ret = pci_enable_device(pdev);
> +	if (ret)
> +		goto err_free;
> +
> +	ret = hibmc_load(dev, 0);
> +	if (ret)
> +		goto err_disable;
> +
> +	ret = drm_dev_register(dev, 0);
> +	if (ret)
> +		goto err_unload;
> +
> +	return 0;
> +
> +err_unload:
> +	hibmc_unload(dev);
> +err_disable:
> +	pci_disable_device(pdev);
> +err_free:
> +	drm_dev_unref(dev);
> +
> +	return ret;
> +}
> +
> +static void hibmc_pci_remove(struct pci_dev *pdev)
> +{
> +	struct drm_device *dev = pci_get_drvdata(pdev);
> +
> +	drm_dev_unregister(dev);
> +	hibmc_unload(dev);
> +	drm_dev_unref(dev);
> +}
> +
> +static struct pci_device_id hibmc_pci_table[] = {
> +	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
> +	{0,}
> +};
> +
> +static struct pci_driver hibmc_pci_driver = {
> +	.name =		"hibmc-drm",
> +	.id_table =	hibmc_pci_table,
> +	.probe =	hibmc_pci_probe,
> +	.remove =	hibmc_pci_remove,
> +	.driver.pm =    &hibmc_pm_ops,
> +};
> +
> +static int __init hibmc_init(void)
> +{
> +	return pci_register_driver(&hibmc_pci_driver);
> +}
> +
> +static void __exit hibmc_exit(void)
> +{
> +	return pci_unregister_driver(&hibmc_pci_driver);
> +}
> +
> +module_init(hibmc_init);
> +module_exit(hibmc_exit);
> +
> +MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
> +MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
> +MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
> +MODULE_LICENSE("GPL v2");
> +
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
> new file mode 100644
> index 0000000..a072ea9
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
> @@ -0,0 +1,39 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong@huawei>
> + *	Rongrong Zou <zourongrong@gmail.com>
> + *	Jianhua Li <lijianhua@huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef HIBMC_DRM_DRV_H
> +#define HIBMC_DRM_DRV_H
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +
> +struct hibmc_drm_device {
> +	/* hw */
> +	void __iomem   *mmio;
> +	void __iomem   *fb_map;
> +	unsigned long  fb_base;
> +	unsigned long  fb_size;
> +
> +	/* drm */
> +	struct drm_device  *dev;
> +	bool mode_config_initialized;
> +};
> +
> +
> +#endif
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
> new file mode 100644
> index 0000000..673be10
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
> @@ -0,0 +1,91 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong@huawei>
> + *	Rongrong Zou <zourongrong@gmail.com>
> + *	Jianhua Li <lijianhua@huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/io.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include "hibmc_drm_drv.h"
> +#include "hibmc_drm_regs.h"
> +
> +/*
> + * It can operate in one of three modes: 0, 1 or Sleep.
> + */
> +void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
> +				 unsigned int power_mode)
> +{
> +	unsigned int control_value = 0;
> +	void __iomem   *mmio = hidev->mmio;
> +
> +	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
> +		return;
> +
> +	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
> +	control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
> +
> +	control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
> +			 HIBMC_PW_MODE_CTL_MODE_MASK;
> +
> +
> +    /* Set up other fields in Power Control Register */
> +	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +	} else {
> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
> +
> +	}
> +    /* Program new power mode. */
> +	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
> +}
> +
> +static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
> +{
> +	void __iomem   *mmio = hidev->mmio;
> +
> +	return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
> +		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
> +}
> +
> +void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
> +{
> +	unsigned int gate_reg;
> +	unsigned int mode;
> +	void __iomem   *mmio = hidev->mmio;
> +
> +	/* Get current power mode. */
> +	mode = hibmc_get_power_mode(hidev);
> +
> +	switch (mode) {
> +	case HIBMC_PW_MODE_CTL_MODE_MODE0:
> +		gate_reg = HIBMC_MODE0_GATE;
> +		break;
> +
> +	case HIBMC_PW_MODE_CTL_MODE_MODE1:
> +		gate_reg = HIBMC_MODE1_GATE;
> +		break;
> +
> +	default:
> +		gate_reg = HIBMC_MODE0_GATE;
> +		break;
> +	}
> +	writel(gate, mmio + gate_reg);
> +}
> +
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
> new file mode 100644
> index 0000000..39f7a17
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
> @@ -0,0 +1,28 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong@huawei>
> + *	Rongrong Zou <zourongrong@gmail.com>
> + *	Jianhua Li <lijianhua@huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef HIBMC_DRM_POWER_H
> +#define HIBMC_DRM_POWER_H
> +
> +#include "hibmc_drm_drv.h"
> +
> +extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
> +				 unsigned int power_mode);
> +extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
> +				   unsigned int gate);
> +#endif
> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
> new file mode 100644
> index 0000000..4966c42
> --- /dev/null
> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
> @@ -0,0 +1,214 @@
> +/* Hisilicon Hibmc SoC drm driver
> + *
> + * Based on the bochs drm driver.
> + *
> + * Copyright (c) 2016 Huawei Limited.
> + *
> + * Author:
> + *	Rongrong Zou <zourongrong@huawei>
> + *	Rongrong Zou <zourongrong@gmail.com>
> + *	Jianhua Li <lijianhua@huawei.com>
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef HIBMC_DRM_HW_H
> +#define HIBMC_DRM_HW_H
> +
> +#define OFF 0
> +#define ON  1
> +#define DISABLE               0
> +#define ENABLE                1
> +
> +
> +
> +/* register definition */
> +#define HIBMC_MISC_CTRL				0x4
> +
> +#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
> +#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
> +
> +#define RESET                0
> +#define NORMAL               1
> +
> +#define HIBMC_CURRENT_GATE			0x000040
> +#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
> +#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
> +
> +#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
> +#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
> +
> +#define HIBMC_MODE0_GATE			0x000044
> +#define HIBMC_MODE1_GATE			0x000048
> +#define HIBMC_POWER_MODE_CTRL			0x00004C
> +
> +#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
> +#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
> +
> +#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
> +#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
> +#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
> +
> +
> +#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
> +#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
> +#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
> +
> +#define HIBMC_PANEL_PLL_CTRL			0x00005C
> +#define HIBMC_CRT_PLL_CTRL			0x000060
> +
> +#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
> +#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
> +
> +#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
> +#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
> +
> +#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
> +#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
> +
> +#define OSC					0
> +#define TESTCLK					1
> +
> +#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
> +#define HIBMC_PLL_CTRL_POD_MASK			0xC000
> +
> +#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
> +#define HIBMC_PLL_CTRL_OD_MASK			0x3000
> +
> +#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
> +#define HIBMC_PLL_CTRL_N_MASK			0xF00
> +
> +#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
> +#define HIBMC_PLL_CTRL_M_MASK			0xFF
> +
> +
> +#define HIBMC_CRT_DISP_CTL			0x80200
> +
> +#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
> +#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
> +
> +#define CRTSELECT_VGA                0
> +#define CRTSELECT_CRT                1
> +
> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
> +
> +#define PHASE_ACTIVE_HIGH      0
> +#define PHASE_ACTIVE_LOW       1
> +
> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
> +
> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
> +
> +#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
> +#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
> +
> +
> +#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
> +#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
> +
> +#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
> +#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
> +
> +
> +
> +#define HIBMC_CRT_FB_ADDRESS			0x080204
> +
> +#define HIBMC_CRT_FB_WIDTH			0x080208
> +#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
> +#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
> +#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
> +#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
> +
> +
> +#define HIBMC_CRT_HORZ_TOTAL			0x08020C
> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
> +
> +
> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)	((x) << 0)
> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK	0xFFF
> +
> +#define HIBMC_CRT_HORZ_SYNC			0x080210
> +#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
> +#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
> +
> +#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
> +#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
> +
> +#define HIBMC_CRT_VERT_TOTAL			0x080214
> +#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
> +#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
> +
> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)	((x) << 0)
> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK	0x7FF
> +
> +#define HIBMC_CRT_VERT_SYNC			0x080218
> +#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
> +#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
> +
> +
> +#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
> +#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
> +
> +/* Auto Centering */
> +#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK	0x7FF0000
> +
> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK	0x7FF
> +
> +#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
> +
> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
> +
> +/* register to control panel output */
> +#define DISPLAY_CONTROL_HISILE			0x80288
> +
> +/* register and values for PLL control */
> +#define CRT_PLL1_HS				0x802a8
> +#define CRT_PLL1_HS_25MHZ			0x23d40f02
> +#define CRT_PLL1_HS_40MHZ			0x23940801
> +#define CRT_PLL1_HS_65MHZ			0x23940d01
> +#define CRT_PLL1_HS_78MHZ			0x23540F82
> +#define CRT_PLL1_HS_74MHZ			0x23941dc2
> +#define CRT_PLL1_HS_80MHZ			0x23941001
> +#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
> +#define CRT_PLL1_HS_108MHZ			0x23b41b01
> +#define CRT_PLL1_HS_162MHZ			0x23480681
> +#define CRT_PLL1_HS_148MHZ			0x23541dc2
> +#define CRT_PLL1_HS_193MHZ			0x234807c1
> +
> +#define CRT_PLL2_HS				0x802ac
> +#define CRT_PLL2_HS_25MHZ			0x206B851E
> +#define CRT_PLL2_HS_40MHZ			0x30000000
> +#define CRT_PLL2_HS_65MHZ			0x40000000
> +#define CRT_PLL2_HS_78MHZ			0x50E147AE
> +#define CRT_PLL2_HS_74MHZ			0x602B6AE7
> +#define CRT_PLL2_HS_80MHZ			0x70000000
> +#define CRT_PLL2_HS_108MHZ			0x80000000
> +#define CRT_PLL2_HS_162MHZ			0xA0000000
> +#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
> +#define CRT_PLL2_HS_193MHZ			0xC0872B02
> +
> +/* Global macros */
> +#define RGB(r, g, b) \
> +( \
> +	(unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
> +)
> +
> +#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
> +
> +#define MB(x) ((x) << 20)
> +
> +#endif
> -- 
> 1.9.1
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  2016-05-30  9:03   ` Daniel Vetter
@ 2016-05-30 12:09     ` Rongrong Zou
  2016-05-30 12:51       ` Rongrong Zou
  0 siblings, 1 reply; 15+ messages in thread
From: Rongrong Zou @ 2016-05-30 12:09 UTC (permalink / raw)
  To: Rongrong Zou, airlied, emil.l.velikov, lijianhua, xinliang.liu,
	linux-fbdev, linux-kernel, dri-devel, linuxarm, guohanjun,
	linux-arm-kernel, majun258
  Cc: robert.foss, tomeu.vizoso

Hi Daniel,
Thanks for reveiwing!

在 2016/5/30 17:03, Daniel Vetter 写道:
> On Sun, May 29, 2016 at 05:40:49PM +0800, Rongrong Zou wrote:
>> Add DRM master driver for Hisilicon Hibmc SoC which used for
>> Out-of-band management. Blow is the general hardware connection,
>> both the Hibmc and the host CPU are on the same mother board.
>>
>> +----------+       +----------+
>> |          | PCIe  |  Hibmc   |
>> |host CPU( |<----->| display  |
>> |arm64,x86)|       |subsystem |
>> +----------+       +----------+
>>
>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>> Signed-off-by: Jianhua Li <lijianhua@huawei.com>
>> ---
>>   drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>>   drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>>   drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>>   drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
>>   9 files changed, 699 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>
>> diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
>> index 558c61b..2fd2724 100644
>> --- a/drivers/gpu/drm/hisilicon/Kconfig
>> +++ b/drivers/gpu/drm/hisilicon/Kconfig
>> @@ -2,4 +2,5 @@
>>   # hisilicon drm device configuration.
>>   # Please keep this list sorted alphabetically
>>
>> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
>>   source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
>> diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
>> index e3f6d49..4d7185c 100644
>> --- a/drivers/gpu/drm/hisilicon/Makefile
>> +++ b/drivers/gpu/drm/hisilicon/Makefile
>> @@ -2,4 +2,5 @@
>>   # Makefile for hisilicon drm drivers.
>>   # Please keep this list sorted alphabetically
>>
>> -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
>> +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>> \ No newline at end of file
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> new file mode 100644
>> index 0000000..1e7810d
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> @@ -0,0 +1,13 @@
>> +config DRM_HISI_HIBMC
>> +	tristate "DRM Support for Hisilicon Hibmc"
>> +	depends on DRM && PCI
>> +	select DRM_KMS_HELPER
>> +	select DRM_KMS_FB_HELPER
>> +	select DRM_GEM_CMA_HELPER
>> +	select DRM_KMS_CMA_HELPER
>> +	select FB_SYS_FILLRECT
>> +	select FB_SYS_COPYAREA
>> +	select FB_SYS_IMAGEBLIT
>> +	help
>> +	  Choose this option if you have a Hisilicon Hibmc soc chipset.
>> +	  If M is selected the module will be called hibmc-drm.
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> new file mode 100644
>> index 0000000..533f9ed
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> @@ -0,0 +1,4 @@
>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>> +
>> +obj-$(CONFIG_DRM_HISI_HIBMC)	+=hibmc-drm.o
>> +#obj-y	+= hibmc-drm.o
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> new file mode 100644
>> index 0000000..7eaacd8
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> @@ -0,0 +1,307 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong@huawei>
>> + *	Rongrong Zou <zourongrong@gmail.com>
>> + *	Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/console.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include <drm/drm_gem_cma_helper.h>
>> +#include <drm/drmP.h>
>> +
>> +#include "hibmc_drm_drv.h"
>> +#include "hibmc_drm_regs.h"
>> +#include "hibmc_drm_power.h"
>> +
>> +static const struct file_operations hibmc_fops = {
>> +	.owner		= THIS_MODULE,
>> +	.open		= drm_open,
>> +	.release	= drm_release,
>> +	.unlocked_ioctl	= drm_ioctl,
>> +#ifdef CONFIG_COMPAT
>> +	.compat_ioctl	= drm_compat_ioctl,
>> +#endif
>> +	.poll		= drm_poll,
>> +	.read		= drm_read,
>> +	.llseek		= no_llseek,
>> +};
>> +
>> +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
>> +{
>> +	return 0;
>> +}
>> +
>> +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>> +{
>> +}
>> +
>> +static struct drm_driver hibmc_driver = {
>> +	.driver_features	= DRIVER_GEM | DRIVER_MODESET,
>> +	.fops			= &hibmc_fops,
>> +	.name			= "hibmc",
>> +	.desc			= "hibmc drm driver",
>> +	.major			= 1,
>> +	.minor			= 0,
>> +	.get_vblank_counter = drm_vblank_no_hw_counter,
>> +	.enable_vblank		= hibmc_enable_vblank,
>> +	.disable_vblank	= hibmc_disable_vblank,
>> +	.gem_free_object        = drm_gem_cma_free_object,
>
> gem_free_object_unlocked pls.

Applied, thanks.

>
>> +	.gem_vm_ops		= &drm_gem_cma_vm_ops,
>> +	.dumb_create            = drm_gem_cma_dumb_create,
>> +	.dumb_map_offset        = drm_gem_cma_dumb_map_offset,
>> +	.dumb_destroy           = drm_gem_dumb_destroy,
>> +};
>> +
>> +static int hibmc_pm_suspend(struct device *dev)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(dev);
>> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
>> +
>> +	drm_kms_helper_poll_disable(drm_dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static int hibmc_pm_resume(struct device *dev)
>> +{
>> +	struct pci_dev *pdev = to_pci_dev(dev);
>> +	struct drm_device *drm_dev = pci_get_drvdata(pdev);
>> +
>> +	drm_helper_resume_force_mode(drm_dev);
>> +	drm_kms_helper_poll_enable(drm_dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct dev_pm_ops hibmc_pm_ops = {
>> +	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
>> +				hibmc_pm_resume)
>> +};
>> +
>> +static const struct drm_mode_config_funcs mode_config_funcs = {
>> +	.atomic_check = drm_atomic_helper_check,
>> +	.atomic_commit = drm_atomic_helper_commit,
>
> So how exactly does nonblocking commit work for you? Please run the igt
> validation suit on your new driver, a bunch of collabora engineers are
> working hard to make it run on non-intel drivers too. Ping Tomeu and
> Robert Foss for more info on this please.

OK, I should learn igt validation suit and test the new driver.
I tested the driver with tools such as fbtest before. Thanks.

>
> Lucky for you I'm working on generic nonblocking support in the atomic
> helpers, patches are on the mailing list.
>

It's nice, thanks. :)

>> +};
>> +
>> +
>> +static int hibmc_hw_config(struct hibmc_drm_device *hidev)
>> +{
>> +	unsigned int reg;
>> +
>> +	/* On hardware reset, power mode 0 is default. */
>> +	hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
>> +
>> +	/* Enable display power gate & LOCALMEM power gate*/
>> +	reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
>> +	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
>> +	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
>> +	reg |= HIBMC_CURR_GATE_DISPLAY(ON);
>> +	reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
>> +
>> +	hibmc_set_current_gate(hidev, reg);
>> +
>> +	/* Reset the memory controller. If the memory controller
>> +	 * is not reset in chip,the system might hang when sw accesses
>> +	 * the memory.The memory should be resetted after
>> +	 * changing the MXCLK.
>> +	 */
>> +	reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
>> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
>> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>> +
>> +	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>> +	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
>> +
>> +	writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>> +
>> +	/* We can add more initialization as needed. */
>> +
>> +	return 0;
>> +}
>> +
>> +static int hibmc_hw_map(struct hibmc_drm_device *hidev)
>> +{
>> +	struct drm_device *dev = hidev->dev;
>> +	struct pci_dev *pdev = dev->pdev;
>> +	resource_size_t addr, size, ioaddr, iosize;
>> +
>> +	ioaddr = pci_resource_start(pdev, 1);
>> +	iosize = MB(2);
>> +
>> +	hidev->mmio = ioremap_nocache(ioaddr, iosize);
>> +
>> +	if (!hidev->mmio) {
>> +		DRM_ERROR("Cannot map mmio region\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	addr = pci_resource_start(pdev, 0);
>> +	size = MB(16);
>> +
>> +	hidev->fb_map = ioremap(addr, size);
>> +	if (!hidev->fb_map) {
>> +		DRM_ERROR("Cannot map framebuffer\n");
>> +		return -ENOMEM;
>> +	}
>> +	hidev->fb_base = addr;
>> +	hidev->fb_size = size;
>> +
>> +	return 0;
>> +}
>> +
>> +static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
>> +{
>> +	if (hidev->mmio)
>> +		iounmap(hidev->mmio);
>> +	if (hidev->fb_map)
>> +		iounmap(hidev->fb_map);
>> +}
>> +
>> +static int hibmc_hw_init(struct hibmc_drm_device *hidev)
>> +{
>> +	int ret;
>> +
>> +	ret = hibmc_hw_map(hidev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	hibmc_hw_config(hidev);
>> +
>> +	return 0;
>> +}
>> +
>> +static int hibmc_unload(struct drm_device *dev)
>> +{
>> +	struct hibmc_drm_device *hidev = dev->dev_private;
>> +
>> +	hibmc_hw_fini(hidev);
>> +	dev->dev_private = NULL;
>> +	return 0;
>> +}
>> +
>> +static int hibmc_load(struct drm_device *dev, unsigned long flags)
>> +{
>> +	struct hibmc_drm_device *hidev;
>> +	int ret;
>> +
>> +	hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
>> +	if (!hidev)
>> +		return -ENOMEM;
>> +	dev->dev_private = hidev;
>> +	hidev->dev = dev;
>> +
>> +	ret = hibmc_hw_init(hidev);
>> +	if (ret)
>> +		goto err;
>> +
>> +
>> +	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
>> +	if (ret) {
>> +		DRM_ERROR("failed to initialize vblank.\n");
>> +		return ret;
>> +	}
>> +	/* reset all the states of crtc/plane/encoder/connector */
>> +	drm_mode_config_reset(dev);
>> +
>> +	return 0;
>> +
>> +err:
>> +	hibmc_unload(dev);
>> +	DRM_ERROR("failed to initialize drm driver.\n");
>> +	return ret;
>> +}
>> +
>> +
>> +static int hibmc_pci_probe(struct pci_dev *pdev,
>> +			   const struct pci_device_id *ent)
>> +{
>> +	struct drm_device *dev;
>> +	int ret;
>> +
>> +	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
>> +	if (!dev)
>> +		return -ENOMEM;
>> +
>> +	dev->pdev = pdev;
>> +	pci_set_drvdata(pdev, dev);
>> +
>> +	ret = pci_enable_device(pdev);
>> +	if (ret)
>> +		goto err_free;
>> +
>> +	ret = hibmc_load(dev, 0);
>> +	if (ret)
>> +		goto err_disable;
>> +
>> +	ret = drm_dev_register(dev, 0);
>> +	if (ret)
>> +		goto err_unload;
>> +
>> +	return 0;
>> +
>> +err_unload:
>> +	hibmc_unload(dev);
>> +err_disable:
>> +	pci_disable_device(pdev);
>> +err_free:
>> +	drm_dev_unref(dev);
>> +
>> +	return ret;
>> +}
>> +
>> +static void hibmc_pci_remove(struct pci_dev *pdev)
>> +{
>> +	struct drm_device *dev = pci_get_drvdata(pdev);
>> +
>> +	drm_dev_unregister(dev);
>> +	hibmc_unload(dev);
>> +	drm_dev_unref(dev);
>> +}
>> +
>> +static struct pci_device_id hibmc_pci_table[] = {
>> +	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>> +	{0,}
>> +};
>> +
>> +static struct pci_driver hibmc_pci_driver = {
>> +	.name =		"hibmc-drm",
>> +	.id_table =	hibmc_pci_table,
>> +	.probe =	hibmc_pci_probe,
>> +	.remove =	hibmc_pci_remove,
>> +	.driver.pm =    &hibmc_pm_ops,
>> +};
>> +
>> +static int __init hibmc_init(void)
>> +{
>> +	return pci_register_driver(&hibmc_pci_driver);
>> +}
>> +
>> +static void __exit hibmc_exit(void)
>> +{
>> +	return pci_unregister_driver(&hibmc_pci_driver);
>> +}
>> +
>> +module_init(hibmc_init);
>> +module_exit(hibmc_exit);
>> +
>> +MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
>> +MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
>> +MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
>> +MODULE_LICENSE("GPL v2");
>> +
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> new file mode 100644
>> index 0000000..a072ea9
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> @@ -0,0 +1,39 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong@huawei>
>> + *	Rongrong Zou <zourongrong@gmail.com>
>> + *	Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_DRV_H
>> +#define HIBMC_DRM_DRV_H
>> +
>> +#include <drm/drmP.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include <drm/drm_gem_cma_helper.h>
>> +
>> +struct hibmc_drm_device {
>> +	/* hw */
>> +	void __iomem   *mmio;
>> +	void __iomem   *fb_map;
>> +	unsigned long  fb_base;
>> +	unsigned long  fb_size;
>> +
>> +	/* drm */
>> +	struct drm_device  *dev;
>> +	bool mode_config_initialized;
>> +};
>> +
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>> new file mode 100644
>> index 0000000..673be10
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>> @@ -0,0 +1,91 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong@huawei>
>> + *	Rongrong Zou <zourongrong@gmail.com>
>> + *	Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <drm/drmP.h>
>> +#include <drm/drm_fb_helper.h>
>> +#include "hibmc_drm_drv.h"
>> +#include "hibmc_drm_regs.h"
>> +
>> +/*
>> + * It can operate in one of three modes: 0, 1 or Sleep.
>> + */
>> +void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>> +				 unsigned int power_mode)
>> +{
>> +	unsigned int control_value = 0;
>> +	void __iomem   *mmio = hidev->mmio;
>> +
>> +	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
>> +		return;
>> +
>> +	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
>> +	control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
>> +
>> +	control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
>> +			 HIBMC_PW_MODE_CTL_MODE_MASK;
>> +
>> +
>> +    /* Set up other fields in Power Control Register */
>> +	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
>> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
>> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +	} else {
>> +		control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +		control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
>> +				 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>> +
>> +	}
>> +    /* Program new power mode. */
>> +	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
>> +}
>> +
>> +static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
>> +{
>> +	void __iomem   *mmio = hidev->mmio;
>> +
>> +	return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
>> +		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
>> +}
>> +
>> +void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
>> +{
>> +	unsigned int gate_reg;
>> +	unsigned int mode;
>> +	void __iomem   *mmio = hidev->mmio;
>> +
>> +	/* Get current power mode. */
>> +	mode = hibmc_get_power_mode(hidev);
>> +
>> +	switch (mode) {
>> +	case HIBMC_PW_MODE_CTL_MODE_MODE0:
>> +		gate_reg = HIBMC_MODE0_GATE;
>> +		break;
>> +
>> +	case HIBMC_PW_MODE_CTL_MODE_MODE1:
>> +		gate_reg = HIBMC_MODE1_GATE;
>> +		break;
>> +
>> +	default:
>> +		gate_reg = HIBMC_MODE0_GATE;
>> +		break;
>> +	}
>> +	writel(gate, mmio + gate_reg);
>> +}
>> +
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>> new file mode 100644
>> index 0000000..39f7a17
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>> @@ -0,0 +1,28 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong@huawei>
>> + *	Rongrong Zou <zourongrong@gmail.com>
>> + *	Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_POWER_H
>> +#define HIBMC_DRM_POWER_H
>> +
>> +#include "hibmc_drm_drv.h"
>> +
>> +extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>> +				 unsigned int power_mode);
>> +extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
>> +				   unsigned int gate);
>> +#endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>> new file mode 100644
>> index 0000000..4966c42
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>> @@ -0,0 +1,214 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + *	Rongrong Zou <zourongrong@huawei>
>> + *	Rongrong Zou <zourongrong@gmail.com>
>> + *	Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_HW_H
>> +#define HIBMC_DRM_HW_H
>> +
>> +#define OFF 0
>> +#define ON  1
>> +#define DISABLE               0
>> +#define ENABLE                1
>> +
>> +
>> +
>> +/* register definition */
>> +#define HIBMC_MISC_CTRL				0x4
>> +
>> +#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
>> +#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
>> +
>> +#define RESET                0
>> +#define NORMAL               1
>> +
>> +#define HIBMC_CURRENT_GATE			0x000040
>> +#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
>> +#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
>> +
>> +#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
>> +#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
>> +
>> +#define HIBMC_MODE0_GATE			0x000044
>> +#define HIBMC_MODE1_GATE			0x000048
>> +#define HIBMC_POWER_MODE_CTRL			0x00004C
>> +
>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
>> +
>> +#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
>> +#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
>> +#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
>> +
>> +
>> +#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
>> +#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
>> +#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
>> +
>> +#define HIBMC_PANEL_PLL_CTRL			0x00005C
>> +#define HIBMC_CRT_PLL_CTRL			0x000060
>> +
>> +#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
>> +#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
>> +
>> +#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
>> +#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
>> +
>> +#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
>> +#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
>> +
>> +#define OSC					0
>> +#define TESTCLK					1
>> +
>> +#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
>> +#define HIBMC_PLL_CTRL_POD_MASK			0xC000
>> +
>> +#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
>> +#define HIBMC_PLL_CTRL_OD_MASK			0x3000
>> +
>> +#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
>> +#define HIBMC_PLL_CTRL_N_MASK			0xF00
>> +
>> +#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
>> +#define HIBMC_PLL_CTRL_M_MASK			0xFF
>> +
>> +
>> +#define HIBMC_CRT_DISP_CTL			0x80200
>> +
>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
>> +
>> +#define CRTSELECT_VGA                0
>> +#define CRTSELECT_CRT                1
>> +
>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
>> +
>> +#define PHASE_ACTIVE_HIGH      0
>> +#define PHASE_ACTIVE_LOW       1
>> +
>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
>> +
>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
>> +
>> +#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
>> +#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
>> +
>> +
>> +#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
>> +#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
>> +
>> +#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
>> +#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
>> +
>> +
>> +
>> +#define HIBMC_CRT_FB_ADDRESS			0x080204
>> +
>> +#define HIBMC_CRT_FB_WIDTH			0x080208
>> +#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
>> +#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
>> +#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
>> +#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
>> +
>> +
>> +#define HIBMC_CRT_HORZ_TOTAL			0x08020C
>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
>> +
>> +
>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)	((x) << 0)
>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK	0xFFF
>> +
>> +#define HIBMC_CRT_HORZ_SYNC			0x080210
>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
>> +
>> +#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
>> +#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
>> +
>> +#define HIBMC_CRT_VERT_TOTAL			0x080214
>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
>> +
>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)	((x) << 0)
>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK	0x7FF
>> +
>> +#define HIBMC_CRT_VERT_SYNC			0x080218
>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
>> +
>> +
>> +#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
>> +#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
>> +
>> +/* Auto Centering */
>> +#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK	0x7FF0000
>> +
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK	0x7FF
>> +
>> +#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
>> +
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
>> +
>> +/* register to control panel output */
>> +#define DISPLAY_CONTROL_HISILE			0x80288
>> +
>> +/* register and values for PLL control */
>> +#define CRT_PLL1_HS				0x802a8
>> +#define CRT_PLL1_HS_25MHZ			0x23d40f02
>> +#define CRT_PLL1_HS_40MHZ			0x23940801
>> +#define CRT_PLL1_HS_65MHZ			0x23940d01
>> +#define CRT_PLL1_HS_78MHZ			0x23540F82
>> +#define CRT_PLL1_HS_74MHZ			0x23941dc2
>> +#define CRT_PLL1_HS_80MHZ			0x23941001
>> +#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
>> +#define CRT_PLL1_HS_108MHZ			0x23b41b01
>> +#define CRT_PLL1_HS_162MHZ			0x23480681
>> +#define CRT_PLL1_HS_148MHZ			0x23541dc2
>> +#define CRT_PLL1_HS_193MHZ			0x234807c1
>> +
>> +#define CRT_PLL2_HS				0x802ac
>> +#define CRT_PLL2_HS_25MHZ			0x206B851E
>> +#define CRT_PLL2_HS_40MHZ			0x30000000
>> +#define CRT_PLL2_HS_65MHZ			0x40000000
>> +#define CRT_PLL2_HS_78MHZ			0x50E147AE
>> +#define CRT_PLL2_HS_74MHZ			0x602B6AE7
>> +#define CRT_PLL2_HS_80MHZ			0x70000000
>> +#define CRT_PLL2_HS_108MHZ			0x80000000
>> +#define CRT_PLL2_HS_162MHZ			0xA0000000
>> +#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
>> +#define CRT_PLL2_HS_193MHZ			0xC0872B02
>> +
>> +/* Global macros */
>> +#define RGB(r, g, b) \
>> +( \
>> +	(unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
>> +)
>> +
>> +#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
>> +
>> +#define MB(x) ((x) << 20)
>> +
>> +#endif
>> --
>> 1.9.1
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>


-- 
Regards,
Rongrong

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

* Re: [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver
  2016-05-30 12:09     ` Rongrong Zou
@ 2016-05-30 12:51       ` Rongrong Zou
  0 siblings, 0 replies; 15+ messages in thread
From: Rongrong Zou @ 2016-05-30 12:51 UTC (permalink / raw)
  To: Rongrong Zou, airlied, emil.l.velikov, lijianhua, xinliang.liu,
	linux-fbdev, linux-kernel, dri-devel, linuxarm, guohanjun,
	linux-arm-kernel, majun258, Daniel Vetter
  Cc: robert.foss, tomeu.vizoso

Sorry, forgot to add daniel@ffwll.ch to sendto list.

在 2016/5/30 20:09, Rongrong Zou 写道:
> Hi Daniel,
> Thanks for reveiwing!
>
> 在 2016/5/30 17:03, Daniel Vetter 写道:
>> On Sun, May 29, 2016 at 05:40:49PM +0800, Rongrong Zou wrote:
>>> Add DRM master driver for Hisilicon Hibmc SoC which used for
>>> Out-of-band management. Blow is the general hardware connection,
>>> both the Hibmc and the host CPU are on the same mother board.
>>>
>>> +----------+       +----------+
>>> |          | PCIe  |  Hibmc   |
>>> |host CPU( |<----->| display  |
>>> |arm64,x86)|       |subsystem |
>>> +----------+       +----------+
>>>
>>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>>> Signed-off-by: Jianhua Li <lijianhua@huawei.com>
>>> ---
>>>   drivers/gpu/drm/hisilicon/Kconfig                 |   1 +
>>>   drivers/gpu/drm/hisilicon/Makefile                |   3 +-
>>>   drivers/gpu/drm/hisilicon/hibmc/Kconfig           |  13 +
>>>   drivers/gpu/drm/hisilicon/hibmc/Makefile          |   4 +
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c   | 307 ++++++++++++++++++++++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h   |  39 +++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c |  91 +++++++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h |  28 ++
>>>   drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h  | 214 +++++++++++++++
>>>   9 files changed, 699 insertions(+), 1 deletion(-)
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>>   create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>>
>>> diff --git a/drivers/gpu/drm/hisilicon/Kconfig b/drivers/gpu/drm/hisilicon/Kconfig
>>> index 558c61b..2fd2724 100644
>>> --- a/drivers/gpu/drm/hisilicon/Kconfig
>>> +++ b/drivers/gpu/drm/hisilicon/Kconfig
>>> @@ -2,4 +2,5 @@
>>>   # hisilicon drm device configuration.
>>>   # Please keep this list sorted alphabetically
>>>
>>> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
>>>   source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
>>> diff --git a/drivers/gpu/drm/hisilicon/Makefile b/drivers/gpu/drm/hisilicon/Makefile
>>> index e3f6d49..4d7185c 100644
>>> --- a/drivers/gpu/drm/hisilicon/Makefile
>>> +++ b/drivers/gpu/drm/hisilicon/Makefile
>>> @@ -2,4 +2,5 @@
>>>   # Makefile for hisilicon drm drivers.
>>>   # Please keep this list sorted alphabetically
>>>
>>> -obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>>> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
>>> +obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
>>> \ No newline at end of file
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>> new file mode 100644
>>> index 0000000..1e7810d
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>>> @@ -0,0 +1,13 @@
>>> +config DRM_HISI_HIBMC
>>> +    tristate "DRM Support for Hisilicon Hibmc"
>>> +    depends on DRM && PCI
>>> +    select DRM_KMS_HELPER
>>> +    select DRM_KMS_FB_HELPER
>>> +    select DRM_GEM_CMA_HELPER
>>> +    select DRM_KMS_CMA_HELPER
>>> +    select FB_SYS_FILLRECT
>>> +    select FB_SYS_COPYAREA
>>> +    select FB_SYS_IMAGEBLIT
>>> +    help
>>> +      Choose this option if you have a Hisilicon Hibmc soc chipset.
>>> +      If M is selected the module will be called hibmc-drm.
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>> new file mode 100644
>>> index 0000000..533f9ed
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>>> @@ -0,0 +1,4 @@
>>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_power.o
>>> +
>>> +obj-$(CONFIG_DRM_HISI_HIBMC)    +=hibmc-drm.o
>>> +#obj-y    += hibmc-drm.o
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>> new file mode 100644
>>> index 0000000..7eaacd8
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>>> @@ -0,0 +1,307 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong@huawei>
>>> + *    Rongrong Zou <zourongrong@gmail.com>
>>> + *    Jianhua Li <lijianhua@huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#include <linux/module.h>
>>> +#include <linux/console.h>
>>> +#include <drm/drm_atomic_helper.h>
>>> +#include <drm/drm_crtc_helper.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include <drm/drm_gem_cma_helper.h>
>>> +#include <drm/drmP.h>
>>> +
>>> +#include "hibmc_drm_drv.h"
>>> +#include "hibmc_drm_regs.h"
>>> +#include "hibmc_drm_power.h"
>>> +
>>> +static const struct file_operations hibmc_fops = {
>>> +    .owner        = THIS_MODULE,
>>> +    .open        = drm_open,
>>> +    .release    = drm_release,
>>> +    .unlocked_ioctl    = drm_ioctl,
>>> +#ifdef CONFIG_COMPAT
>>> +    .compat_ioctl    = drm_compat_ioctl,
>>> +#endif
>>> +    .poll        = drm_poll,
>>> +    .read        = drm_read,
>>> +    .llseek        = no_llseek,
>>> +};
>>> +
>>> +static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
>>> +{
>>> +    return 0;
>>> +}
>>> +
>>> +static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>>> +{
>>> +}
>>> +
>>> +static struct drm_driver hibmc_driver = {
>>> +    .driver_features    = DRIVER_GEM | DRIVER_MODESET,
>>> +    .fops            = &hibmc_fops,
>>> +    .name            = "hibmc",
>>> +    .desc            = "hibmc drm driver",
>>> +    .major            = 1,
>>> +    .minor            = 0,
>>> +    .get_vblank_counter = drm_vblank_no_hw_counter,
>>> +    .enable_vblank        = hibmc_enable_vblank,
>>> +    .disable_vblank    = hibmc_disable_vblank,
>>> +    .gem_free_object        = drm_gem_cma_free_object,
>>
>> gem_free_object_unlocked pls.
>
> Applied, thanks.
>
>>
>>> +    .gem_vm_ops        = &drm_gem_cma_vm_ops,
>>> +    .dumb_create            = drm_gem_cma_dumb_create,
>>> +    .dumb_map_offset        = drm_gem_cma_dumb_map_offset,
>>> +    .dumb_destroy           = drm_gem_dumb_destroy,
>>> +};
>>> +
>>> +static int hibmc_pm_suspend(struct device *dev)
>>> +{
>>> +    struct pci_dev *pdev = to_pci_dev(dev);
>>> +    struct drm_device *drm_dev = pci_get_drvdata(pdev);
>>> +
>>> +    drm_kms_helper_poll_disable(drm_dev);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_pm_resume(struct device *dev)
>>> +{
>>> +    struct pci_dev *pdev = to_pci_dev(dev);
>>> +    struct drm_device *drm_dev = pci_get_drvdata(pdev);
>>> +
>>> +    drm_helper_resume_force_mode(drm_dev);
>>> +    drm_kms_helper_poll_enable(drm_dev);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static const struct dev_pm_ops hibmc_pm_ops = {
>>> +    SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
>>> +                hibmc_pm_resume)
>>> +};
>>> +
>>> +static const struct drm_mode_config_funcs mode_config_funcs = {
>>> +    .atomic_check = drm_atomic_helper_check,
>>> +    .atomic_commit = drm_atomic_helper_commit,
>>
>> So how exactly does nonblocking commit work for you? Please run the igt
>> validation suit on your new driver, a bunch of collabora engineers are
>> working hard to make it run on non-intel drivers too. Ping Tomeu and
>> Robert Foss for more info on this please.
>
> OK, I should learn igt validation suit and test the new driver.
> I tested the driver with tools such as fbtest before. Thanks.
>
>>
>> Lucky for you I'm working on generic nonblocking support in the atomic
>> helpers, patches are on the mailing list.
>>
>
> It's nice, thanks. :)
>
>>> +};
>>> +
>>> +
>>> +static int hibmc_hw_config(struct hibmc_drm_device *hidev)
>>> +{
>>> +    unsigned int reg;
>>> +
>>> +    /* On hardware reset, power mode 0 is default. */
>>> +    hibmc_set_power_mode(hidev, HIBMC_PW_MODE_CTL_MODE_MODE0);
>>> +
>>> +    /* Enable display power gate & LOCALMEM power gate*/
>>> +    reg = readl(hidev->mmio + HIBMC_CURRENT_GATE);
>>> +    reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
>>> +    reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
>>> +    reg |= HIBMC_CURR_GATE_DISPLAY(ON);
>>> +    reg |= HIBMC_CURR_GATE_LOCALMEM(ON);
>>> +
>>> +    hibmc_set_current_gate(hidev, reg);
>>> +
>>> +    /* Reset the memory controller. If the memory controller
>>> +     * is not reset in chip,the system might hang when sw accesses
>>> +     * the memory.The memory should be resetted after
>>> +     * changing the MXCLK.
>>> +     */
>>> +    reg = readl(hidev->mmio + HIBMC_MISC_CTRL);
>>> +    reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>>> +    reg |= HIBMC_MSCCTL_LOCALMEM_RESET(RESET);
>>> +    writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>>> +
>>> +    reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
>>> +    reg |= HIBMC_MSCCTL_LOCALMEM_RESET(NORMAL);
>>> +
>>> +    writel(reg, hidev->mmio + HIBMC_MISC_CTRL);
>>> +
>>> +    /* We can add more initialization as needed. */
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_hw_map(struct hibmc_drm_device *hidev)
>>> +{
>>> +    struct drm_device *dev = hidev->dev;
>>> +    struct pci_dev *pdev = dev->pdev;
>>> +    resource_size_t addr, size, ioaddr, iosize;
>>> +
>>> +    ioaddr = pci_resource_start(pdev, 1);
>>> +    iosize = MB(2);
>>> +
>>> +    hidev->mmio = ioremap_nocache(ioaddr, iosize);
>>> +
>>> +    if (!hidev->mmio) {
>>> +        DRM_ERROR("Cannot map mmio region\n");
>>> +        return -ENOMEM;
>>> +    }
>>> +
>>> +    addr = pci_resource_start(pdev, 0);
>>> +    size = MB(16);
>>> +
>>> +    hidev->fb_map = ioremap(addr, size);
>>> +    if (!hidev->fb_map) {
>>> +        DRM_ERROR("Cannot map framebuffer\n");
>>> +        return -ENOMEM;
>>> +    }
>>> +    hidev->fb_base = addr;
>>> +    hidev->fb_size = size;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static void hibmc_hw_fini(struct hibmc_drm_device *hidev)
>>> +{
>>> +    if (hidev->mmio)
>>> +        iounmap(hidev->mmio);
>>> +    if (hidev->fb_map)
>>> +        iounmap(hidev->fb_map);
>>> +}
>>> +
>>> +static int hibmc_hw_init(struct hibmc_drm_device *hidev)
>>> +{
>>> +    int ret;
>>> +
>>> +    ret = hibmc_hw_map(hidev);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    hibmc_hw_config(hidev);
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_unload(struct drm_device *dev)
>>> +{
>>> +    struct hibmc_drm_device *hidev = dev->dev_private;
>>> +
>>> +    hibmc_hw_fini(hidev);
>>> +    dev->dev_private = NULL;
>>> +    return 0;
>>> +}
>>> +
>>> +static int hibmc_load(struct drm_device *dev, unsigned long flags)
>>> +{
>>> +    struct hibmc_drm_device *hidev;
>>> +    int ret;
>>> +
>>> +    hidev = devm_kzalloc(dev->dev, sizeof(*hidev), GFP_KERNEL);
>>> +    if (!hidev)
>>> +        return -ENOMEM;
>>> +    dev->dev_private = hidev;
>>> +    hidev->dev = dev;
>>> +
>>> +    ret = hibmc_hw_init(hidev);
>>> +    if (ret)
>>> +        goto err;
>>> +
>>> +
>>> +    ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
>>> +    if (ret) {
>>> +        DRM_ERROR("failed to initialize vblank.\n");
>>> +        return ret;
>>> +    }
>>> +    /* reset all the states of crtc/plane/encoder/connector */
>>> +    drm_mode_config_reset(dev);
>>> +
>>> +    return 0;
>>> +
>>> +err:
>>> +    hibmc_unload(dev);
>>> +    DRM_ERROR("failed to initialize drm driver.\n");
>>> +    return ret;
>>> +}
>>> +
>>> +
>>> +static int hibmc_pci_probe(struct pci_dev *pdev,
>>> +               const struct pci_device_id *ent)
>>> +{
>>> +    struct drm_device *dev;
>>> +    int ret;
>>> +
>>> +    dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
>>> +    if (!dev)
>>> +        return -ENOMEM;
>>> +
>>> +    dev->pdev = pdev;
>>> +    pci_set_drvdata(pdev, dev);
>>> +
>>> +    ret = pci_enable_device(pdev);
>>> +    if (ret)
>>> +        goto err_free;
>>> +
>>> +    ret = hibmc_load(dev, 0);
>>> +    if (ret)
>>> +        goto err_disable;
>>> +
>>> +    ret = drm_dev_register(dev, 0);
>>> +    if (ret)
>>> +        goto err_unload;
>>> +
>>> +    return 0;
>>> +
>>> +err_unload:
>>> +    hibmc_unload(dev);
>>> +err_disable:
>>> +    pci_disable_device(pdev);
>>> +err_free:
>>> +    drm_dev_unref(dev);
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static void hibmc_pci_remove(struct pci_dev *pdev)
>>> +{
>>> +    struct drm_device *dev = pci_get_drvdata(pdev);
>>> +
>>> +    drm_dev_unregister(dev);
>>> +    hibmc_unload(dev);
>>> +    drm_dev_unref(dev);
>>> +}
>>> +
>>> +static struct pci_device_id hibmc_pci_table[] = {
>>> +    {0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
>>> +    {0,}
>>> +};
>>> +
>>> +static struct pci_driver hibmc_pci_driver = {
>>> +    .name =        "hibmc-drm",
>>> +    .id_table =    hibmc_pci_table,
>>> +    .probe =    hibmc_pci_probe,
>>> +    .remove =    hibmc_pci_remove,
>>> +    .driver.pm =    &hibmc_pm_ops,
>>> +};
>>> +
>>> +static int __init hibmc_init(void)
>>> +{
>>> +    return pci_register_driver(&hibmc_pci_driver);
>>> +}
>>> +
>>> +static void __exit hibmc_exit(void)
>>> +{
>>> +    return pci_unregister_driver(&hibmc_pci_driver);
>>> +}
>>> +
>>> +module_init(hibmc_init);
>>> +module_exit(hibmc_exit);
>>> +
>>> +MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
>>> +MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
>>> +MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
>>> +MODULE_LICENSE("GPL v2");
>>> +
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>> new file mode 100644
>>> index 0000000..a072ea9
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>>> @@ -0,0 +1,39 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong@huawei>
>>> + *    Rongrong Zou <zourongrong@gmail.com>
>>> + *    Jianhua Li <lijianhua@huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#ifndef HIBMC_DRM_DRV_H
>>> +#define HIBMC_DRM_DRV_H
>>> +
>>> +#include <drm/drmP.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include <drm/drm_gem_cma_helper.h>
>>> +
>>> +struct hibmc_drm_device {
>>> +    /* hw */
>>> +    void __iomem   *mmio;
>>> +    void __iomem   *fb_map;
>>> +    unsigned long  fb_base;
>>> +    unsigned long  fb_size;
>>> +
>>> +    /* drm */
>>> +    struct drm_device  *dev;
>>> +    bool mode_config_initialized;
>>> +};
>>> +
>>> +
>>> +#endif
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>> new file mode 100644
>>> index 0000000..673be10
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.c
>>> @@ -0,0 +1,91 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong@huawei>
>>> + *    Rongrong Zou <zourongrong@gmail.com>
>>> + *    Jianhua Li <lijianhua@huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +#include <drm/drmP.h>
>>> +#include <drm/drm_fb_helper.h>
>>> +#include "hibmc_drm_drv.h"
>>> +#include "hibmc_drm_regs.h"
>>> +
>>> +/*
>>> + * It can operate in one of three modes: 0, 1 or Sleep.
>>> + */
>>> +void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>>> +                 unsigned int power_mode)
>>> +{
>>> +    unsigned int control_value = 0;
>>> +    void __iomem   *mmio = hidev->mmio;
>>> +
>>> +    if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
>>> +        return;
>>> +
>>> +    control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
>>> +    control_value &= ~HIBMC_PW_MODE_CTL_MODE_MASK;
>>> +
>>> +    control_value |= HIBMC_PW_MODE_CTL_MODE(power_mode) &
>>> +             HIBMC_PW_MODE_CTL_MODE_MASK;
>>> +
>>> +
>>> +    /* Set up other fields in Power Control Register */
>>> +    if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP) {
>>> +        control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +        control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(0) &
>>> +                 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +    } else {
>>> +        control_value &= ~HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +        control_value |= HIBMC_PW_MODE_CTL_OSC_INPUT(1) &
>>> +                 HIBMC_PW_MODE_CTL_OSC_INPUT_MASK;
>>> +
>>> +    }
>>> +    /* Program new power mode. */
>>> +    writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
>>> +}
>>> +
>>> +static unsigned int hibmc_get_power_mode(struct hibmc_drm_device *hidev)
>>> +{
>>> +    void __iomem   *mmio = hidev->mmio;
>>> +
>>> +    return (readl(mmio + HIBMC_POWER_MODE_CTRL)&
>>> +        HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
>>> +}
>>> +
>>> +void hibmc_set_current_gate(struct hibmc_drm_device *hidev, unsigned int gate)
>>> +{
>>> +    unsigned int gate_reg;
>>> +    unsigned int mode;
>>> +    void __iomem   *mmio = hidev->mmio;
>>> +
>>> +    /* Get current power mode. */
>>> +    mode = hibmc_get_power_mode(hidev);
>>> +
>>> +    switch (mode) {
>>> +    case HIBMC_PW_MODE_CTL_MODE_MODE0:
>>> +        gate_reg = HIBMC_MODE0_GATE;
>>> +        break;
>>> +
>>> +    case HIBMC_PW_MODE_CTL_MODE_MODE1:
>>> +        gate_reg = HIBMC_MODE1_GATE;
>>> +        break;
>>> +
>>> +    default:
>>> +        gate_reg = HIBMC_MODE0_GATE;
>>> +        break;
>>> +    }
>>> +    writel(gate, mmio + gate_reg);
>>> +}
>>> +
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>> new file mode 100644
>>> index 0000000..39f7a17
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_power.h
>>> @@ -0,0 +1,28 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong@huawei>
>>> + *    Rongrong Zou <zourongrong@gmail.com>
>>> + *    Jianhua Li <lijianhua@huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#ifndef HIBMC_DRM_POWER_H
>>> +#define HIBMC_DRM_POWER_H
>>> +
>>> +#include "hibmc_drm_drv.h"
>>> +
>>> +extern void hibmc_set_power_mode(struct hibmc_drm_device *hidev,
>>> +                 unsigned int power_mode);
>>> +extern void hibmc_set_current_gate(struct hibmc_drm_device *hidev,
>>> +                   unsigned int gate);
>>> +#endif
>>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>> new file mode 100644
>>> index 0000000..4966c42
>>> --- /dev/null
>>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
>>> @@ -0,0 +1,214 @@
>>> +/* Hisilicon Hibmc SoC drm driver
>>> + *
>>> + * Based on the bochs drm driver.
>>> + *
>>> + * Copyright (c) 2016 Huawei Limited.
>>> + *
>>> + * Author:
>>> + *    Rongrong Zou <zourongrong@huawei>
>>> + *    Rongrong Zou <zourongrong@gmail.com>
>>> + *    Jianhua Li <lijianhua@huawei.com>
>>> + *
>>> + * 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.
>>> + *
>>> + */
>>> +
>>> +#ifndef HIBMC_DRM_HW_H
>>> +#define HIBMC_DRM_HW_H
>>> +
>>> +#define OFF 0
>>> +#define ON  1
>>> +#define DISABLE               0
>>> +#define ENABLE                1
>>> +
>>> +
>>> +
>>> +/* register definition */
>>> +#define HIBMC_MISC_CTRL                0x4
>>> +
>>> +#define HIBMC_MSCCTL_LOCALMEM_RESET(x)        ((x) << 6)
>>> +#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK    0x40
>>> +
>>> +#define RESET                0
>>> +#define NORMAL               1
>>> +
>>> +#define HIBMC_CURRENT_GATE            0x000040
>>> +#define HIBMC_CURR_GATE_DISPLAY(x)        ((x) << 2)
>>> +#define HIBMC_CURR_GATE_DISPLAY_MASK        0x4
>>> +
>>> +#define HIBMC_CURR_GATE_LOCALMEM(x)        ((x) << 1)
>>> +#define HIBMC_CURR_GATE_LOCALMEM_MASK        0x2
>>> +
>>> +#define HIBMC_MODE0_GATE            0x000044
>>> +#define HIBMC_MODE1_GATE            0x000048
>>> +#define HIBMC_POWER_MODE_CTRL            0x00004C
>>> +
>>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)        ((x) << 3)
>>> +#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK    0x8
>>> +
>>> +#define HIBMC_PW_MODE_CTL_MODE(x)        ((x) << 0)
>>> +#define HIBMC_PW_MODE_CTL_MODE_MASK        0x03
>>> +#define HIBMC_PW_MODE_CTL_MODE_SHIFT        0
>>> +
>>> +
>>> +#define HIBMC_PW_MODE_CTL_MODE_MODE0        0
>>> +#define HIBMC_PW_MODE_CTL_MODE_MODE1        1
>>> +#define HIBMC_PW_MODE_CTL_MODE_SLEEP        2
>>> +
>>> +#define HIBMC_PANEL_PLL_CTRL            0x00005C
>>> +#define HIBMC_CRT_PLL_CTRL            0x000060
>>> +
>>> +#define HIBMC_PLL_CTRL_BYPASS(x)        ((x) << 18)
>>> +#define HIBMC_PLL_CTRL_BYPASS_MASK        0x40000
>>> +
>>> +#define HIBMC_PLL_CTRL_POWER(x)            ((x) << 17)
>>> +#define HIBMC_PLL_CTRL_POWER_MASK        0x20000
>>> +
>>> +#define HIBMC_PLL_CTRL_INPUT(x)            ((x) << 16)
>>> +#define HIBMC_PLL_CTRL_INPUT_MASK        0x10000
>>> +
>>> +#define OSC                    0
>>> +#define TESTCLK                    1
>>> +
>>> +#define HIBMC_PLL_CTRL_POD(x)            ((x) << 14)
>>> +#define HIBMC_PLL_CTRL_POD_MASK            0xC000
>>> +
>>> +#define HIBMC_PLL_CTRL_OD(x)            ((x) << 12)
>>> +#define HIBMC_PLL_CTRL_OD_MASK            0x3000
>>> +
>>> +#define HIBMC_PLL_CTRL_N(x)            ((x) << 8)
>>> +#define HIBMC_PLL_CTRL_N_MASK            0xF00
>>> +
>>> +#define HIBMC_PLL_CTRL_M(x)            ((x) << 0)
>>> +#define HIBMC_PLL_CTRL_M_MASK            0xFF
>>> +
>>> +
>>> +#define HIBMC_CRT_DISP_CTL            0x80200
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)        ((x) << 25)
>>> +#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK    0x2000000
>>> +
>>> +#define CRTSELECT_VGA                0
>>> +#define CRTSELECT_CRT                1
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)    ((x) << 14)
>>> +#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK    0x4000
>>> +
>>> +#define PHASE_ACTIVE_HIGH      0
>>> +#define PHASE_ACTIVE_LOW       1
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)    ((x) << 13)
>>> +#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK    0x2000
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)    ((x) << 12)
>>> +#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK    0x1000
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_TIMING(x)        ((x) << 8)
>>> +#define HIBMC_CRT_DISP_CTL_TIMING_MASK        0x100
>>> +
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_PLANE(x)        ((x) << 2)
>>> +#define HIBMC_CRT_DISP_CTL_PLANE_MASK        4
>>> +
>>> +#define HIBMC_CRT_DISP_CTL_FORMAT(x)        ((x) << 0)
>>> +#define HIBMC_CRT_DISP_CTL_FORMAT_MASK        0x03
>>> +
>>> +
>>> +
>>> +#define HIBMC_CRT_FB_ADDRESS            0x080204
>>> +
>>> +#define HIBMC_CRT_FB_WIDTH            0x080208
>>> +#define HIBMC_CRT_FB_WIDTH_WIDTH(x)        ((x) << 16)
>>> +#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK        0x3FFF0000
>>> +#define HIBMC_CRT_FB_WIDTH_OFFS(x)        ((x) << 0)
>>> +#define HIBMC_CRT_FB_WIDTH_OFFS_MASK        0x3FFF
>>> +
>>> +
>>> +#define HIBMC_CRT_HORZ_TOTAL            0x08020C
>>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)        ((x) << 16)
>>> +#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK        0xFFF0000
>>> +
>>> +
>>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END(x)    ((x) << 0)
>>> +#define HIBMC_CRT_HORZ_TOTAL_DISPLAY_END_MASK    0xFFF
>>> +
>>> +#define HIBMC_CRT_HORZ_SYNC            0x080210
>>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)        ((x) << 16)
>>> +#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK        0xFF0000
>>> +
>>> +#define HIBMC_CRT_HORZ_SYNC_START(x)        ((x) << 0)
>>> +#define HIBMC_CRT_HORZ_SYNC_START_MASK        0xFFF
>>> +
>>> +#define HIBMC_CRT_VERT_TOTAL            0x080214
>>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)        ((x) << 16)
>>> +#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK        0x7FFF0000
>>> +
>>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END(x)    ((x) << 0)
>>> +#define HIBMC_CRT_VERT_TOTAL_DISPLAY_END_MASK    0x7FF
>>> +
>>> +#define HIBMC_CRT_VERT_SYNC            0x080218
>>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)        ((x) << 16)
>>> +#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK        0x3F0000
>>> +
>>> +
>>> +#define HIBMC_CRT_VERT_SYNC_START(x)        ((x) << 0)
>>> +#define HIBMC_CRT_VERT_SYNC_START_MASK        0x7FF
>>> +
>>> +/* Auto Centering */
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL        0x080280
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)    ((x) << 16)
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MSK    0x7FF0000
>>> +
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)    ((x) << 0)
>>> +#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MSK    0x7FF
>>> +
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR        0x080284
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)    ((x) << 16)
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK    0x7FF0000
>>> +
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)    ((x) << 0)
>>> +#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK    0x7FF
>>> +
>>> +/* register to control panel output */
>>> +#define DISPLAY_CONTROL_HISILE            0x80288
>>> +
>>> +/* register and values for PLL control */
>>> +#define CRT_PLL1_HS                0x802a8
>>> +#define CRT_PLL1_HS_25MHZ            0x23d40f02
>>> +#define CRT_PLL1_HS_40MHZ            0x23940801
>>> +#define CRT_PLL1_HS_65MHZ            0x23940d01
>>> +#define CRT_PLL1_HS_78MHZ            0x23540F82
>>> +#define CRT_PLL1_HS_74MHZ            0x23941dc2
>>> +#define CRT_PLL1_HS_80MHZ            0x23941001
>>> +#define CRT_PLL1_HS_80MHZ_1152            0x23540fc2
>>> +#define CRT_PLL1_HS_108MHZ            0x23b41b01
>>> +#define CRT_PLL1_HS_162MHZ            0x23480681
>>> +#define CRT_PLL1_HS_148MHZ            0x23541dc2
>>> +#define CRT_PLL1_HS_193MHZ            0x234807c1
>>> +
>>> +#define CRT_PLL2_HS                0x802ac
>>> +#define CRT_PLL2_HS_25MHZ            0x206B851E
>>> +#define CRT_PLL2_HS_40MHZ            0x30000000
>>> +#define CRT_PLL2_HS_65MHZ            0x40000000
>>> +#define CRT_PLL2_HS_78MHZ            0x50E147AE
>>> +#define CRT_PLL2_HS_74MHZ            0x602B6AE7
>>> +#define CRT_PLL2_HS_80MHZ            0x70000000
>>> +#define CRT_PLL2_HS_108MHZ            0x80000000
>>> +#define CRT_PLL2_HS_162MHZ            0xA0000000
>>> +#define CRT_PLL2_HS_148MHZ            0xB0CCCCCD
>>> +#define CRT_PLL2_HS_193MHZ            0xC0872B02
>>> +
>>> +/* Global macros */
>>> +#define RGB(r, g, b) \
>>> +( \
>>> +    (unsigned long)(((r) << 16) | ((g) << 8) | (b)) \
>>> +)
>>> +
>>> +#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
>>> +
>>> +#define MB(x) ((x) << 20)
>>> +
>>> +#endif
>>> --
>>> 1.9.1
>>>
>>> _______________________________________________
>>> dri-devel mailing list
>>> dri-devel@lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>>
>
>


-- 
Regards,
Rongrong

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

end of thread, other threads:[~2016-05-30 12:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-29  9:40 [path v2 0/7] Add DRM driver for Hisilicon Hibmc Rongrong Zou
2016-05-29  9:40 ` [path v2 1/7] drm/hisilicon/hibmc: Add hisilicon hibmc drm master driver Rongrong Zou
2016-05-30  9:03   ` Daniel Vetter
2016-05-30 12:09     ` Rongrong Zou
2016-05-30 12:51       ` Rongrong Zou
2016-05-29  9:40 ` [path v2 2/7] drm/hisilicon/hibmc: Add plane for DE Rongrong Zou
2016-05-29  9:40 ` [path v2 3/7] drm/hisilicon/hibmc: Add crtc " Rongrong Zou
2016-05-29  9:40 ` [path v2 4/7] drm/hisilicon/hibmc: Add encoder for VDAC Rongrong Zou
2016-05-29  9:40 ` [path v2 5/7] drm/hisilicon/hibmc: Add connector " Rongrong Zou
2016-05-29  9:40 ` [path v2 6/7] drm/hisilicon/hibmc: Add support for frame buffer Rongrong Zou
2016-05-29  9:40 ` [path v2 7/7] drm/hisilicon/hibmc: Add maintainer for Hibmc DRM Rongrong Zou
2016-05-30  2:31   ` Xinliang Liu
2016-05-30  3:21     ` Rongrong Zou
2016-05-30  3:01 ` [path v2 0/7] Add DRM driver for Hisilicon Hibmc Xinliang Liu
2016-05-30  3:11   ` Rongrong Zou

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).