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
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
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
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
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
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
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
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; +} +
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; +} +
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; +}
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
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
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
.
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
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
.
dri-devel@lists.freedesktop.org