* [PATCH v6 5/9] [media] add maintainers for DRM STM driver
From: Yannick Fertre @ 2017-04-14 8:10 UTC (permalink / raw)
To: Alexandre TORGUE, Thierry Reding, David Airlie, Maxime Coquelin,
Russell King, Mark Rutland, Rob Herring, Arnd Bergmann,
Benjamin Gaignard, Yannick Fertre
Cc: devicetree, kernel, Philippe Cornu, Fabien Dessenne, dri-devel,
Mickael Reulier, Vincent Abriou, Gabriel FERNANDEZ,
linux-arm-kernel
In-Reply-To: <1492157455-2283-1-git-send-email-yannick.fertre@st.com>
Add Philippe Cornu and myself as maintainers.
Signed-off-by: Yannick Fertre <yannick.fertre@st.com>
---
MAINTAINERS | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index c36dfae..84cf73f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4424,6 +4424,15 @@ S: Maintained
F: drivers/gpu/drm/sti
F: Documentation/devicetree/bindings/display/st,stih4xx.txt
+DRM DRIVERS FOR STM
+M: Yannick Fertre <yannick.fertre@st.com>
+M: Philippe Cornu <philippe.cornu@st.com>
+L: dri-devel@lists.freedesktop.org
+T: git git://anongit.freedesktop.org/drm/drm-misc
+S: Maintained
+F: drivers/gpu/drm/stm
+F: Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
+
DRM DRIVER FOR TDFX VIDEO CARDS
S: Orphan / Obsolete
F: drivers/gpu/drm/tdfx/
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH v6 4/9] drm/stm: Add STM32 LTDC driver
From: Yannick Fertre @ 2017-04-14 8:10 UTC (permalink / raw)
To: Alexandre TORGUE, Thierry Reding, David Airlie, Maxime Coquelin,
Russell King, Mark Rutland, Rob Herring, Arnd Bergmann,
Benjamin Gaignard, Yannick Fertre
Cc: devicetree, kernel, Philippe Cornu, Fabien Dessenne, dri-devel,
Mickael Reulier, Vincent Abriou, Gabriel FERNANDEZ,
linux-arm-kernel
In-Reply-To: <1492157455-2283-1-git-send-email-yannick.fertre@st.com>
This controller provides output signals to interface directly a variety
of LCD and TFT panels. These output signals are: RGB signals
(up to 24bpp), vertical & horizontal synchronisations, data enable and
the pixel clock.
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Yannick Fertre <yannick.fertre@st.com>
---
drivers/gpu/drm/Kconfig | 2 +
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/stm/Kconfig | 16 +
drivers/gpu/drm/stm/Makefile | 7 +
drivers/gpu/drm/stm/drv.c | 221 ++++++++
drivers/gpu/drm/stm/ltdc.c | 1161 ++++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/stm/ltdc.h | 40 ++
7 files changed, 1448 insertions(+)
create mode 100644 drivers/gpu/drm/stm/Kconfig
create mode 100644 drivers/gpu/drm/stm/Makefile
create mode 100644 drivers/gpu/drm/stm/drv.c
create mode 100644 drivers/gpu/drm/stm/ltdc.c
create mode 100644 drivers/gpu/drm/stm/ltdc.h
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 78d7fc0..f57540d 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -246,6 +246,8 @@ source "drivers/gpu/drm/fsl-dcu/Kconfig"
source "drivers/gpu/drm/tegra/Kconfig"
+source "drivers/gpu/drm/stm/Kconfig"
+
source "drivers/gpu/drm/panel/Kconfig"
source "drivers/gpu/drm/bridge/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 59f0f9b..aa62ded 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_DRM_BOCHS) += bochs/
obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio/
obj-$(CONFIG_DRM_MSM) += msm/
obj-$(CONFIG_DRM_TEGRA) += tegra/
+obj-$(CONFIG_DRM_STM) += stm/
obj-$(CONFIG_DRM_STI) += sti/
obj-$(CONFIG_DRM_IMX) += imx/
obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
diff --git a/drivers/gpu/drm/stm/Kconfig b/drivers/gpu/drm/stm/Kconfig
new file mode 100644
index 0000000..2c4817f
--- /dev/null
+++ b/drivers/gpu/drm/stm/Kconfig
@@ -0,0 +1,16 @@
+config DRM_STM
+ tristate "DRM Support for STMicroelectronics SoC Series"
+ depends on DRM && (ARCH_STM32 || ARCH_MULTIPLATFORM)
+ select DRM_KMS_HELPER
+ select DRM_GEM_CMA_HELPER
+ select DRM_KMS_CMA_HELPER
+ select DRM_PANEL
+ select VIDEOMODE_HELPERS
+ select FB_PROVIDE_GET_FB_UNMAPPED_AREA
+ default y
+
+ help
+ Enable support for the on-chip display controller on
+ STMicroelectronics STM32 MCUs.
+ To compile this driver as a module, choose M here: the module
+ will be called stm-drm.
diff --git a/drivers/gpu/drm/stm/Makefile b/drivers/gpu/drm/stm/Makefile
new file mode 100644
index 0000000..e114d45
--- /dev/null
+++ b/drivers/gpu/drm/stm/Makefile
@@ -0,0 +1,7 @@
+ccflags-y := -Iinclude/drm
+
+stm-drm-y := \
+ drv.o \
+ ltdc.o
+
+obj-$(CONFIG_DRM_STM) += stm-drm.o
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
new file mode 100644
index 0000000..83ab48f
--- /dev/null
+++ b/drivers/gpu/drm/stm/drv.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2017
+ *
+ * Authors: Philippe Cornu <philippe.cornu@st.com>
+ * Yannick Fertre <yannick.fertre@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * Mickael Reulier <mickael.reulier@st.com>
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/component.h>
+#include <linux/of_platform.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "ltdc.h"
+
+#define DRIVER_NAME "stm"
+#define DRIVER_DESC "STMicroelectronics SoC DRM"
+#define DRIVER_DATE "20170330"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+#define DRIVER_PATCH_LEVEL 0
+
+#define STM_MAX_FB_WIDTH 2048
+#define STM_MAX_FB_HEIGHT 2048 /* same as width to handle orientation */
+
+static void drv_output_poll_changed(struct drm_device *ddev)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ drm_fbdev_cma_hotplug_event(ldev->fbdev);
+}
+
+static const struct drm_mode_config_funcs drv_mode_config_funcs = {
+ .fb_create = drm_fb_cma_create,
+ .output_poll_changed = drv_output_poll_changed,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static void drv_lastclose(struct drm_device *ddev)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ DRM_DEBUG("%s\n", __func__);
+
+ drm_fbdev_cma_restore_mode(ldev->fbdev);
+}
+
+DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops);
+
+static struct drm_driver drv_driver = {
+ .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+ DRIVER_ATOMIC,
+ .lastclose = drv_lastclose,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCH_LEVEL,
+ .fops = &drv_driver_fops,
+ .dumb_create = drm_gem_cma_dumb_create,
+ .dumb_map_offset = drm_gem_cma_dumb_map_offset,
+ .dumb_destroy = drm_gem_dumb_destroy,
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_free_object_unlocked = drm_gem_cma_free_object,
+ .gem_vm_ops = &drm_gem_cma_vm_ops,
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+ .gem_prime_vmap = drm_gem_cma_prime_vmap,
+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+ .gem_prime_mmap = drm_gem_cma_prime_mmap,
+ .enable_vblank = ltdc_crtc_enable_vblank,
+ .disable_vblank = ltdc_crtc_disable_vblank,
+};
+
+static int drv_load(struct drm_device *ddev)
+{
+ struct platform_device *pdev = to_platform_device(ddev->dev);
+ struct drm_fbdev_cma *fbdev;
+ struct ltdc_device *ldev;
+ int ret;
+
+ DRM_DEBUG("%s\n", __func__);
+
+ ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL);
+ if (!ldev)
+ return -ENOMEM;
+
+ ddev->dev_private = (void *)ldev;
+
+ drm_mode_config_init(ddev);
+
+ /*
+ * set max width and height as default value.
+ * this value would be used to check framebuffer size limitation
+ * at drm_mode_addfb().
+ */
+ ddev->mode_config.min_width = 0;
+ ddev->mode_config.min_height = 0;
+ ddev->mode_config.max_width = STM_MAX_FB_WIDTH;
+ ddev->mode_config.max_height = STM_MAX_FB_HEIGHT;
+ ddev->mode_config.funcs = &drv_mode_config_funcs;
+
+ ret = ltdc_load(ddev);
+ if (ret)
+ goto err;
+
+ drm_mode_config_reset(ddev);
+ drm_kms_helper_poll_init(ddev);
+
+ if (ddev->mode_config.num_connector) {
+ ldev = ddev->dev_private;
+ fbdev = drm_fbdev_cma_init(ddev, 16,
+ ddev->mode_config.num_connector);
+ if (IS_ERR(fbdev)) {
+ DRM_DEBUG("Warning: fails to create fbdev\n");
+ fbdev = NULL;
+ }
+ ldev->fbdev = fbdev;
+ }
+
+ platform_set_drvdata(pdev, ddev);
+
+ return 0;
+err:
+ drm_mode_config_cleanup(ddev);
+ return ret;
+}
+
+static void drv_unload(struct drm_device *ddev)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ DRM_DEBUG("%s\n", __func__);
+
+ if (ldev->fbdev) {
+ drm_fbdev_cma_fini(ldev->fbdev);
+ ldev->fbdev = NULL;
+ }
+ drm_kms_helper_poll_fini(ddev);
+ ltdc_unload(ddev);
+ drm_mode_config_cleanup(ddev);
+}
+
+static int stm_drm_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct drm_device *ddev;
+ int ret;
+
+ DRM_DEBUG("%s\n", __func__);
+
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+
+ ddev = drm_dev_alloc(&drv_driver, dev);
+ if (IS_ERR(ddev))
+ return PTR_ERR(ddev);
+
+ ret = drv_load(ddev);
+ if (ret)
+ goto err_unref;
+
+ ret = drm_dev_register(ddev, 0);
+ if (ret)
+ goto err_unref;
+
+ return 0;
+
+err_unref:
+ drm_dev_unref(ddev);
+
+ return ret;
+}
+
+static int stm_drm_platform_remove(struct platform_device *pdev)
+{
+ struct drm_device *ddev = platform_get_drvdata(pdev);
+
+ DRM_DEBUG("%s\n", __func__);
+
+ drm_dev_unregister(ddev);
+ drv_unload(ddev);
+ drm_dev_unref(ddev);
+
+ return 0;
+}
+
+static const struct of_device_id drv_dt_ids[] = {
+ { .compatible = "st,stm32-ltdc"},
+ { /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, drv_dt_ids);
+
+static struct platform_driver stm_drm_platform_driver = {
+ .probe = stm_drm_platform_probe,
+ .remove = stm_drm_platform_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = drv_dt_ids,
+ },
+};
+
+module_platform_driver(stm_drm_platform_driver);
+
+MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
+MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
+MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
+MODULE_AUTHOR("Mickael Reulier <mickael.reulier@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST DRM LTDC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c
new file mode 100644
index 0000000..a373178
--- /dev/null
+++ b/drivers/gpu/drm/stm/ltdc.c
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2017
+ *
+ * Authors: Philippe Cornu <philippe.cornu@st.com>
+ * Yannick Fertre <yannick.fertre@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * Mickael Reulier <mickael.reulier@st.com>
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_address.h>
+#include <linux/of_graph.h>
+#include <linux/reset.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_plane_helper.h>
+
+#include <video/videomode.h>
+
+#include "ltdc.h"
+
+#define NB_CRTC 1
+#define CRTC_MASK GENMASK(NB_CRTC - 1, 0)
+
+#define MAX_IRQ 4
+
+#define HWVER_10200 0x010200
+#define HWVER_10300 0x010300
+#define HWVER_20101 0x020101
+
+/*
+ * The address of some registers depends on the HW version: such registers have
+ * an extra offset specified with reg_ofs.
+ */
+#define REG_OFS_NONE 0
+#define REG_OFS_4 4 /* Insertion of "Layer Configuration 2" reg */
+#define REG_OFS (ldev->caps.reg_ofs)
+#define LAY_OFS 0x80 /* Register Offset between 2 layers */
+
+/* Global register offsets */
+#define LTDC_IDR 0x0000 /* IDentification */
+#define LTDC_LCR 0x0004 /* Layer Count */
+#define LTDC_SSCR 0x0008 /* Synchronization Size Configuration */
+#define LTDC_BPCR 0x000C /* Back Porch Configuration */
+#define LTDC_AWCR 0x0010 /* Active Width Configuration */
+#define LTDC_TWCR 0x0014 /* Total Width Configuration */
+#define LTDC_GCR 0x0018 /* Global Control */
+#define LTDC_GC1R 0x001C /* Global Configuration 1 */
+#define LTDC_GC2R 0x0020 /* Global Configuration 2 */
+#define LTDC_SRCR 0x0024 /* Shadow Reload Configuration */
+#define LTDC_GACR 0x0028 /* GAmma Correction */
+#define LTDC_BCCR 0x002C /* Background Color Configuration */
+#define LTDC_IER 0x0034 /* Interrupt Enable */
+#define LTDC_ISR 0x0038 /* Interrupt Status */
+#define LTDC_ICR 0x003C /* Interrupt Clear */
+#define LTDC_LIPCR 0x0040 /* Line Interrupt Position Configuration */
+#define LTDC_CPSR 0x0044 /* Current Position Status */
+#define LTDC_CDSR 0x0048 /* Current Display Status */
+
+/* Layer register offsets */
+#define LTDC_L1LC1R (0x0080) /* L1 Layer Configuration 1 */
+#define LTDC_L1LC2R (0x0084) /* L1 Layer Configuration 2 */
+#define LTDC_L1CR (0x0084 + REG_OFS) /* L1 Control */
+#define LTDC_L1WHPCR (0x0088 + REG_OFS) /* L1 Window Hor Position Config */
+#define LTDC_L1WVPCR (0x008C + REG_OFS) /* L1 Window Vert Position Config */
+#define LTDC_L1CKCR (0x0090 + REG_OFS) /* L1 Color Keying Configuration */
+#define LTDC_L1PFCR (0x0094 + REG_OFS) /* L1 Pixel Format Configuration */
+#define LTDC_L1CACR (0x0098 + REG_OFS) /* L1 Constant Alpha Config */
+#define LTDC_L1DCCR (0x009C + REG_OFS) /* L1 Default Color Configuration */
+#define LTDC_L1BFCR (0x00A0 + REG_OFS) /* L1 Blend Factors Configuration */
+#define LTDC_L1FBBCR (0x00A4 + REG_OFS) /* L1 FrameBuffer Bus Control */
+#define LTDC_L1AFBCR (0x00A8 + REG_OFS) /* L1 AuxFB Control */
+#define LTDC_L1CFBAR (0x00AC + REG_OFS) /* L1 Color FrameBuffer Address */
+#define LTDC_L1CFBLR (0x00B0 + REG_OFS) /* L1 Color FrameBuffer Length */
+#define LTDC_L1CFBLNR (0x00B4 + REG_OFS) /* L1 Color FrameBuffer Line Nb */
+#define LTDC_L1AFBAR (0x00B8 + REG_OFS) /* L1 AuxFB Address */
+#define LTDC_L1AFBLR (0x00BC + REG_OFS) /* L1 AuxFB Length */
+#define LTDC_L1AFBLNR (0x00C0 + REG_OFS) /* L1 AuxFB Line Number */
+#define LTDC_L1CLUTWR (0x00C4 + REG_OFS) /* L1 CLUT Write */
+#define LTDC_L1YS1R (0x00E0 + REG_OFS) /* L1 YCbCr Scale 1 */
+#define LTDC_L1YS2R (0x00E4 + REG_OFS) /* L1 YCbCr Scale 2 */
+
+/* Bit definitions */
+#define SSCR_VSH GENMASK(10, 0) /* Vertical Synchronization Height */
+#define SSCR_HSW GENMASK(27, 16) /* Horizontal Synchronization Width */
+
+#define BPCR_AVBP GENMASK(10, 0) /* Accumulated Vertical Back Porch */
+#define BPCR_AHBP GENMASK(27, 16) /* Accumulated Horizontal Back Porch */
+
+#define AWCR_AAH GENMASK(10, 0) /* Accumulated Active Height */
+#define AWCR_AAW GENMASK(27, 16) /* Accumulated Active Width */
+
+#define TWCR_TOTALH GENMASK(10, 0) /* TOTAL Height */
+#define TWCR_TOTALW GENMASK(27, 16) /* TOTAL Width */
+
+#define GCR_LTDCEN BIT(0) /* LTDC ENable */
+#define GCR_DEN BIT(16) /* Dither ENable */
+#define GCR_PCPOL BIT(28) /* Pixel Clock POLarity */
+#define GCR_DEPOL BIT(29) /* Data Enable POLarity */
+#define GCR_VSPOL BIT(30) /* Vertical Synchro POLarity */
+#define GCR_HSPOL BIT(31) /* Horizontal Synchro POLarity */
+
+#define GC1R_WBCH GENMASK(3, 0) /* Width of Blue CHannel output */
+#define GC1R_WGCH GENMASK(7, 4) /* Width of Green Channel output */
+#define GC1R_WRCH GENMASK(11, 8) /* Width of Red Channel output */
+#define GC1R_PBEN BIT(12) /* Precise Blending ENable */
+#define GC1R_DT GENMASK(15, 14) /* Dithering Technique */
+#define GC1R_GCT GENMASK(19, 17) /* Gamma Correction Technique */
+#define GC1R_SHREN BIT(21) /* SHadow Registers ENabled */
+#define GC1R_BCP BIT(22) /* Background Colour Programmable */
+#define GC1R_BBEN BIT(23) /* Background Blending ENabled */
+#define GC1R_LNIP BIT(24) /* Line Number IRQ Position */
+#define GC1R_TP BIT(25) /* Timing Programmable */
+#define GC1R_IPP BIT(26) /* IRQ Polarity Programmable */
+#define GC1R_SPP BIT(27) /* Sync Polarity Programmable */
+#define GC1R_DWP BIT(28) /* Dither Width Programmable */
+#define GC1R_STREN BIT(29) /* STatus Registers ENabled */
+#define GC1R_BMEN BIT(31) /* Blind Mode ENabled */
+
+#define GC2R_EDCA BIT(0) /* External Display Control Ability */
+#define GC2R_STSAEN BIT(1) /* Slave Timing Sync Ability ENabled */
+#define GC2R_DVAEN BIT(2) /* Dual-View Ability ENabled */
+#define GC2R_DPAEN BIT(3) /* Dual-Port Ability ENabled */
+#define GC2R_BW GENMASK(6, 4) /* Bus Width (log2 of nb of bytes) */
+#define GC2R_EDCEN BIT(7) /* External Display Control ENabled */
+
+#define SRCR_IMR BIT(0) /* IMmediate Reload */
+#define SRCR_VBR BIT(1) /* Vertical Blanking Reload */
+
+#define BCCR_BCBLACK 0x00 /* Background Color BLACK */
+#define BCCR_BCBLUE GENMASK(7, 0) /* Background Color BLUE */
+#define BCCR_BCGREEN GENMASK(15, 8) /* Background Color GREEN */
+#define BCCR_BCRED GENMASK(23, 16) /* Background Color RED */
+#define BCCR_BCWHITE GENMASK(23, 0) /* Background Color WHITE */
+
+#define IER_LIE BIT(0) /* Line Interrupt Enable */
+#define IER_FUIE BIT(1) /* Fifo Underrun Interrupt Enable */
+#define IER_TERRIE BIT(2) /* Transfer ERRor Interrupt Enable */
+#define IER_RRIE BIT(3) /* Register Reload Interrupt enable */
+
+#define ISR_LIF BIT(0) /* Line Interrupt Flag */
+#define ISR_FUIF BIT(1) /* Fifo Underrun Interrupt Flag */
+#define ISR_TERRIF BIT(2) /* Transfer ERRor Interrupt Flag */
+#define ISR_RRIF BIT(3) /* Register Reload Interrupt Flag */
+
+#define LXCR_LEN BIT(0) /* Layer ENable */
+#define LXCR_COLKEN BIT(1) /* Color Keying Enable */
+#define LXCR_CLUTEN BIT(4) /* Color Look-Up Table ENable */
+
+#define LXWHPCR_WHSTPOS GENMASK(11, 0) /* Window Horizontal StarT POSition */
+#define LXWHPCR_WHSPPOS GENMASK(27, 16) /* Window Horizontal StoP POSition */
+
+#define LXWVPCR_WVSTPOS GENMASK(10, 0) /* Window Vertical StarT POSition */
+#define LXWVPCR_WVSPPOS GENMASK(26, 16) /* Window Vertical StoP POSition */
+
+#define LXPFCR_PF GENMASK(2, 0) /* Pixel Format */
+
+#define LXCACR_CONSTA GENMASK(7, 0) /* CONSTant Alpha */
+
+#define LXBFCR_BF2 GENMASK(2, 0) /* Blending Factor 2 */
+#define LXBFCR_BF1 GENMASK(10, 8) /* Blending Factor 1 */
+
+#define LXCFBLR_CFBLL GENMASK(12, 0) /* Color Frame Buffer Line Length */
+#define LXCFBLR_CFBP GENMASK(28, 16) /* Color Frame Buffer Pitch in bytes */
+
+#define LXCFBLNR_CFBLN GENMASK(10, 0) /* Color Frame Buffer Line Number */
+
+#define HSPOL_AL 0 /* Horizontal Sync POLarity Active Low */
+#define VSPOL_AL 0 /* Vertical Sync POLarity Active Low */
+#define DEPOL_AL 0 /* Data Enable POLarity Active Low */
+#define PCPOL_IPC 0 /* Input Pixel Clock */
+#define HSPOL_AH GCR_HSPOL /* Horizontal Sync POLarity Active High */
+#define VSPOL_AH GCR_VSPOL /* Vertical Sync POLarity Active High */
+#define DEPOL_AH GCR_DEPOL /* Data Enable POLarity Active High */
+#define PCPOL_IIPC GCR_PCPOL /* Inverted Input Pixel Clock */
+#define CONSTA_MAX 0xFF /* CONSTant Alpha MAX= 1.0 */
+#define BF1_PAXCA 0x600 /* Pixel Alpha x Constant Alpha */
+#define BF1_CA 0x400 /* Constant Alpha */
+#define BF2_1PAXCA 0x007 /* 1 - (Pixel Alpha x Constant Alpha) */
+#define BF2_1CA 0x005 /* 1 - Constant Alpha */
+
+#define NB_PF 8 /* Max nb of HW pixel format */
+
+enum ltdc_pix_fmt {
+ PF_NONE,
+ /* RGB formats */
+ PF_ARGB8888, /* ARGB [32 bits] */
+ PF_RGBA8888, /* RGBA [32 bits] */
+ PF_RGB888, /* RGB [24 bits] */
+ PF_RGB565, /* RGB [16 bits] */
+ PF_ARGB1555, /* ARGB A:1 bit RGB:15 bits [16 bits] */
+ PF_ARGB4444, /* ARGB A:4 bits R/G/B: 4 bits each [16 bits] */
+ /* Indexed formats */
+ PF_L8, /* Indexed 8 bits [8 bits] */
+ PF_AL44, /* Alpha:4 bits + indexed 4 bits [8 bits] */
+ PF_AL88 /* Alpha:8 bits + indexed 8 bits [16 bits] */
+};
+
+/* The index gives the encoding of the pixel format for an HW version */
+static const enum ltdc_pix_fmt ltdc_pix_fmt_a0[NB_PF] = {
+ PF_ARGB8888, /* 0x00 */
+ PF_RGB888, /* 0x01 */
+ PF_RGB565, /* 0x02 */
+ PF_ARGB1555, /* 0x03 */
+ PF_ARGB4444, /* 0x04 */
+ PF_L8, /* 0x05 */
+ PF_AL44, /* 0x06 */
+ PF_AL88 /* 0x07 */
+};
+
+static const enum ltdc_pix_fmt ltdc_pix_fmt_a1[NB_PF] = {
+ PF_ARGB8888, /* 0x00 */
+ PF_RGB888, /* 0x01 */
+ PF_RGB565, /* 0x02 */
+ PF_RGBA8888, /* 0x03 */
+ PF_AL44, /* 0x04 */
+ PF_L8, /* 0x05 */
+ PF_ARGB1555, /* 0x06 */
+ PF_ARGB4444 /* 0x07 */
+};
+
+static inline u32 reg_read(void __iomem *base, u32 reg)
+{
+ return readl_relaxed(base + reg);
+}
+
+static inline void reg_write(void __iomem *base, u32 reg, u32 val)
+{
+ writel_relaxed(val, base + reg);
+}
+
+static inline void reg_set(void __iomem *base, u32 reg, u32 mask)
+{
+ reg_write(base, reg, reg_read(base, reg) | mask);
+}
+
+static inline void reg_clear(void __iomem *base, u32 reg, u32 mask)
+{
+ reg_write(base, reg, reg_read(base, reg) & ~mask);
+}
+
+static inline void reg_update_bits(void __iomem *base, u32 reg, u32 mask,
+ u32 val)
+{
+ reg_write(base, reg, (reg_read(base, reg) & ~mask) | val);
+}
+
+static inline struct ltdc_device *crtc_to_ltdc(struct drm_crtc *crtc)
+{
+ return (struct ltdc_device *)crtc->dev->dev_private;
+}
+
+static inline struct ltdc_device *plane_to_ltdc(struct drm_plane *plane)
+{
+ return (struct ltdc_device *)plane->dev->dev_private;
+}
+
+static inline struct ltdc_device *encoder_to_ltdc(struct drm_encoder *enc)
+{
+ return (struct ltdc_device *)enc->dev->dev_private;
+}
+
+static inline struct ltdc_device *connector_to_ltdc(struct drm_connector *con)
+{
+ return (struct ltdc_device *)con->dev->dev_private;
+}
+
+static inline enum ltdc_pix_fmt to_ltdc_pixelformat(u32 drm_fmt)
+{
+ enum ltdc_pix_fmt pf;
+
+ switch (drm_fmt) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ pf = PF_ARGB8888;
+ break;
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_RGBX8888:
+ pf = PF_RGBA8888;
+ break;
+ case DRM_FORMAT_RGB888:
+ pf = PF_RGB888;
+ break;
+ case DRM_FORMAT_RGB565:
+ pf = PF_RGB565;
+ break;
+ case DRM_FORMAT_ARGB1555:
+ case DRM_FORMAT_XRGB1555:
+ pf = PF_ARGB1555;
+ break;
+ case DRM_FORMAT_ARGB4444:
+ case DRM_FORMAT_XRGB4444:
+ pf = PF_ARGB4444;
+ break;
+ case DRM_FORMAT_C8:
+ pf = PF_L8;
+ break;
+ default:
+ pf = PF_NONE;
+ break;
+ /* Note: There are no DRM_FORMAT for AL44 and AL88 */
+ }
+
+ return pf;
+}
+
+static inline u32 to_drm_pixelformat(enum ltdc_pix_fmt pf)
+{
+ switch (pf) {
+ case PF_ARGB8888:
+ return DRM_FORMAT_ARGB8888;
+ case PF_RGBA8888:
+ return DRM_FORMAT_RGBA8888;
+ case PF_RGB888:
+ return DRM_FORMAT_RGB888;
+ case PF_RGB565:
+ return DRM_FORMAT_RGB565;
+ case PF_ARGB1555:
+ return DRM_FORMAT_ARGB1555;
+ case PF_ARGB4444:
+ return DRM_FORMAT_ARGB4444;
+ case PF_L8:
+ return DRM_FORMAT_C8;
+ case PF_AL44: /* No DRM support */
+ case PF_AL88: /* No DRM support */
+ case PF_NONE:
+ default:
+ return 0;
+ }
+}
+
+static irqreturn_t ltdc_irq_thread(int irq, void *arg)
+{
+ struct drm_device *ddev = arg;
+ struct ltdc_device *ldev = ddev->dev_private;
+ struct drm_crtc *crtc = drm_crtc_from_index(ddev, 0);
+
+ /* Line IRQ : trigger the vblank event */
+ if (ldev->irq_status & ISR_LIF)
+ drm_crtc_handle_vblank(crtc);
+
+ /* Save FIFO Underrun & Transfer Error status */
+ mutex_lock(&ldev->err_lock);
+ if (ldev->irq_status & ISR_FUIF)
+ ldev->error_status |= ISR_FUIF;
+ if (ldev->irq_status & ISR_TERRIF)
+ ldev->error_status |= ISR_TERRIF;
+ mutex_unlock(&ldev->err_lock);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ltdc_irq(int irq, void *arg)
+{
+ struct drm_device *ddev = arg;
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ /* Read & Clear the interrupt status */
+ ldev->irq_status = reg_read(ldev->regs, LTDC_ISR);
+ reg_write(ldev->regs, LTDC_ICR, ldev->irq_status);
+
+ return IRQ_WAKE_THREAD;
+}
+
+/*
+ * DRM_CRTC
+ */
+
+static void ltdc_crtc_load_lut(struct drm_crtc *crtc)
+{
+ struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+ unsigned int i, lay;
+
+ for (lay = 0; lay < ldev->caps.nb_layers; lay++)
+ for (i = 0; i < 256; i++)
+ reg_write(ldev->regs, LTDC_L1CLUTWR + lay * LAY_OFS,
+ ldev->clut[i]);
+}
+
+static void ltdc_crtc_enable(struct drm_crtc *crtc)
+{
+ struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /* Sets the background color value */
+ reg_write(ldev->regs, LTDC_BCCR, BCCR_BCBLACK);
+
+ /* Enable IRQ */
+ reg_set(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
+
+ /* Immediately commit the planes */
+ reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);
+
+ /* Enable LTDC */
+ reg_set(ldev->regs, LTDC_GCR, GCR_LTDCEN);
+
+ drm_crtc_vblank_on(crtc);
+}
+
+static void ltdc_crtc_disable(struct drm_crtc *crtc)
+{
+ struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+ struct drm_pending_vblank_event *event = crtc->state->event;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_crtc_vblank_off(crtc);
+
+ /* disable LTDC */
+ reg_clear(ldev->regs, LTDC_GCR, GCR_LTDCEN);
+
+ /* disable IRQ */
+ reg_clear(ldev->regs, LTDC_IER, IER_RRIE | IER_FUIE | IER_TERRIE);
+
+ /* immediately commit disable of layers before switching off LTDC */
+ reg_set(ldev->regs, LTDC_SRCR, SRCR_IMR);
+}
+
+static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+ struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+ struct videomode vm;
+ int rate = mode->clock * 1000;
+ u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h;
+ u32 total_width, total_height;
+ u32 val;
+
+ drm_display_mode_to_videomode(mode, &vm);
+
+ DRM_DEBUG_DRIVER("CRTC:%d mode:%s\n", crtc->base.id, mode->name);
+ DRM_DEBUG_DRIVER("Video mode: %dx%d", vm.hactive, vm.vactive);
+ DRM_DEBUG_DRIVER(" hfp %d hbp %d hsl %d vfp %d vbp %d vsl %d\n",
+ vm.hfront_porch, vm.hback_porch, vm.hsync_len,
+ vm.vfront_porch, vm.vback_porch, vm.vsync_len);
+
+ /* Convert video timings to ltdc timings */
+ hsync = vm.hsync_len - 1;
+ vsync = vm.vsync_len - 1;
+ accum_hbp = hsync + vm.hback_porch;
+ accum_vbp = vsync + vm.vback_porch;
+ accum_act_w = accum_hbp + vm.hactive;
+ accum_act_h = accum_vbp + vm.vactive;
+ total_width = accum_act_w + vm.hfront_porch;
+ total_height = accum_act_h + vm.vfront_porch;
+
+ clk_disable(ldev->pixel_clk);
+
+ if (clk_set_rate(ldev->pixel_clk, rate) < 0) {
+ DRM_ERROR("Cannot set rate (%dHz) for pixel clk\n", rate);
+ return;
+ }
+
+ clk_enable(ldev->pixel_clk);
+
+ /* Configures the HS, VS, DE and PC polarities. */
+ val = HSPOL_AL | HSPOL_AL | DEPOL_AL | PCPOL_IPC;
+
+ if (vm.flags & DISPLAY_FLAGS_HSYNC_HIGH)
+ val |= HSPOL_AH;
+
+ if (vm.flags & DISPLAY_FLAGS_VSYNC_HIGH)
+ val |= VSPOL_AH;
+
+ if (vm.flags & DISPLAY_FLAGS_DE_HIGH)
+ val |= DEPOL_AH;
+
+ if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+ val |= PCPOL_IIPC;
+
+ reg_update_bits(ldev->regs, LTDC_GCR,
+ GCR_HSPOL | GCR_VSPOL | GCR_DEPOL | GCR_PCPOL, val);
+
+ /* Set Synchronization size */
+ val = (hsync << 16) | vsync;
+ reg_update_bits(ldev->regs, LTDC_SSCR, SSCR_VSH | SSCR_HSW, val);
+
+ /* Set Accumulated Back porch */
+ val = (accum_hbp << 16) | accum_vbp;
+ reg_update_bits(ldev->regs, LTDC_BPCR, BPCR_AVBP | BPCR_AHBP, val);
+
+ /* Set Accumulated Active Width */
+ val = (accum_act_w << 16) | accum_act_h;
+ reg_update_bits(ldev->regs, LTDC_AWCR, AWCR_AAW | AWCR_AAH, val);
+
+ /* Set total width & height */
+ val = (total_width << 16) | total_height;
+ reg_update_bits(ldev->regs, LTDC_TWCR, TWCR_TOTALH | TWCR_TOTALW, val);
+
+ reg_write(ldev->regs, LTDC_LIPCR, (accum_act_h + 1));
+}
+
+static void ltdc_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state)
+{
+ struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+ struct drm_pending_vblank_event *event = crtc->state->event;
+
+ DRM_DEBUG_ATOMIC("\n");
+
+ /* Commit shadow registers = update planes at next vblank */
+ reg_set(ldev->regs, LTDC_SRCR, SRCR_VBR);
+
+ if (event) {
+ crtc->state->event = NULL;
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ if (drm_crtc_vblank_get(crtc) == 0)
+ drm_crtc_arm_vblank_event(crtc, event);
+ else
+ drm_crtc_send_vblank_event(crtc, event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+ }
+}
+
+static struct drm_crtc_helper_funcs ltdc_crtc_helper_funcs = {
+ .load_lut = ltdc_crtc_load_lut,
+ .enable = ltdc_crtc_enable,
+ .disable = ltdc_crtc_disable,
+ .mode_set_nofb = ltdc_crtc_mode_set_nofb,
+ .atomic_flush = ltdc_crtc_atomic_flush,
+};
+
+int ltdc_crtc_enable_vblank(struct drm_device *ddev, unsigned int pipe)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ DRM_DEBUG_DRIVER("\n");
+ reg_set(ldev->regs, LTDC_IER, IER_LIE);
+
+ return 0;
+}
+
+void ltdc_crtc_disable_vblank(struct drm_device *ddev, unsigned int pipe)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ DRM_DEBUG_DRIVER("\n");
+ reg_clear(ldev->regs, LTDC_IER, IER_LIE);
+}
+
+static struct drm_crtc_funcs ltdc_crtc_funcs = {
+ .destroy = drm_crtc_cleanup,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+/*
+ * DRM_PLANE
+ */
+
+static int ltdc_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct drm_framebuffer *fb = state->fb;
+ u32 src_x, src_y, src_w, src_h;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (!fb)
+ return 0;
+
+ /* convert src_ from 16:16 format */
+ src_x = state->src_x >> 16;
+ src_y = state->src_y >> 16;
+ src_w = state->src_w >> 16;
+ src_h = state->src_h >> 16;
+
+ /* Reject scaling */
+ if ((src_w != state->crtc_w) || (src_h != state->crtc_h)) {
+ DRM_ERROR("Scaling is not supported");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void ltdc_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *oldstate)
+{
+ struct ltdc_device *ldev = plane_to_ltdc(plane);
+ struct drm_plane_state *state = plane->state;
+ struct drm_framebuffer *fb = state->fb;
+ u32 lofs = plane->index * LAY_OFS;
+ u32 x0 = state->crtc_x;
+ u32 x1 = state->crtc_x + state->crtc_w - 1;
+ u32 y0 = state->crtc_y;
+ u32 y1 = state->crtc_y + state->crtc_h - 1;
+ u32 src_x, src_y, src_w, src_h;
+ u32 val, pitch_in_bytes, line_length, paddr, ahbp, avbp, bpcr;
+ enum ltdc_pix_fmt pf;
+
+ if (!state->crtc || !fb) {
+ DRM_DEBUG_DRIVER("fb or crtc NULL");
+ return;
+ }
+
+ /* convert src_ from 16:16 format */
+ src_x = state->src_x >> 16;
+ src_y = state->src_y >> 16;
+ src_w = state->src_w >> 16;
+ src_h = state->src_h >> 16;
+
+ DRM_DEBUG_DRIVER(
+ "plane:%d fb:%d (%dx%d)@(%d,%d) -> (%dx%d)@(%d,%d)\n",
+ plane->base.id, fb->base.id,
+ src_w, src_h, src_x, src_y,
+ state->crtc_w, state->crtc_h, state->crtc_x, state->crtc_y);
+
+ bpcr = reg_read(ldev->regs, LTDC_BPCR);
+ ahbp = (bpcr & BPCR_AHBP) >> 16;
+ avbp = bpcr & BPCR_AVBP;
+
+ /* Configures the horizontal start and stop position */
+ val = ((x1 + 1 + ahbp) << 16) + (x0 + 1 + ahbp);
+ reg_update_bits(ldev->regs, LTDC_L1WHPCR + lofs,
+ LXWHPCR_WHSTPOS | LXWHPCR_WHSPPOS, val);
+
+ /* Configures the vertical start and stop position */
+ val = ((y1 + 1 + avbp) << 16) + (y0 + 1 + avbp);
+ reg_update_bits(ldev->regs, LTDC_L1WVPCR + lofs,
+ LXWVPCR_WVSTPOS | LXWVPCR_WVSPPOS, val);
+
+ /* Specifies the pixel format */
+ pf = to_ltdc_pixelformat(fb->format->format);
+ for (val = 0; val < NB_PF; val++)
+ if (ldev->caps.pix_fmt_hw[val] == pf)
+ break;
+
+ if (val == NB_PF) {
+ DRM_ERROR("Pixel format %.4s not supported\n",
+ (char *)&fb->format->format);
+ val = 0; /* set by default ARGB 32 bits */
+ }
+ reg_update_bits(ldev->regs, LTDC_L1PFCR + lofs, LXPFCR_PF, val);
+
+ /* Configures the color frame buffer pitch in bytes & line length */
+ pitch_in_bytes = fb->pitches[0];
+ line_length = drm_format_plane_cpp(fb->format->format, 0) *
+ (x1 - x0 + 1) + (ldev->caps.bus_width >> 3) - 1;
+ val = ((pitch_in_bytes << 16) | line_length);
+ reg_update_bits(ldev->regs, LTDC_L1CFBLR + lofs,
+ LXCFBLR_CFBLL | LXCFBLR_CFBP, val);
+
+ /* Specifies the constant alpha value */
+ val = CONSTA_MAX;
+ reg_update_bits(ldev->regs, LTDC_L1CACR + lofs,
+ LXCACR_CONSTA, val);
+
+ /* Specifies the blending factors */
+ val = BF1_PAXCA | BF2_1PAXCA;
+ reg_update_bits(ldev->regs, LTDC_L1BFCR + lofs,
+ LXBFCR_BF2 | LXBFCR_BF1, val);
+
+ /* Configures the frame buffer line number */
+ val = y1 - y0 + 1;
+ reg_update_bits(ldev->regs, LTDC_L1CFBLNR + lofs,
+ LXCFBLNR_CFBLN, val);
+
+ /* Sets the FB address */
+ paddr = (u32)drm_fb_cma_get_gem_addr(fb, state, 0);
+
+ DRM_DEBUG_DRIVER("fb: phys 0x%08x", paddr);
+ reg_write(ldev->regs, LTDC_L1CFBAR + lofs, paddr);
+
+ /* Enable layer and CLUT if needed */
+ val = fb->format->format == DRM_FORMAT_C8 ? LXCR_CLUTEN : 0;
+ val |= LXCR_LEN;
+ reg_update_bits(ldev->regs, LTDC_L1CR + lofs,
+ LXCR_LEN | LXCR_CLUTEN, val);
+
+ mutex_lock(&ldev->err_lock);
+ if (ldev->error_status & ISR_FUIF) {
+ DRM_DEBUG_DRIVER("Fifo underrun\n");
+ ldev->error_status &= ~ISR_FUIF;
+ }
+ if (ldev->error_status & ISR_TERRIF) {
+ DRM_DEBUG_DRIVER("Transfer error\n");
+ ldev->error_status &= ~ISR_TERRIF;
+ }
+ mutex_unlock(&ldev->err_lock);
+}
+
+static void ltdc_plane_atomic_disable(struct drm_plane *plane,
+ struct drm_plane_state *oldstate)
+{
+ struct ltdc_device *ldev = plane_to_ltdc(plane);
+ u32 lofs = plane->index * LAY_OFS;
+
+ /* disable layer */
+ reg_clear(ldev->regs, LTDC_L1CR + lofs, LXCR_LEN);
+
+ DRM_DEBUG_DRIVER("CRTC:%d plane:%d\n",
+ oldstate->crtc->base.id, plane->base.id);
+}
+
+static struct drm_plane_funcs ltdc_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .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 ltdc_plane_helper_funcs = {
+ .atomic_check = ltdc_plane_atomic_check,
+ .atomic_update = ltdc_plane_atomic_update,
+ .atomic_disable = ltdc_plane_atomic_disable,
+};
+
+static struct drm_plane *ltdc_plane_create(struct drm_device *ddev,
+ enum drm_plane_type type)
+{
+ unsigned long possible_crtcs = CRTC_MASK;
+ struct ltdc_device *ldev = ddev->dev_private;
+ struct device *dev = ddev->dev;
+ struct drm_plane *plane;
+ unsigned int i, nb_fmt = 0;
+ u32 formats[NB_PF];
+ u32 drm_fmt;
+ int ret;
+
+ /* Get supported pixel formats */
+ for (i = 0; i < NB_PF; i++) {
+ drm_fmt = to_drm_pixelformat(ldev->caps.pix_fmt_hw[i]);
+ if (!drm_fmt)
+ continue;
+ formats[nb_fmt++] = drm_fmt;
+ }
+
+ plane = devm_kzalloc(dev, sizeof(*plane), GFP_KERNEL);
+ if (!plane)
+ return 0;
+
+ ret = drm_universal_plane_init(ddev, plane, possible_crtcs,
+ <dc_plane_funcs, formats, nb_fmt,
+ type, NULL);
+ if (ret < 0)
+ return 0;
+
+ drm_plane_helper_add(plane, <dc_plane_helper_funcs);
+
+ DRM_DEBUG_DRIVER("plane:%d created\n", plane->base.id);
+
+ return plane;
+}
+
+static void ltdc_plane_destroy_all(struct drm_device *ddev)
+{
+ struct drm_plane *plane, *plane_temp;
+
+ list_for_each_entry_safe(plane, plane_temp,
+ &ddev->mode_config.plane_list, head)
+ drm_plane_cleanup(plane);
+}
+
+static int ltdc_crtc_init(struct drm_device *ddev, struct drm_crtc *crtc)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+ struct drm_plane *primary, *overlay;
+ unsigned int i;
+ int res;
+
+ primary = ltdc_plane_create(ddev, DRM_PLANE_TYPE_PRIMARY);
+ if (!primary) {
+ DRM_ERROR("Can not create primary plane\n");
+ return -EINVAL;
+ }
+
+ res = drm_crtc_init_with_planes(ddev, crtc, primary, NULL,
+ <dc_crtc_funcs, NULL);
+ if (res) {
+ DRM_ERROR("Can not initialize CRTC\n");
+ goto cleanup;
+ }
+
+ drm_crtc_helper_add(crtc, <dc_crtc_helper_funcs);
+
+ DRM_DEBUG_DRIVER("CRTC:%d created\n", crtc->base.id);
+
+ /* Add planes. Note : the first layer is used by primary plane */
+ for (i = 1; i < ldev->caps.nb_layers; i++) {
+ overlay = ltdc_plane_create(ddev, DRM_PLANE_TYPE_OVERLAY);
+ if (!overlay) {
+ res = -ENOMEM;
+ DRM_ERROR("Can not create overlay plane %d\n", i);
+ goto cleanup;
+ }
+ }
+
+ return 0;
+
+cleanup:
+ ltdc_plane_destroy_all(ddev);
+ return res;
+}
+
+/*
+ * DRM_ENCODER
+ */
+
+static void ltdc_rgb_encoder_enable(struct drm_encoder *encoder)
+{
+ struct ltdc_device *ldev = encoder_to_ltdc(encoder);
+
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_panel_prepare(ldev->panel);
+ drm_panel_enable(ldev->panel);
+}
+
+static void ltdc_rgb_encoder_disable(struct drm_encoder *encoder)
+{
+ struct ltdc_device *ldev = encoder_to_ltdc(encoder);
+
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_panel_disable(ldev->panel);
+ drm_panel_unprepare(ldev->panel);
+}
+
+static const struct drm_encoder_helper_funcs ltdc_rgb_encoder_helper_funcs = {
+ .enable = ltdc_rgb_encoder_enable,
+ .disable = ltdc_rgb_encoder_disable,
+};
+
+static const struct drm_encoder_funcs ltdc_rgb_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+static struct drm_encoder *ltdc_rgb_encoder_create(struct drm_device *ddev)
+{
+ struct drm_encoder *encoder;
+
+ encoder = devm_kzalloc(ddev->dev, sizeof(*encoder), GFP_KERNEL);
+ if (!encoder)
+ return NULL;
+
+ encoder->possible_crtcs = CRTC_MASK;
+ encoder->possible_clones = 0; /* No cloning support */
+
+ drm_encoder_init(ddev, encoder, <dc_rgb_encoder_funcs,
+ DRM_MODE_ENCODER_DPI, NULL);
+
+ drm_encoder_helper_add(encoder, <dc_rgb_encoder_helper_funcs);
+
+ DRM_DEBUG_DRIVER("RGB encoder:%d created\n", encoder->base.id);
+
+ return encoder;
+}
+
+/*
+ * DRM_CONNECTOR
+ */
+
+static int ltdc_rgb_connector_get_modes(struct drm_connector *connector)
+{
+ struct drm_device *ddev = connector->dev;
+ struct ltdc_device *ldev = ddev->dev_private;
+ int ret = 0;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ if (ldev->panel)
+ ret = drm_panel_get_modes(ldev->panel);
+
+ return ret < 0 ? 0 : ret;
+}
+
+static struct drm_connector_helper_funcs ltdc_rgb_connector_helper_funcs = {
+ .get_modes = ltdc_rgb_connector_get_modes,
+};
+
+static enum drm_connector_status
+ltdc_rgb_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct ltdc_device *ldev = connector_to_ltdc(connector);
+
+ return ldev->panel ? connector_status_connected :
+ connector_status_disconnected;
+}
+
+static void ltdc_rgb_connector_destroy(struct drm_connector *connector)
+{
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_connector_unregister(connector);
+ drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs ltdc_rgb_connector_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .detect = ltdc_rgb_connector_detect,
+ .destroy = ltdc_rgb_connector_destroy,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+struct drm_connector *ltdc_rgb_connector_create(struct drm_device *ddev)
+{
+ struct drm_connector *connector;
+ int err;
+
+ connector = devm_kzalloc(ddev->dev, sizeof(*connector), GFP_KERNEL);
+ if (!connector) {
+ DRM_ERROR("Failed to allocate connector\n");
+ return NULL;
+ }
+
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+ err = drm_connector_init(ddev, connector, <dc_rgb_connector_funcs,
+ DRM_MODE_CONNECTOR_DPI);
+ if (err) {
+ DRM_ERROR("Failed to initialize connector\n");
+ return NULL;
+ }
+
+ drm_connector_helper_add(connector, <dc_rgb_connector_helper_funcs);
+
+ DRM_DEBUG_DRIVER("RGB connector:%d created\n", connector->base.id);
+
+ return connector;
+}
+
+static int ltdc_get_caps(struct drm_device *ddev)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+ u32 bus_width_log2, lcr, gc2r;
+
+ /* at least 1 layer must be managed */
+ lcr = reg_read(ldev->regs, LTDC_LCR);
+
+ ldev->caps.nb_layers = max_t(int, lcr, 1);
+
+ /* set data bus width */
+ gc2r = reg_read(ldev->regs, LTDC_GC2R);
+ bus_width_log2 = (gc2r & GC2R_BW) >> 4;
+ ldev->caps.bus_width = 8 << bus_width_log2;
+ ldev->caps.hw_version = reg_read(ldev->regs, LTDC_IDR);
+
+ switch (ldev->caps.hw_version) {
+ case HWVER_10200:
+ case HWVER_10300:
+ ldev->caps.reg_ofs = REG_OFS_NONE;
+ ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a0;
+ break;
+ case HWVER_20101:
+ ldev->caps.reg_ofs = REG_OFS_4;
+ ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a1;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static struct drm_panel *ltdc_get_panel(struct drm_device *ddev)
+{
+ struct device *dev = ddev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *entity, *port = NULL;
+ struct drm_panel *panel = NULL;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ /*
+ * Parse ltdc node to get remote port and find RGB panel / HDMI slave
+ * If a dsi or a bridge (hdmi, lvds...) is connected to ltdc,
+ * a remote port & RGB panel will not be found.
+ */
+ for_each_endpoint_of_node(np, entity) {
+ if (!of_device_is_available(entity))
+ continue;
+
+ port = of_graph_get_remote_port_parent(entity);
+ if (port) {
+ panel = of_drm_find_panel(port);
+ of_node_put(port);
+ if (panel) {
+ DRM_DEBUG_DRIVER("remote panel %s\n",
+ port->full_name);
+ } else {
+ DRM_DEBUG_DRIVER("panel missing\n");
+ of_node_put(entity);
+ }
+ }
+ }
+
+ return panel;
+}
+
+int ltdc_load(struct drm_device *ddev)
+{
+ struct platform_device *pdev = to_platform_device(ddev->dev);
+ struct ltdc_device *ldev = ddev->dev_private;
+ struct device *dev = ddev->dev;
+ struct device_node *np = dev->of_node;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector = NULL;
+ struct drm_crtc *crtc;
+ struct reset_control *rstc;
+ struct resource res;
+ int irq, ret, i;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ ldev->panel = ltdc_get_panel(ddev);
+ if (!ldev->panel)
+ return -EPROBE_DEFER;
+
+ rstc = of_reset_control_get(np, NULL);
+
+ mutex_init(&ldev->err_lock);
+
+ ldev->pixel_clk = devm_clk_get(dev, "lcd");
+ if (IS_ERR(ldev->pixel_clk)) {
+ DRM_ERROR("Unable to get lcd clock\n");
+ return -ENODEV;
+ }
+
+ if (clk_prepare_enable(ldev->pixel_clk)) {
+ DRM_ERROR("Unable to prepare pixel clock\n");
+ return -ENODEV;
+ }
+
+ if (of_address_to_resource(np, 0, &res)) {
+ DRM_ERROR("Unable to get resource\n");
+ return -ENODEV;
+ }
+
+ ldev->regs = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(ldev->regs)) {
+ DRM_ERROR("Unable to get ltdc registers\n");
+ return PTR_ERR(ldev->regs);
+ }
+
+ for (i = 0; i < MAX_IRQ; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ continue;
+
+ ret = devm_request_threaded_irq(dev, irq, ltdc_irq,
+ ltdc_irq_thread, IRQF_ONESHOT,
+ dev_name(dev), ddev);
+ if (ret) {
+ DRM_ERROR("Failed to register LTDC interrupt\n");
+ return ret;
+ }
+ }
+
+ if (!IS_ERR(rstc))
+ reset_control_deassert(rstc);
+
+ /* Disable interrupts */
+ reg_clear(ldev->regs, LTDC_IER,
+ IER_LIE | IER_RRIE | IER_FUIE | IER_TERRIE);
+
+ ret = ltdc_get_caps(ddev);
+ if (ret) {
+ DRM_ERROR("hardware identifier (0x%08x) not supported!\n",
+ ldev->caps.hw_version);
+ return ret;
+ }
+
+ DRM_INFO("ltdc hw version 0x%08x - ready\n", ldev->caps.hw_version);
+
+ if (ldev->panel) {
+ encoder = ltdc_rgb_encoder_create(ddev);
+ if (!encoder) {
+ DRM_ERROR("Failed to create RGB encoder\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ connector = ltdc_rgb_connector_create(ddev);
+ if (!connector) {
+ DRM_ERROR("Failed to create RGB connector\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = drm_mode_connector_attach_encoder(connector, encoder);
+ if (ret) {
+ DRM_ERROR("Failed to attach connector to encoder\n");
+ goto err;
+ }
+
+ drm_panel_attach(ldev->panel, connector);
+ }
+
+ crtc = devm_kzalloc(dev, sizeof(*crtc), GFP_KERNEL);
+ if (!crtc) {
+ DRM_ERROR("Failed to allocate crtc\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = ltdc_crtc_init(ddev, crtc);
+ if (ret) {
+ DRM_ERROR("Failed to init crtc\n");
+ goto err;
+ }
+
+ ret = drm_vblank_init(ddev, NB_CRTC);
+ if (ret) {
+ DRM_ERROR("Failed calling drm_vblank_init()\n");
+ goto err;
+ }
+
+ /* Allow usage of vblank without having to call drm_irq_install */
+ ddev->irq_enabled = 1;
+
+ return 0;
+err:
+ if (ldev->panel)
+ drm_panel_detach(ldev->panel);
+
+ clk_disable_unprepare(ldev->pixel_clk);
+
+ return ret;
+}
+
+void ltdc_unload(struct drm_device *ddev)
+{
+ struct ltdc_device *ldev = ddev->dev_private;
+
+ DRM_DEBUG_DRIVER("\n");
+
+ drm_vblank_cleanup(ddev);
+
+ if (ldev->panel)
+ drm_panel_detach(ldev->panel);
+
+ clk_disable_unprepare(ldev->pixel_clk);
+}
+
+MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
+MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
+MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
+MODULE_AUTHOR("Mickael Reulier <mickael.reulier@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST DRM LTDC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/stm/ltdc.h b/drivers/gpu/drm/stm/ltdc.h
new file mode 100644
index 0000000..d7a9c73
--- /dev/null
+++ b/drivers/gpu/drm/stm/ltdc.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) STMicroelectronics SA 2017
+ *
+ * Authors: Philippe Cornu <philippe.cornu@st.com>
+ * Yannick Fertre <yannick.fertre@st.com>
+ * Fabien Dessenne <fabien.dessenne@st.com>
+ * Mickael Reulier <mickael.reulier@st.com>
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _LTDC_H_
+#define _LTDC_H_
+
+struct ltdc_caps {
+ u32 hw_version; /* hardware version */
+ u32 nb_layers; /* number of supported layers */
+ u32 reg_ofs; /* register offset for applicable regs */
+ u32 bus_width; /* bus width (32 or 64 bits) */
+ const u32 *pix_fmt_hw; /* supported pixel formats */
+};
+
+struct ltdc_device {
+ struct drm_fbdev_cma *fbdev;
+ void __iomem *regs;
+ struct clk *pixel_clk; /* lcd pixel clock */
+ struct drm_panel *panel;
+ struct mutex err_lock; /* protecting error_status */
+ struct ltdc_caps caps;
+ u32 clut[256]; /* color look up table */
+ u32 error_status;
+ u32 irq_status;
+};
+
+int ltdc_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe);
+void ltdc_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe);
+int ltdc_load(struct drm_device *ddev);
+void ltdc_unload(struct drm_device *ddev);
+
+#endif
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH v6 3/9] dt-bindings: display: Add STM32 LTDC driver
From: Yannick Fertre @ 2017-04-14 8:10 UTC (permalink / raw)
To: Alexandre TORGUE, Thierry Reding, David Airlie, Maxime Coquelin,
Russell King, Mark Rutland, Rob Herring, Arnd Bergmann,
Benjamin Gaignard, Yannick Fertre
Cc: devicetree, kernel, Philippe Cornu, Fabien Dessenne, dri-devel,
Mickael Reulier, Vincent Abriou, Gabriel FERNANDEZ,
linux-arm-kernel
In-Reply-To: <1492157455-2283-1-git-send-email-yannick.fertre@st.com>
This patch adds documentation of device tree bindings for the STM32 LTDC
(Lcd-Tft Display Controller).
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Yannick Fertre <yannick.fertre@st.com>
---
.../devicetree/bindings/display/st,stm32-ltdc.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
diff --git a/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt b/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
new file mode 100644
index 0000000..8e14769
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
@@ -0,0 +1,36 @@
+* STMicroelectronics STM32 lcd-tft display controller
+
+- ltdc: lcd-tft display controller host
+ must be a sub-node of st-display-subsystem
+ Required properties:
+ - compatible: "st,stm32-ltdc"
+ - reg: Physical base address of the IP registers and length of memory mapped region.
+ - clocks: A list of phandle + clock-specifier pairs, one for each
+ entry in 'clock-names'.
+ - clock-names: A list of clock names. For ltdc it should contain:
+ - "lcd" for the clock feeding the output pixel clock & IP clock.
+ - resets: reset to be used by the device (defined by use of RCC macro).
+ Required nodes:
+ - Video port for RGB output.
+
+Example:
+
+/ {
+ ...
+ soc {
+ ...
+ ltdc: display-controller@40016800 {
+ compatible = "st,stm32-ltdc";
+ reg = <0x40016800 0x200>;
+ interrupts = <88>, <89>;
+ resets = <&rcc STM32F4_APB2_RESET(LTDC)>;
+ clocks = <&rcc 1 CLK_LCD>;
+ clock-names = "lcd";
+
+ port {
+ ltdc_out_rgb: endpoint {
+ };
+ };
+ };
+ };
+};
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH v6 2/9] drm/fb-cma-helper: Add drm_fb_cma_get_gem_addr()
From: Yannick Fertre @ 2017-04-14 8:10 UTC (permalink / raw)
To: Alexandre TORGUE, Thierry Reding, David Airlie, Maxime Coquelin,
Russell King, Mark Rutland, Rob Herring, Arnd Bergmann,
Benjamin Gaignard, Yannick Fertre
Cc: devicetree, kernel, Philippe Cornu, Fabien Dessenne, dri-devel,
Mickael Reulier, Vincent Abriou, Gabriel FERNANDEZ,
linux-arm-kernel
In-Reply-To: <1492157455-2283-1-git-send-email-yannick.fertre@st.com>
Add function drm_fb_cma_get_gem_addr() which return the physical address
of framebuffer (1st pixel). This function will usually be called by plane
callback (atomic_update).
Signed-off-by: Yannick Fertre <yannick.fertre@st.com>
---
drivers/gpu/drm/drm_fb_cma_helper.c | 27 +++++++++++++++++++++++++++
include/drm/drm_fb_cma_helper.h | 4 ++++
2 files changed, 31 insertions(+)
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 50abd1f..d2b77b0 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -260,6 +260,33 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
/**
+ * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer
+ * @fb: The framebuffer
+ * @state: Which state of drm plane
+ * @plane: Which plane
+ * Return the CMA GEM address for given framebuffer.
+ *
+ * This function will usually be called from the PLANE callback functions.
+ */
+dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
+ struct drm_plane_state *state,
+ unsigned int plane)
+{
+ struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+ dma_addr_t paddr;
+
+ if (plane >= 4)
+ return 0;
+
+ paddr = fb_cma->obj[plane]->paddr + fb->offsets[plane];
+ paddr += fb->format->cpp[plane] * (state->src_x >> 16);
+ paddr += fb->pitches[plane] * (state->src_y >> 16);
+
+ return paddr;
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
+
+/**
* drm_fb_cma_prepare_fb() - Prepare CMA framebuffer
* @plane: Which plane
* @state: Plane state attach fence to
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index a5ecc0a..199a63f 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -41,6 +41,10 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
unsigned int plane);
+dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
+ struct drm_plane_state *state,
+ unsigned int plane);
+
int drm_fb_cma_prepare_fb(struct drm_plane *plane,
struct drm_plane_state *state);
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH v6 1/9] drm/cma: Update DEFINE_DRM_GEM_CMA_FOPS to add get_unmapped_area
From: Yannick Fertre @ 2017-04-14 8:10 UTC (permalink / raw)
To: Alexandre TORGUE, Thierry Reding, David Airlie, Maxime Coquelin,
Russell King, Mark Rutland, Rob Herring, Arnd Bergmann,
Benjamin Gaignard, Yannick Fertre
Cc: devicetree, kernel, Philippe Cornu, Fabien Dessenne, dri-devel,
Mickael Reulier, Vincent Abriou, Gabriel FERNANDEZ,
linux-arm-kernel
In-Reply-To: <1492157455-2283-1-git-send-email-yannick.fertre@st.com>
Missing field get_unmapped_area which is necessary with device without MMU
Signed-off-by: Yannick Fertre <yannick.fertre@st.com>
---
include/drm/drm_gem_cma_helper.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index f962d33..7320b14 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -50,6 +50,7 @@ struct drm_gem_cma_object {
.read = drm_read,\
.llseek = noop_llseek,\
.mmap = drm_gem_cma_mmap,\
+ .get_unmapped_area = drm_gem_cma_get_unmapped_area,\
}
/* free GEM object */
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH v6 0/9] STM32 LCD-TFT display controller
From: Yannick Fertre @ 2017-04-14 8:10 UTC (permalink / raw)
To: Alexandre TORGUE, Thierry Reding, David Airlie, Maxime Coquelin,
Russell King, Mark Rutland, Rob Herring, Arnd Bergmann,
Benjamin Gaignard, Yannick Fertre
Cc: devicetree, kernel, Philippe Cornu, Fabien Dessenne, dri-devel,
Mickael Reulier, Vincent Abriou, Gabriel FERNANDEZ,
linux-arm-kernel
Version 6:
- Add patch on MAINTAINERS file to add Philippe Cornu & myself.
- Update driver stm to remove uneccessary functions called.
Version 5:
- Add patch on drm_gem_cma_helper.h to udapte DEFINE_DRM_GEM_CMA_FOPS.
- Add patch on drm_fb_cma_helper to add new function to get physical address.
- Solve some typos & update ltdc driver including last remarks of Eric Anholt
- Update commits of config patches.
Version 4:
- Update "ampire,am-480272h3tmqw-t01h.txt" binding with more details on gpios.
- Update ltdc.c. Remove regmap, solve some typo & warnings.
Version 3:
- Update "st,stm32-ltdc.txt" binding.
- Add a commit to "ARM: configs: stm32: ADD LDTC support" patch.
Version 2:
- Rename driver directory from st to stm.
- Rename compatiblity from st,ltdc to st,stm32-ltdc.
- Remove compatibility st,display-subsystem.
- Rename driver from st-drm to stm-drm.
- Rework probe sequence & remove display-subsystem part.
- I keep clock name which is necessary for devm_regmap_init_mmio_clk call.
Version 1:
- Initial commit
The purpose of this set of patches is to add a new driver for stm32f429.
This driver was developed and tested on evaluation board stm32429i.
Stm32f4 is a MCU platform which don't have MMU so the last patches developed
by Benjamin Gaignard regarding "DRM: allow to use mmuless devices"
are necessary.
The board stm429i embeds a Ampire AM-480272H3TMQW-T01H screen.
A new simple panel am-480272h3tmqw-t01h have been added to support it.
Yannick Fertre (9):
drm/cma: Update DEFINE_DRM_GEM_CMA_FOPS to add get_unmapped_area
drm/fb-cma-helper: Add drm_fb_cma_get_gem_addr()
dt-bindings: display: Add STM32 LTDC driver
drm/stm: Add STM32 LTDC driver
[media] add maintainers for DRM STM driver
ARM: dts: stm32: Add ltdc support on stm32f429 MCU
ARM: dts: stm32: Enable ltdc & simple panel on stm32f429-Eval board
ARM: configs: stm32: Add DRM support in STM32 defconfig
ARM: configs: stm32: Add simple panel support in STM32 defconfig
.../devicetree/bindings/display/st,stm32-ltdc.txt | 36 +
MAINTAINERS | 9 +
arch/arm/boot/dts/stm32429i-eval.dts | 59 +
arch/arm/boot/dts/stm32f429.dtsi | 12 +-
arch/arm/configs/stm32_defconfig | 3 +
drivers/gpu/drm/Kconfig | 2 +
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/drm_fb_cma_helper.c | 27 +
drivers/gpu/drm/stm/Kconfig | 16 +
drivers/gpu/drm/stm/Makefile | 7 +
drivers/gpu/drm/stm/drv.c | 221 ++++
drivers/gpu/drm/stm/ltdc.c | 1161 ++++++++++++++++++++
drivers/gpu/drm/stm/ltdc.h | 40 +
include/drm/drm_fb_cma_helper.h | 4 +
include/drm/drm_gem_cma_helper.h | 1 +
15 files changed, 1598 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/display/st,stm32-ltdc.txt
create mode 100644 drivers/gpu/drm/stm/Kconfig
create mode 100644 drivers/gpu/drm/stm/Makefile
create mode 100644 drivers/gpu/drm/stm/drv.c
create mode 100644 drivers/gpu/drm/stm/ltdc.c
create mode 100644 drivers/gpu/drm/stm/ltdc.h
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v3 14/37] mtd: nand: denali: support "nand-ecc-strength" DT property
From: Masahiro Yamada @ 2017-04-14 7:57 UTC (permalink / raw)
To: Boris Brezillon
Cc: linux-mtd, Enrico Jorns, Artem Bityutskiy, Dinh Nguyen,
Marek Vasut, Graham Moore, David Woodhouse, Masami Hiramatsu,
Chuanxiao Dong, Jassi Brar, devicetree, Linux Kernel Mailing List,
Brian Norris, Richard Weinberger, Cyrille Pitchen, Rob Herring,
Mark Rutland
In-Reply-To: <20170411095637.5aa87cf6@bbrezillon>
Hi Boris,
2017-04-11 16:56 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
> Hi Masahiro,
>
> On Tue, 11 Apr 2017 15:19:21 +0900
> Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>
>> Hi Boris,
>>
>>
>>
>> 2017-04-10 1:33 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
>> > On Mon, 3 Apr 2017 12:16:34 +0900
>> > Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>> >
>> >> Hi Boris,
>> >>
>> >>
>> >>
>> >> 2017-03-31 18:46 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
>> >>
>> >> > You can try something like that when no explicit ecc.strength and
>> >> > ecc.size has been set in the DT and when ECC_MAXIMIZE was not passed.
>> >> >
>> >> > static int
>> >> > denali_get_closest_ecc_strength(struct denali_nand_info *denali,
>> >> > int strength)
>> >> > {
>> >> > /*
>> >> > * Whatever you need to select a strength that is greater than
>> >> > * or equal to strength.
>> >> > */
>> >> >
>> >> > return X;
>> >> > }
>> >>
>> >>
>> >> Is here anything specific to Denali?
>> >
>> > Well, only the denali driver knows what the hardware supports, though
>> > having a generic function that takes a table of supported strengths
>> > would work.
>> >
>> >>
>> >>
>> >> > static int denali_try_to_match_ecc_req(struct denali_nand_info *denali)
>> >> > {
>> >> > struct nand_chip *chip = &denali->nand;
>> >> > struct mtd_info *mtd = nand_to_mtd(chip);
>> >> > int max_ecc_bytes = mtd->oobsize - denali->bbtskipbytes;
>> >> > int ecc_steps, ecc_strength, ecc_bytes;
>> >> > int ecc_size = chip->ecc_step_ds;
>> >> > int ecc_strength = chip->ecc_strength_ds;
>> >> >
>> >> > /*
>> >> > * No information provided by the NAND chip, let the core
>> >> > * maximize the strength.
>> >> > */
>> >> > if (!ecc_size || !ecc_strength)
>> >> > return -ENOTSUPP;
>> >> >
>> >> > if (ecc_size > 512)
>> >> > ecc_size = 1024;
>> >> > else
>> >> > ecc_size = 512;
>> >> >
>> >> > /* Adjust ECC step size based on hardware support. */
>> >> > if (ecc_size == 1024 &&
>> >> > !(denali->caps & DENALI_CAP_ECC_SIZE_1024))
>> >> > ecc_size = 512;
>> >> > else if(ecc_size == 512 &&
>> >> > !(denali->caps & DENALI_CAP_ECC_SIZE_512))
>> >> > ecc_size = 1024;
>> >> >
>> >> > if (ecc_size < chip->ecc_size_ds) {
>> >> > /*
>> >> > * When the selected size if smaller than the expected
>> >> > * one we try to use the same strength but on 512 blocks
>> >> > * so that we can still fix the same number of errors
>> >> > * even if they are concentrated in the first 512bytes
>> >> > * of a 1024bytes portion.
>> >> > */
>> >> > ecc_strength = chip->ecc_strength_ds;
>> >> > ecc_strength = denali_get_closest_ecc_strength(denali,
>> >> > ecc_strength);
>> >> > } else {
>> >> > /* Always prefer 1024bytes ECC blocks when possible. */
>> >> > if (ecc_size != 1024 &&
>> >> > (denali->caps & DENALI_CAP_ECC_SIZE_1024) &&
>> >> > mtd->writesize > 1024)
>> >> > ecc_size = 1024;
>> >> >
>> >> > /*
>> >> > * Adjust the strength based on the selected ECC step
>> >> > * size.
>> >> > */
>> >> > ecc_strength = DIV_ROUND_UP(ecc_size,
>> >> > chip->ecc_step_ds) *
>> >> > chip->ecc_strength_ds;
>> >> > }
>> >> >
>> >> > ecc_bytes = denali_calc_ecc_bytes(ecc_size,
>> >> > ecc_strength);
>> >> > ecc_bytes *= mtd->writesize / ecc_size;
>> >> >
>> >> > /*
>> >> > * If we don't have enough space, let the core maximize
>> >> > * the strength.
>> >> > */
>> >> > if (ecc_bytes > max_ecc_bytes)
>> >> > return -ENOTSUPP;
>> >> >
>> >> > chip->ecc.strength = ecc_strength;
>> >> > chip->ecc.size = ecc_size;
>> >> >
>> >> > return 0;
>> >> > }
>> >>
>> >>
>> >> As a whole, this does not seem to driver-specific.
>> >
>> > It's almost controller-agnostic, except for the denali_calc_ecc_bytes()
>> > function, but I guess we could ask drivers to implement a hook that is
>> > passed the ECC step size and strength and returns the associated
>> > number of ECC bytes.
>> >
>> >>
>> >>
>> >> [1] A driver provides some pairs of (ecc_strength, ecc_size)
>> >> it can support.
>> >>
>> >> [2] The core framework knows the chip's requirement
>> >> (ecc_strength_ds, ecc_size_ds).
>> >>
>> >>
>> >> Then, the core framework provides a function
>> >> to return a most recommended (ecc_strength, ecc_size).
>> >>
>> >>
>> >>
>> >> struct nand_ecc_spec {
>> >> int ecc_strength;
>> >> int ecc_size;
>> >> };
>> >>
>> >> /*
>> >> * This function choose the most recommented (ecc_str, ecc_size)
>> >> * "recommended" means: minimum ecc stregth that meets
>> >> * the chip's requirment.
>> >> *
>> >> *
>> >> * @chip - nand_chip
>> >> * @controller_ecc_spec - Array of (ecc_str, ecc_size) supported by the
>> >> controller. (terminated by NULL as sentinel)
>> >> */
>> >> struct nand_ecc_spec * nand_try_to_match_ecc_req(struct nand_chip *chip,
>> >> struct nand_ecc_spec
>> >> *controller_ecc_spec)
>> >> {
>> >> /*
>> >> * Return the pointer to the most recommended
>> >> * struct nand_ecc_spec.
>> >> * If nothing suitable found, return NULL.
>> >> */
>> >> }
>> >>
>> >
>> > I like the idea, except I would do this slightly differently to avoid
>> > declaring all combinations of stepsize and strengths
>> >
>> > struct nand_ecc_stepsize_info {
>> > int stepsize;
>> > int nstrengths;
>> > int *strengths;
>> > };
>> >
>> > struct nand_ecc_engine_caps {
>> > int nstepsizes;
>> > struct nand_ecc_stepsize_info *stepsizes;
>> > int (*calc_ecc_bytes)(int stepsize, int strength);
>> > };
>> >
>> > int nand_try_to_match_ecc_req(struct nand_chip *chip,
>> > const struct nand_ecc_engine_caps *caps,
>> > struct nand_ecc_spec *spec)
>> > {
>> > /*
>> > * Find the most appropriate setting based on the ECC engine
>> > * caps and fill the spec object accordingly.
>> > * Returns 0 in case of success and a negative error code
>> > * otherwise.
>> > */
>> > }
>> >
>> > Note that nand_try_to_match_ecc_req() has to be more generic than
>> > denali_try_to_match_ecc_req() WRT step sizes, which will probably
>> > complexify the logic.
>>
>>
>> After I fiddle with this generic approach for a while,
>> I started to feel like giving up.
>
> I don't get it. What was the problem with my initial suggestion (the
> denali specific one, not the generic approach)? You proposed to make it
> generic, which, I agree, is a bit more complicated.
>
>>
>> I wonder if we really want over-implementation
>> for covering _theoretically_ possible cases.
>
> Okay, one more theoretical case I'd like to expose: you have board
> design with different NAND parts which have different ECC requirements.
> If you were about to describe the exact ECC strength you want for each
> board you'll have to have different DTs.
In this case, fixed ecc-strength in DT is not feasible.
> Maximizing the ECC strength
> would still work, but what if the MTD user needs some OOB bytes (like
> is the case with JFFS2) and ECC maximization reserved all of the
> available bytes?
JFFS2 needs some bytes in oob-free area for the clean marker.
You are right.
This implies NAND_ECC_MAXIMIZE is not very useful.
We do not know whether we have enough space left in oob, or not.
> The other reason I prefer to have the drivers automatically guessing
> what's appropriate is because then you don't have to care when writing
> your DT.
>
>>
>> In practice, there are not so many ECC settings possible
>> on a single controller.
>>
>> As for Denali IP, it would be theoretically possible to instantiate
>> multiple ECC engines. However, in practice, there is no sensible
>> reason to do so. At least, I do not know any real chip to support that.
>>
>> So, I'd like to simplify the logic for Denali.
>>
>> - Support either 512 or 1024 ECC size.
>> If there is (ever) a controller that supports both,
>> 1024 should be chosen.
>>
>> - ECC strength is not specified via DT, it is simply maximized.
>>
>> This simplifies the logic much and I believe this is enough.
>>
>> One more reason is, as we talked before,
>> we need to match ECC setting between Linux and firmware (boot-loader),
>
> If the bootloader implements the same logic it should match.
>
>> so anyway we end up with using a fixed setting specified by DT.
>>
>
> Really, I don't see what's the problem with the function I proposed,
> but I'm willing to make a concession.
> Make the nand-ecc-strength+nand-ecc-step-size or nand-ecc-maximize
> mandatory so that if someone ever needs to support the 'match NAND
> requirements' feature we won't have to add a vendor specific property
> like this one [1].
>
> Are you fine with that?
No. This requirement seems too strong.
At least, it is a problem for non-DT platforms.
If a driver provides ECC engine caps info,
perhaps ECC maximizing could be a generalized helper function as well.
I am trying this still.
--
Best Regards
Masahiro Yamada
^ permalink raw reply
* Re: [PATCH 4/4] net: macb: Add macb_ptp to compilation chain
From: Richard Cochran @ 2017-04-14 7:53 UTC (permalink / raw)
To: Rafal Ozieblo
Cc: David Miller, nicolas.ferre, netdev, linux-kernel, devicetree,
linux-arm-kernel, harinikatakamlinux, harini.katakam,
Andrei.Pistirica
In-Reply-To: <1492090798-16253-1-git-send-email-rafalo@cadence.com>
On Thu, Apr 13, 2017 at 02:39:58PM +0100, Rafal Ozieblo wrote:
> Add macb_ptp.c to Makefile.
> In case that macb is compiled as a module, it has been renamed to
> cadence-macb.ko to avoid naming confusion in Makefile.
Renaming modules will break user's modpobe scripts.
Why not keep macb.ko as the build product and rename macb.c to
macb_main.c instead?
Thanks,
Richard
^ permalink raw reply
* Re: [PATCH 1/4] net: macb: Add support for PTP timestamps in DMA descriptors
From: Richard Cochran @ 2017-04-14 7:43 UTC (permalink / raw)
To: Rafal Ozieblo
Cc: David Miller, nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
harinikatakamlinux-Re5JQEeQqe8AvxtiuMwx3w,
harini.katakam-gjFFaj9aHVfQT0dZR+AlfA,
Andrei.Pistirica-UWL1GkI3JZL3oGB3hsPCZA
In-Reply-To: <1492090439-11793-1-git-send-email-rafalo-vna1KIf7WgpBDgjK7y7TUQ@public.gmane.org>
On Thu, Apr 13, 2017 at 02:33:59PM +0100, Rafal Ozieblo wrote:
> @@ -1921,9 +1972,13 @@ static void macb_configure_dma(struct macb *bp)
> dmacfg &= ~GEM_BIT(TXCOEN);
>
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (bp->hw_dma_cap == HW_DMA_CAP_64B)
> + if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> dmacfg |= GEM_BIT(ADDR64);
> #endif
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> + if (bp->hw_dma_cap & HW_DMA_CAP_PTP)
> + dmacfg |= GEM_BIT(RXEXT) | GEM_BIT(TXEXT);
> +#endif
> netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
> dmacfg);
> gem_writel(bp, DMACFG, dmacfg);
> @@ -1971,14 +2026,15 @@ static void macb_init_hw(struct macb *bp)
> /* Initialize TX and RX buffers */
> macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (bp->hw_dma_cap == HW_DMA_CAP_64B)
> + if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
> #endif
> for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
> queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (bp->hw_dma_cap == HW_DMA_CAP_64B)
> - queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
> + if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> + queue_writel(queue, TBQPH,
> + upper_32_bits(queue->tx_ring_dma));
Align arg3 with arg1 please.
> #endif
>
> /* Enable interrupts */
> @@ -2579,6 +2635,18 @@ static void macb_configure_caps(struct macb *bp,
> dcfg = gem_readl(bp, DCFG2);
> if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
> bp->caps |= MACB_CAPS_FIFO_MODE;
> + /* if HWSTAMP is configure and gem has the capability */
This comment is redundant. We can see that clearly in the code already.
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> + bp->ptp_hw_support = false;
No need to clear this again. (The struct was cleared after
allocation, right?)
> + if (gem_has_ptp(bp)) {
Why not drop the #idef:
if (IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) && gem_has_ptp(bp)) ...
> + if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))
> + pr_err("GEM doesn't support hardware ptp.\n");
> + else {
> + pr_emerg("rozieblo: ptp_hw_support = true");
pr_emerg?
> + bp->ptp_hw_support = true;
> + }
Proper if/else CodingStyle please.
> + }
> +#endif
> }
>
> dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps);
> @@ -2716,7 +2784,7 @@ static int macb_init(struct platform_device *pdev)
> queue->IMR = GEM_IMR(hw_q - 1);
> queue->TBQP = GEM_TBQP(hw_q - 1);
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (bp->hw_dma_cap == HW_DMA_CAP_64B)
> + if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> queue->TBQPH = GEM_TBQPH(hw_q - 1);
> #endif
> } else {
> @@ -2727,7 +2795,7 @@ static int macb_init(struct platform_device *pdev)
> queue->IMR = MACB_IMR;
> queue->TBQP = MACB_TBQP;
> #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (bp->hw_dma_cap == HW_DMA_CAP_64B)
> + if (bp->hw_dma_cap & HW_DMA_CAP_64B)
> queue->TBQPH = MACB_TBQPH;
> #endif
> }
> @@ -3307,19 +3375,24 @@ static int macb_probe(struct platform_device *pdev)
> bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
> device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
>
> -#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
> - dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
> - bp->hw_dma_cap = HW_DMA_CAP_64B;
> - } else
> - bp->hw_dma_cap = HW_DMA_CAP_32B;
> -#endif
> -
> spin_lock_init(&bp->lock);
>
> /* setup capabilities */
> macb_configure_caps(bp, macb_config);
>
> +#ifdef MACB_EXT_DESC
> + bp->hw_dma_cap = HW_DMA_CAP_32B;
> +#endif
> +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> + if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
> + dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
> + bp->hw_dma_cap |= HW_DMA_CAP_64B;
> + }
> +#endif
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> + if (bp->ptp_hw_support)
> + bp->hw_dma_cap |= HW_DMA_CAP_PTP;
So bp->ptp_hw_support is a waste of storage. You can test for
(!GEM_BFEXT(TSU, gem_readl(bp, DCFG5))) directly here, or return a
flag from macb_configure_caps(), or set the hw_dma_cap flag in that
function, ...
> +#endif
> platform_set_drvdata(pdev, dev);
>
> dev->irq = platform_get_irq(pdev, 0);
> @@ -954,8 +972,12 @@ struct macb {
> u32 wol;
>
> struct macb_ptp_info *ptp_info; /* macb-ptp interface */
> -#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
> - enum macb_hw_dma_cap hw_dma_cap;
> +#ifdef MACB_EXT_DESC
> + uint8_t hw_dma_cap;
> +#endif
> +
> +#ifdef CONFIG_MACB_USE_HWSTAMP
> + bool ptp_hw_support;
Remove this, please.
Thanks,
Richard
> #endif
> };
>
> --
> 2.4.5
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 3/4] net: macb: Add hardware PTP support
From: kbuild test robot @ 2017-04-14 7:42 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, David Miller,
nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
harinikatakamlinux-Re5JQEeQqe8AvxtiuMwx3w,
harini.katakam-gjFFaj9aHVfQT0dZR+AlfA,
richardcochran-Re5JQEeQqe8AvxtiuMwx3w,
Andrei.Pistirica-UWL1GkI3JZL3oGB3hsPCZA, Rafal Ozieblo
In-Reply-To: <1492090763-15686-1-git-send-email-rafalo-vna1KIf7WgpBDgjK7y7TUQ@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 3090 bytes --]
Hi Rafal,
[auto build test ERROR on net-next/master]
[also build test ERROR on v4.11-rc6 next-20170413]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Rafal-Ozieblo/net-macb-Add-support-for-PTP-timestamps-in-DMA-descriptors/20170414-001330
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64
Note: the linux-review/Rafal-Ozieblo/net-macb-Add-support-for-PTP-timestamps-in-DMA-descriptors/20170414-001330 HEAD 3b878618e04f866388fd62f6c44752e50b15658a builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
drivers/built-in.o: In function `gem_ptp_do_rxstamp':
>> drivers/net/ethernet/cadence/macb.h:1108: undefined reference to `gem_ptp_rxstamp'
drivers/net/ethernet/cadence/macb.h:1108:(.text+0x264604): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `gem_ptp_rxstamp'
drivers/built-in.o: In function `gem_ptp_do_txstamp':
>> drivers/net/ethernet/cadence/macb.h:1100: undefined reference to `gem_ptp_txstamp'
drivers/net/ethernet/cadence/macb.h:1100:(.text+0x266564): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `gem_ptp_txstamp'
drivers/built-in.o: In function `macb_interrupt':
>> drivers/net/ethernet/cadence/macb.c:1332: undefined reference to `macb_ptp_int'
drivers/net/ethernet/cadence/macb.c:1332:(.text+0x2666ac): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `macb_ptp_int'
drivers/built-in.o:(.data+0x93fc8): undefined reference to `gem_ptp_init'
drivers/built-in.o:(.data+0x93fd0): undefined reference to `gem_ptp_remove'
drivers/built-in.o:(.data+0x93ff0): undefined reference to `gem_get_hwtst'
drivers/built-in.o:(.data+0x93ff8): undefined reference to `gem_set_hwtst'
vim +1108 drivers/net/ethernet/cadence/macb.h
1094 void macb_ptp_int(struct macb_queue *queue, u32 status);
1095 static inline int gem_ptp_do_txstamp(struct macb_queue *queue, struct sk_buff *skb, struct macb_dma_desc *desc)
1096 {
1097 if (queue->bp->tstamp_config.tx_type == TSTAMP_DISABLED)
1098 return -ENOTSUPP;
1099
> 1100 return gem_ptp_txstamp(queue, skb, desc);
1101 }
1102
1103 static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc)
1104 {
1105 if (bp->tstamp_config.rx_filter == TSTAMP_DISABLED)
1106 return;
1107
> 1108 gem_ptp_rxstamp(bp, skb, desc);
1109 }
1110 int gem_get_hwtst(struct net_device *dev, struct ifreq *rq);
1111 int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd);
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34537 bytes --]
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: Add support for samsung s6e3ha2 edge panel binding
From: Andrzej Hajda @ 2017-04-14 7:33 UTC (permalink / raw)
To: Hoegeun Kwon, thierry.reding, airlied, robh+dt, mark.rutland,
catalin.marinas, will.deacon, kgene, krzk
Cc: devicetree, linux-samsung-soc, linux-kernel, dri-devel, javier,
andi.shyti, linux-arm-kernel
In-Reply-To: <1492147179-7824-2-git-send-email-hoegeun.kwon@samsung.com>
Hi Hoegeun,
On 14.04.2017 07:19, Hoegeun Kwon wrote:
> The Samsung s6e3ha2 edge is a 5.65" 1600x2560 AMOLED panel connected
> using MIPI-DSI interfaces.
As I wrote in discussion about s6e3ha2, there is no edge version of
s6e3ha2, it is just different panel: s6e3hf2, or more precisely IC driver.
[1]: https://lkml.org/lkml/2017/1/9/159
>
> Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
> ---
> .../bindings/display/panel/samsung,s6e3ha2-e.txt | 28 ++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
>
> diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
> new file mode 100644
> index 0000000..09c65f6
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
> @@ -0,0 +1,28 @@
> +Samsung S6E3HA2 5.65" 1600x2560 AMOLED panel
> +
> +Required properties:
> + - compatible: "samsung,s6e3ha2-e"
I think "samsung,s6e3hf2" should be then used, I guess it could be even
simpler to just add new compatible string to samsung,s6e3ha2.txt binding
with some comments, as these panels are of the same family.
Regards
Andrzej
> + - reg: the virtual channel number of a DSI peripheral
> + - vdd3-supply: I/O voltage supply
> + - vci-supply: voltage supply for analog circuits
> + - reset-gpios: a GPIO spec for the reset pin (active low)
> + - enable-gpios: a GPIO spec for the panel enable pin (active high)
> +
> +Optional properties:
> + - te-gpios: a GPIO spec for the tearing effect synchronization signal
> + gpio pin (active high)
> +
> +Example:
> +&dsi {
> + ...
> +
> + panel@0 {
> + compatible = "samsung,s6e3ha2-e";
> + reg = <0>;
> + vdd3-supply = <&ldo27_reg>;
> + vci-supply = <&ldo28_reg>;
> + reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
> + enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
> + te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
> + };
> +};
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* [PATCH v2] dt-bindings: input: add bindings document for ar1021_i2c driver
From: Martin Kepplinger @ 2017-04-14 6:11 UTC (permalink / raw)
To: robh-DgEjT+Ai2ygdnm+yROfE0A,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w
Cc: christian.gmeiner-Re5JQEeQqe8AvxtiuMwx3w,
linux-0h96xk9xTtrk1uMJSBkQmQ, linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Martin Kepplinger
In-Reply-To: <20170413204041.lqtqfc24vueo5fbj@rob-hp-laptop>
Add a simple binding document describing the supported devices and the
I2C bus address.
Signed-off-by: Martin Kepplinger <martin.kepplinger-hfTNJOUbDMh54TAoqtyWWQ@public.gmane.org>
---
revision history
----------------
v2: fixed subject line and binding; thanks Rob Herring
v1: initial idea
.../devicetree/bindings/input/touchscreen/ar1021.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/ar1021.txt
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ar1021.txt b/Documentation/devicetree/bindings/input/touchscreen/ar1021.txt
new file mode 100644
index 0000000..e459e85
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ar1021.txt
@@ -0,0 +1,16 @@
+* Microchip AR1020 and AR1021 touchscreen interface (I2C)
+
+Required properties:
+- compatible : "microchip,ar1021-i2c"
+- reg : I2C slave address
+- interrupt-parent : the phandle for the interrupt controller
+- interrupts : touch controller interrupt
+
+Example:
+
+ touchscreen@4d {
+ compatible = "microchip,ar1021-i2c";
+ reg = <0x4d>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <11 IRQ_TYPE_LEVEL_HIGH>;
+ };
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH 3/4] net: macb: Add hardware PTP support
From: kbuild test robot @ 2017-04-14 6:03 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, David Miller,
nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
harinikatakamlinux-Re5JQEeQqe8AvxtiuMwx3w,
harini.katakam-gjFFaj9aHVfQT0dZR+AlfA,
richardcochran-Re5JQEeQqe8AvxtiuMwx3w,
Andrei.Pistirica-UWL1GkI3JZL3oGB3hsPCZA, Rafal Ozieblo
In-Reply-To: <1492090763-15686-1-git-send-email-rafalo-vna1KIf7WgpBDgjK7y7TUQ@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1725 bytes --]
Hi Rafal,
[auto build test ERROR on net-next/master]
[also build test ERROR on v4.11-rc6 next-20170413]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Rafal-Ozieblo/net-macb-Add-support-for-PTP-timestamps-in-DMA-descriptors/20170414-001330
config: arm-at91_dt_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
Note: the linux-review/Rafal-Ozieblo/net-macb-Add-support-for-PTP-timestamps-in-DMA-descriptors/20170414-001330 HEAD 3b878618e04f866388fd62f6c44752e50b15658a builds fine.
It only hurts bisectibility.
All errors (new ones prefixed by >>):
drivers/built-in.o: In function `macb_interrupt':
>> kfifo_buf.c:(.text+0xeabd8): undefined reference to `macb_ptp_int'
>> kfifo_buf.c:(.text+0xeac6c): undefined reference to `gem_ptp_txstamp'
drivers/built-in.o: In function `gem_rx':
>> kfifo_buf.c:(.text+0xebbd8): undefined reference to `gem_ptp_rxstamp'
>> drivers/built-in.o:(.data+0xa5e0): undefined reference to `gem_ptp_init'
>> drivers/built-in.o:(.data+0xa5e4): undefined reference to `gem_ptp_remove'
>> drivers/built-in.o:(.data+0xa5f4): undefined reference to `gem_get_hwtst'
>> drivers/built-in.o:(.data+0xa5f8): undefined reference to `gem_set_hwtst'
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 22468 bytes --]
^ permalink raw reply
* [PATCH v2] input: touchscreen: ar1021_i2c: highlight support for AR1020
From: Martin Kepplinger @ 2017-04-14 6:02 UTC (permalink / raw)
To: robh, dmitry.torokhov
Cc: christian.gmeiner, linux, linux-input, linux-kernel, devicetree,
Martin Kepplinger
In-Reply-To: <20170413203532.thktt4yhqsg34cvc@rob-hp-laptop>
ar1021_i2c simply also supports the ar1020 device I'm using. This is
tested. They also share the same datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/40001393C.pdf
So let users see that they have a compatible in front of them by adding
AR1020 to the driver's description.
Signed-off-by: Martin Kepplinger <martin.kepplinger@ginzinger.com>
---
revision history
----------------
v2: leave compatible string untouched. only add description.
v1: initial idea.
drivers/input/touchscreen/Kconfig | 4 ++--
drivers/input/touchscreen/ar1021_i2c.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 33c62e5..535b91a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -96,8 +96,8 @@ config TOUCHSCREEN_AR1021_I2C
tristate "Microchip AR1021 i2c touchscreen"
depends on I2C && OF
help
- Say Y here if you have the Microchip AR1021 touchscreen controller
- chip in your system.
+ Say Y here if you have the Microchip AR1020 or AR1021 touchscreen
+ controller chip in your system.
If unsure, say N.
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c
index 2e7500e..03784d2 100644
--- a/drivers/input/touchscreen/ar1021_i2c.c
+++ b/drivers/input/touchscreen/ar1021_i2c.c
@@ -1,5 +1,5 @@
/*
- * Microchip AR1021 driver for I2C
+ * Microchip AR1020 and AR1021 driver for I2C
*
* Author: Christian Gmeiner <christian.gmeiner@gmail.com>
*
@@ -175,5 +175,5 @@ static struct i2c_driver ar1021_i2c_driver = {
module_i2c_driver(ar1021_i2c_driver);
MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>");
-MODULE_DESCRIPTION("Microchip AR1021 I2C Driver");
+MODULE_DESCRIPTION("Microchip AR1020 and AR1021 I2C Driver");
MODULE_LICENSE("GPL");
--
2.1.4
^ permalink raw reply related
* Re: [PATCH RFC 0/5] *** SPI Slave mode support ***
From: Jiada Wang @ 2017-04-14 5:39 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Mark Brown, Rob Herring, Mark Rutland, Shawn Guo, Sascha Hauer,
Fabio Estevam, linux-spi,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <CAMuHMdUm=90ddNWM5KWqT+W0hqZ-QO6vPHj5OisbYquDYq1ZmA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hello Geert
On 04/13/2017 12:47 PM, Geert Uytterhoeven wrote:
> On Thu, Apr 13, 2017 at 2:59 PM, Mark Brown<broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>> On Thu, Apr 13, 2017 at 05:13:59AM -0700, jiada_wang-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org wrote:
>>> From: Jiada Wang<jiada_wang-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
>>>
>>> v1:
>>> add Slave mode support in SPI core
>>> spidev create slave device when SPI controller work in slave mode
>>> spi-imx support to work in slave mode
>> Adding Geert who also had a series doing this in progress that was
>> getting very near to being merged.
> Thank you!
>
> Actually my plan is to fix the last remaining issues and resubmit for v4.13.
I noticed your patch set for SPI slave support,
(I am sure you can find out some of the change
in this patch set is based on your work).
we have similar requirement to add slave mode support to ecspi IP on
imx6 Soc.
Our use case is to use spidev as an interface to communicate with
external SPI master devices.
meanwhile the SPI bus controller can also act as master device to send
data to other
SPI slave devices on the board.
I found in your implementation, SPI bus controller is limited to either
work in master mode or
slave mode, is there any reasoning to not configure SPI mode based on
SPI devices use case?
Thanks,
Jiada
> References:
> - v2: https://lkml.org/lkml/2016/9/12/1065
> - v1: https://lkml.org/lkml/2016/6/22/423
>
> BTW Jiada, what's your use case? Just spidev?
>
> Thx!
>
> Gr{oetje,eeting}s,
>
> Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert-Td1EMuHUCqxL1ZNQvxDV9g@public.gmane.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
> -- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 3/3] arm64: dts: exynos: Add support for S6E3HA2 edge panel device on TM2e board
From: Hoegeun Kwon @ 2017-04-14 5:19 UTC (permalink / raw)
To: thierry.reding, airlied, robh+dt, mark.rutland, catalin.marinas,
will.deacon, kgene, krzk
Cc: devicetree, linux-samsung-soc, linux-kernel, dri-devel, javier,
andi.shyti, Hoegeun Kwon, linux-arm-kernel
In-Reply-To: <1492147179-7824-1-git-send-email-hoegeun.kwon@samsung.com>
This patch add the panel device tree node for S6E3HA2 edge display
controller to TM2e dts.
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
---
arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
index 694717a..79f22f7 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
@@ -52,6 +52,18 @@
assigned-clock-rates = <278000000>, <400000000>;
};
+&dsi {
+ panel@0 {
+ compatible = "samsung,s6e3ha2-e";
+ reg = <0>;
+ vdd3-supply = <&ldo27_reg>;
+ vci-supply = <&ldo28_reg>;
+ reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
+ enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+ te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
+ };
+};
+
&ldo31_reg {
regulator-name = "TSP_VDD_1.8V_AP";
regulator-min-microvolt = <1800000>;
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 2/3] drm/panel: s6e3ha2: Add support for S6eHEA2 edge panel on TM2e board
From: Hoegeun Kwon @ 2017-04-14 5:19 UTC (permalink / raw)
To: thierry.reding, airlied, robh+dt, mark.rutland, catalin.marinas,
will.deacon, kgene, krzk
Cc: dri-devel, devicetree, linux-arm-kernel, linux-samsung-soc,
linux-kernel, javier, a.hajda, andi.shyti, Hoegeun Kwon
In-Reply-To: <1492147179-7824-1-git-send-email-hoegeun.kwon@samsung.com>
This patch considers edge type of panel on TM2e board and The panel
has 1600x2560 resolution in 5.65" physical panel in the TM2e device.
This identify panel type with compatibility string, also invoke
display mode that matches the type. So add the check code for default
compatibility and edge type and select the drm_display_mode of default
and edge type.
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
---
drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 62 ++++++++++++++++++++++++---
1 file changed, 56 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
index 4cc08d7..b4a064a 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
@@ -16,6 +16,7 @@
#include <drm/drm_panel.h>
#include <linux/backlight.h>
#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#define S6E3HA2_MIN_BRIGHTNESS 0
@@ -218,6 +219,16 @@
0x1d, 0x1e, 0x1f, 0x20, 0x21
};
+enum s6e3ha2_type {
+ DEFAULT_TYPE,
+ EDGE_TYPE,
+};
+
+struct s6e3ha2_panel_desc {
+ const struct drm_display_mode *mode;
+ enum s6e3ha2_type type;
+};
+
struct s6e3ha2 {
struct device *dev;
struct drm_panel panel;
@@ -226,6 +237,8 @@ struct s6e3ha2 {
struct regulator_bulk_data supplies[2];
struct gpio_desc *reset_gpio;
struct gpio_desc *enable_gpio;
+
+ const struct s6e3ha2_panel_desc *desc;
};
static int s6e3ha2_dcs_write(struct s6e3ha2 *ctx, const void *data, size_t len)
@@ -283,11 +296,19 @@ static int s6e3ha2_single_dsi_set(struct s6e3ha2 *ctx)
static int s6e3ha2_freq_calibration(struct s6e3ha2 *ctx)
{
s6e3ha2_dcs_write_seq_static(ctx, 0xfd, 0x1c);
+ if (ctx->desc->type == EDGE_TYPE)
+ s6e3ha2_dcs_write_seq_static(ctx, 0xf2, 0x67, 0x40, 0xc5);
s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20, 0x39);
s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0xa0);
s6e3ha2_dcs_write_seq_static(ctx, 0xfe, 0x20);
- s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62, 0x40,
- 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5);
+
+ if (ctx->desc->type == DEFAULT_TYPE)
+ s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x12, 0x62,
+ 0x40, 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5);
+ else
+ s6e3ha2_dcs_write_seq_static(ctx, 0xce, 0x03, 0x3b, 0x14, 0x6d,
+ 0x40, 0x80, 0xc0, 0x28, 0x28, 0x28, 0x28, 0x39, 0xc5);
+
return 0;
}
@@ -597,16 +618,41 @@ static int s6e3ha2_enable(struct drm_panel *panel)
.flags = 0,
};
+static const struct s6e3ha2_panel_desc samsung_s6e3ha2_tm2 = {
+ .mode = &default_mode,
+ .type = DEFAULT_TYPE,
+};
+
+static const struct drm_display_mode edge_mode = {
+ .clock = 247856,
+ .hdisplay = 1600,
+ .hsync_start = 1600 + 1,
+ .hsync_end = 1600 + 1 + 1,
+ .htotal = 1600 + 1 + 1 + 1,
+ .vdisplay = 2560,
+ .vsync_start = 2560 + 1,
+ .vsync_end = 2560 + 1 + 1,
+ .vtotal = 2560 + 1 + 1 + 15,
+ .vrefresh = 60,
+ .flags = 0,
+};
+
+static const struct s6e3ha2_panel_desc samsung_s6e3ha2_tm2e = {
+ .mode = &edge_mode,
+ .type = EDGE_TYPE,
+};
+
static int s6e3ha2_get_modes(struct drm_panel *panel)
{
struct drm_connector *connector = panel->connector;
+ struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel);
struct drm_display_mode *mode;
- mode = drm_mode_duplicate(panel->drm, &default_mode);
+ mode = drm_mode_duplicate(panel->drm, ctx->desc->mode);
if (!mode) {
DRM_ERROR("failed to add mode %ux%ux@%u\n",
- default_mode.hdisplay, default_mode.vdisplay,
- default_mode.vrefresh);
+ ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay,
+ ctx->desc->mode->vrefresh);
return -ENOMEM;
}
@@ -642,6 +688,7 @@ static int s6e3ha2_probe(struct mipi_dsi_device *dsi)
mipi_dsi_set_drvdata(dsi, ctx);
ctx->dev = dev;
+ ctx->desc = of_device_get_match_data(dev);
dsi->lanes = 4;
dsi->format = MIPI_DSI_FMT_RGB888;
@@ -717,7 +764,10 @@ static int s6e3ha2_remove(struct mipi_dsi_device *dsi)
}
static const struct of_device_id s6e3ha2_of_match[] = {
- { .compatible = "samsung,s6e3ha2" },
+ { .compatible = "samsung,s6e3ha2",
+ .data = &samsung_s6e3ha2_tm2 },
+ { .compatible = "samsung,s6e3ha2-e",
+ .data = &samsung_s6e3ha2_tm2e },
{ }
};
MODULE_DEVICE_TABLE(of, s6e3ha2_of_match);
--
1.9.1
^ permalink raw reply related
* [PATCH 1/3] dt-bindings: Add support for samsung s6e3ha2 edge panel binding
From: Hoegeun Kwon @ 2017-04-14 5:19 UTC (permalink / raw)
To: thierry.reding, airlied, robh+dt, mark.rutland, catalin.marinas,
will.deacon, kgene, krzk
Cc: devicetree, linux-samsung-soc, linux-kernel, dri-devel, javier,
andi.shyti, Hoegeun Kwon, linux-arm-kernel
In-Reply-To: <1492147179-7824-1-git-send-email-hoegeun.kwon@samsung.com>
The Samsung s6e3ha2 edge is a 5.65" 1600x2560 AMOLED panel connected
using MIPI-DSI interfaces.
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
---
.../bindings/display/panel/samsung,s6e3ha2-e.txt | 28 ++++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
new file mode 100644
index 0000000..09c65f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
@@ -0,0 +1,28 @@
+Samsung S6E3HA2 5.65" 1600x2560 AMOLED panel
+
+Required properties:
+ - compatible: "samsung,s6e3ha2-e"
+ - reg: the virtual channel number of a DSI peripheral
+ - vdd3-supply: I/O voltage supply
+ - vci-supply: voltage supply for analog circuits
+ - reset-gpios: a GPIO spec for the reset pin (active low)
+ - enable-gpios: a GPIO spec for the panel enable pin (active high)
+
+Optional properties:
+ - te-gpios: a GPIO spec for the tearing effect synchronization signal
+ gpio pin (active high)
+
+Example:
+&dsi {
+ ...
+
+ panel@0 {
+ compatible = "samsung,s6e3ha2-e";
+ reg = <0>;
+ vdd3-supply = <&ldo27_reg>;
+ vci-supply = <&ldo28_reg>;
+ reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
+ enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+ te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
+ };
+};
--
1.9.1
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 0/3] Add support for the S6E3HA2 edge panel on TM2e board
From: Hoegeun Kwon @ 2017-04-14 5:19 UTC (permalink / raw)
To: thierry.reding, airlied, robh+dt, mark.rutland, catalin.marinas,
will.deacon, kgene, krzk
Cc: dri-devel, devicetree, linux-arm-kernel, linux-samsung-soc,
linux-kernel, javier, a.hajda, andi.shyti, Hoegeun Kwon
In-Reply-To: <CGME20170414051958epcas5p379f82e72e9239fdea0b99de88c4c39f1@epcas5p3.samsung.com>
The purpose of this patch is add support for S6E3HA2 edge AMOLED panel
on the TM2e board. The panel has 1600x2560 resolution in 5.65"
physical panel in the TM2e device.
The S6E3HA2 edge panel(5.65") is simliar to the previous S6E3HA2
panel(5.7"), but resolution and some command message are different. So
it can be distinguished as a compatiblitiy string.
Best regards,
Hoegeun
Hoegeun Kwon (3):
dt-bindings: Add support for samsung s6e3ha2 edge panel binding
drm/panel: s6e3ha2: Add support for S6eHEA2 edge panel on TM2e board
arm64: dts: exynos: Add support for S6E3HA2 edge panel device on TM2e
board
.../bindings/display/panel/samsung,s6e3ha2-e.txt | 28 ++++++++++
arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts | 12 +++++
drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c | 62 +++++++++++++++++++---
3 files changed, 96 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/panel/samsung,s6e3ha2-e.txt
--
1.9.1
^ permalink raw reply
* Re: [PATCH 2/2] hwrng: mtk: Add driver for hardware random generator on MT7623 SoC
From: PrasannaKumar Muralidharan @ 2017-04-14 4:57 UTC (permalink / raw)
To: Sean Wang
Cc: Herbert Xu, Matt Mackall, Rob Herring, Mark Rutland,
Corentin LABBE, Romain Perier, shannon.nelson, Wei Yongjun,
devicetree, linux-crypto, linux-mediatek, linux-arm-kernel,
linux-kernel, sean wang
In-Reply-To: <1492142296.6147.19.camel@mtkswgap22>
On 14 April 2017 at 09:28, Sean Wang <sean.wang@mediatek.com> wrote:
>
> Hi PrasannaKumar,
>
> Add my comments inline
>
>>
>> Use readl_poll_timeout_atomic's return value or -EIO instead of
>> !!ready. This will simplify mtk_rng_read.
>>
>
> !!ready provided is in order to let blocking/non-blocking case could
> share same code path. And readl_poll_timeout_atomic only handles
> blocking case.
Missed this point. Makes sense. My previous comment about return value
in mtk_rng_read is invalid as I based it on a wrong assumption.
>
>> > +static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
>> > +{
>> > + struct mtk_rng *priv = to_mtk_rng(rng);
>> > + int retval = 0;
>> > +
>> > + while (max >= sizeof(u32)) {
>> > + if (!mtk_rng_wait_ready(rng, wait))
>> > + break;
>> > +
>> > + *(u32 *)buf = readl(priv->base + RNG_DATA);
>> > + retval += sizeof(u32);
>> > + buf += sizeof(u32);
>> > + max -= sizeof(u32);
>> > + }
>> > +
>> > + if (unlikely(wait && max))
>> > + dev_warn(priv->dev, "timeout might be not properly set\n");
>>
>> Is this really necessary? Better to choose proper timeout than
>> providing this warning message. In rare cases if the timeout could
>> occur due to some reason (may be a hardware fault) print appropriate
>> warning message.
>
> It is good, I will choose the proper timeout and remove the log in the
> next one.
>
>>
>> > + return retval || !wait ? retval : -EIO;
>> > +}
>>
>> Set retavl to mtk_rng_wait_ready and return retval.
>>
>
> Maybe i didn't get your points exactly. Adding some explanation about
> thoughts here.
>
> "return retval || !wait ? retval : -EIO;" I use can also help handling
> the both cases in one line which i think is elegant enough.
>
> And retval is accumulated with each round if some data's existing in
> hardware, so we don't return the value from mtk_rng_wait_ready().
retval can be 0 only when mkt_rng_wait_ready fails, returning 0 when
wait is true is confusing. Expected return value when 0 bytes is read
from device and wait is true is not clearly documented.
"return retval || !wait ? retval : -EIO;" is also fine.
Overall the code looks good to me. You can add:
Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>.
Regards,
PrasannaKumar
^ permalink raw reply
* Re: [PATCH 2/2] hwrng: mtk: Add driver for hardware random generator on MT7623 SoC
From: Sean Wang @ 2017-04-14 3:58 UTC (permalink / raw)
To: PrasannaKumar Muralidharan
Cc: Herbert Xu, Matt Mackall, Rob Herring, Mark Rutland,
Corentin LABBE, Romain Perier, shannon.nelson, Wei Yongjun,
devicetree, linux-crypto, linux-mediatek, linux-arm-kernel,
linux-kernel, keyhaede
In-Reply-To: <CANc+2y4Oj-sbSKnsTSK+kRYNewp7Pj0fEk_=dqULxWG08L77Eg@mail.gmail.com>
Hi PrasannaKumar,
Add my comments inline
On Thu, 2017-04-13 at 14:09 +0530, PrasannaKumar Muralidharan wrote:
> Hi Sean,
>
> Mostly looks good, have few minor comments.
>
> On 13 April 2017 at 12:35, <sean.wang@mediatek.com> wrote:
> > +static bool mtk_rng_wait_ready(struct hwrng *rng, bool wait)
> > +{
> > + struct mtk_rng *priv = to_mtk_rng(rng);
> > + int ready;
> > +
> > + ready = readl(priv->base + RNG_CTRL) & RNG_READY;
> > + if (!ready && wait)
> > + readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready,
> > + ready & RNG_READY, USEC_POLL,
> > + TIMEOUT_POLL);
> > + return !!ready;
> > +}
>
> Use readl_poll_timeout_atomic's return value or -EIO instead of
> !!ready. This will simplify mtk_rng_read.
>
!!ready provided is in order to let blocking/non-blocking case could
share same code path. And readl_poll_timeout_atomic only handles
blocking case.
> > +static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
> > +{
> > + struct mtk_rng *priv = to_mtk_rng(rng);
> > + int retval = 0;
> > +
> > + while (max >= sizeof(u32)) {
> > + if (!mtk_rng_wait_ready(rng, wait))
> > + break;
> > +
> > + *(u32 *)buf = readl(priv->base + RNG_DATA);
> > + retval += sizeof(u32);
> > + buf += sizeof(u32);
> > + max -= sizeof(u32);
> > + }
> > +
> > + if (unlikely(wait && max))
> > + dev_warn(priv->dev, "timeout might be not properly set\n");
>
> Is this really necessary? Better to choose proper timeout than
> providing this warning message. In rare cases if the timeout could
> occur due to some reason (may be a hardware fault) print appropriate
> warning message.
It is good, I will choose the proper timeout and remove the log in the
next one.
>
> > + return retval || !wait ? retval : -EIO;
> > +}
>
> Set retavl to mtk_rng_wait_ready and return retval.
>
Maybe i didn't get your points exactly. Adding some explanation about
thoughts here.
"return retval || !wait ? retval : -EIO;" I use can also help handling
the both cases in one line which i think is elegant enough.
And retval is accumulated with each round if some data's existing in
hardware, so we don't return the value from mtk_rng_wait_ready().
> Regards,
> Prasanna
thanks for all your reviewing and suggestion
Sean
^ permalink raw reply
* Re: [PATCH 8/8] ARM: dts: imx7d-sdb: Enable PCIe peripheral
From: Shawn Guo @ 2017-04-14 3:51 UTC (permalink / raw)
To: Andrey Smirnov
Cc: yurovsky-Re5JQEeQqe8AvxtiuMwx3w, Sascha Hauer, Fabio Estevam,
Rob Herring, Mark Rutland, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170413133242.5068-9-andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Thu, Apr 13, 2017 at 06:32:42AM -0700, Andrey Smirnov wrote:
> Enable PCIe peripheral on this board.
>
> Cc: yurovsky-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> Cc: Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> Cc: Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> Signed-off-by: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> arch/arm/boot/dts/imx7d-sdb.dts | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
> index e0ff276..f77e26a 100644
> --- a/arch/arm/boot/dts/imx7d-sdb.dts
> +++ b/arch/arm/boot/dts/imx7d-sdb.dts
> @@ -352,6 +352,13 @@
> };
> };
>
> +&pcie {
> + pinctrl-names = "default";
> + reset-gpio = <&gpio_spi 1 GPIO_ACTIVE_LOW>;
> + disable-gpio = <&gpio_spi 0 GPIO_ACTIVE_LOW>;
I do not see this disable-gpio is documented or supported.
Shawn
> + status = "okay";
> +};
> +
> &pwm1 {
> pinctrl-names = "default";
> pinctrl-0 = <&pinctrl_pwm1>;
> --
> 2.9.3
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 6/8] ARM: dts: imx7d-sdb: Add GPIO expander node
From: Shawn Guo @ 2017-04-14 3:47 UTC (permalink / raw)
To: Andrey Smirnov
Cc: yurovsky-Re5JQEeQqe8AvxtiuMwx3w, Sascha Hauer, Fabio Estevam,
Rob Herring, Mark Rutland, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170413133242.5068-7-andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Thu, Apr 13, 2017 at 06:32:40AM -0700, Andrey Smirnov wrote:
> Add node for U38, a 74LV595PW serial-in shift register that acts as a
> GPIO expander on the board.
>
> Cc: yurovsky-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> Cc: Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> Cc: Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> Signed-off-by: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> arch/arm/boot/dts/imx7d-sdb.dts | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
> index 5be01a1..e0ff276 100644
> --- a/arch/arm/boot/dts/imx7d-sdb.dts
> +++ b/arch/arm/boot/dts/imx7d-sdb.dts
> @@ -52,6 +52,30 @@
> reg = <0x80000000 0x80000000>;
> };
>
> + spi4 {
> + compatible = "spi-gpio";
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_spi1>;
> + status = "okay";
The 'status' is not needed in this case.
> + gpio-sck = <&gpio1 13 0>;
> + gpio-mosi = <&gpio1 9 0>;
> + cs-gpios = <&gpio1 12 0>;
> + num-chipselects = <1>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + gpio_spi: gpio_spi@0 {
gpio-expander might be a better node name?
> + compatible = "fairchild,74hc595";
> + gpio-controller;
> + #gpio-cells = <2>;
> + reg = <0>;
> + registers-number = <1>;
> + /* Enable PERI_3V3, SENSOR_RST_B and HDMI_RST*/
> + registers-default = /bits/ 8 <0x74>;
I do not see this property is documented or supported by kernel.
> + spi-max-frequency = <100000>;
> + };
> + };
> +
> regulators {
> compatible = "simple-bus";
> #address-cells = <1>;
> @@ -642,5 +666,13 @@
> fsl,pins = <
> MX7D_PAD_LPSR_GPIO1_IO01__PWM1_OUT 0x110b0
> >;
> +
> + pinctrl_spi1: spi1grp {
> + fsl,pins = <
> + MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x59
> + MX7D_PAD_GPIO1_IO12__GPIO1_IO12 0x59
> + MX7D_PAD_GPIO1_IO13__GPIO1_IO13 0x59
> + >;
> + };
> };
> };
> --
> 2.9.3
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 4/8] ARM: dts: imx7s: Add node for GPC
From: Shawn Guo @ 2017-04-14 3:40 UTC (permalink / raw)
To: Andrey Smirnov
Cc: yurovsky-Re5JQEeQqe8AvxtiuMwx3w, Sascha Hauer, Fabio Estevam,
Rob Herring, Mark Rutland, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170413133242.5068-5-andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Thu, Apr 13, 2017 at 06:32:38AM -0700, Andrey Smirnov wrote:
> Add node for GPC and specify as a parent interrupt controller for SoC bus.
>
> Cc: yurovsky-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
> Cc: Sascha Hauer <kernel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
> Cc: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> Cc: Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> Signed-off-by: Andrey Smirnov <andrew.smirnov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> arch/arm/boot/dts/imx7s.dtsi | 27 ++++++++++++++++++++++++++-
> 1 file changed, 26 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
> index 8fee299..1a7058f 100644
> --- a/arch/arm/boot/dts/imx7s.dtsi
> +++ b/arch/arm/boot/dts/imx7s.dtsi
> @@ -42,6 +42,7 @@
> */
>
> #include <dt-bindings/clock/imx7d-clock.h>
> +#include <dt-bindings/power/imx7-power.h>
> #include <dt-bindings/gpio/gpio.h>
> #include <dt-bindings/input/input.h>
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> @@ -119,7 +120,7 @@
> #address-cells = <1>;
> #size-cells = <1>;
> compatible = "simple-bus";
> - interrupt-parent = <&intc>;
> + interrupt-parent = <&gpc>;
> ranges;
>
> funnel@30041000 {
> @@ -301,6 +302,7 @@
> interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
> #interrupt-cells = <3>;
> interrupt-controller;
> + interrupt-parent = <&intc>;
> reg = <0x31001000 0x1000>,
> <0x31002000 0x2000>,
> <0x31004000 0x2000>,
> @@ -309,6 +311,7 @@
>
> timer {
> compatible = "arm,armv7-timer";
> + interrupt-parent = <&intc>;
> interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
> @@ -564,6 +567,28 @@
> interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
> #reset-cells = <1>;
> };
> +
> + gpc: gpc@303a0000 {
> + compatible = "fsl,imx7d-gpc";
> + reg = <0x303a0000 0x10000>;
> + interrupt-controller;
> + interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
> + #interrupt-cells = <3>;
> + interrupt-parent = <&intc>;
> + #power-domain-cells = <1>;
> +
> + pgc {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + pgc_pcie_phy: pgc-pcie-phy-domain {
The node name should be something generic and has a unit-address when
there is a 'reg' property in the node.
> + #power-domain-cells = <0>;
> +
Drop this newline.
Shawn
> + reg = <IMX7_POWER_DOMAIN_PCIE_PHY>;
> + power-supply = <®_1p0d>;
> + };
> + };
> + };
> };
>
> aips2: aips-bus@30400000 {
> --
> 2.9.3
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/2] hwrng: mtk: Add driver for hardware random generator on MT7623 SoC
From: Sean Wang @ 2017-04-14 3:38 UTC (permalink / raw)
To: Corentin Labbe
Cc: herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
mpm-VDJrAJ4Gl5ZBDgjK7y7TUQ, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
mark.rutland-5wv7dgnIgG8, prasannatsmkumar-Re5JQEeQqe8AvxtiuMwx3w,
romain.perier-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
shannon.nelson-QHcLZuEGTsvQT0dZR+AlfA,
weiyongjun1-hv44wF8Li93QT0dZR+AlfA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
keyhaede-Re5JQEeQqe8AvxtiuMwx3w
In-Reply-To: <20170413110643.GA413@Red>
Hi Corentin,
I all agree and appreciate your careful reviewing.
They will be added into the next one.
Sean
On Thu, 2017-04-13 at 13:06 +0200, Corentin Labbe wrote:
> Hello
>
> I have some minor comment below:
>
> On Thu, Apr 13, 2017 at 03:05:08PM +0800, sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org wrote:
> > From: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> >
> > This patch adds support for hardware random generator on MT7623 SoC
> > and should also work on other similar Mediatek SoCs. Currently,
> > the driver is already tested successfully with rng-tools.
> >
> > Signed-off-by: Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > ---
> > drivers/char/hw_random/Kconfig | 16 +++-
> > drivers/char/hw_random/Makefile | 2 +-
> > drivers/char/hw_random/mtk-rng.c | 174 +++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 190 insertions(+), 2 deletions(-)
> > create mode 100644 drivers/char/hw_random/mtk-rng.c
> >
> > diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
> > index 0cafe08..af782ce 100644
> > --- a/drivers/char/hw_random/Kconfig
> > +++ b/drivers/char/hw_random/Kconfig
> > @@ -419,10 +419,24 @@ config HW_RANDOM_CAVIUM
> > Generator hardware found on Cavium SoCs.
> >
> > To compile this driver as a module, choose M here: the
> > - module will be called cavium_rng.
> > + module will be called mtk-rng.
>
> Unwanted change
>
> >
> > If unsure, say Y.
> >
> > +config HW_RANDOM_MTK
> > + tristate "Mediatek Random Number Generator support"
> > + depends on HW_RANDOM
> > + depends on ARCH_MEDIATEK || COMPILE_TEST
> > + default y
> > + ---help---
> > + This driver provides kernel-side support for the Random Number
> > + Generator hardware found on Mediatek SoCs.
> > +
> > + To compile this driver as a module, choose M here. the
> > + module will be called mtk-rng.
> > +
> > + If unsure, say Y.
> > +
> > endif # HW_RANDOM
> >
> > config UML_RANDOM
> > diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
> > index 5f52b1e..68be716 100644
> > --- a/drivers/char/hw_random/Makefile
> > +++ b/drivers/char/hw_random/Makefile
> > @@ -1,7 +1,6 @@
> > #
> > # Makefile for HW Random Number Generator (RNG) device drivers.
> > #
> > -
>
> Another unwanted change
>
> > obj-$(CONFIG_HW_RANDOM) += rng-core.o
> > rng-core-y := core.o
> > obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
> > @@ -36,3 +35,4 @@ obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
> > obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o
> > obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o
> > obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o
> > +obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o
> > diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
> > new file mode 100644
> > index 0000000..6561ee0
> > --- /dev/null
> > +++ b/drivers/char/hw_random/mtk-rng.c
> > @@ -0,0 +1,174 @@
> > +/*
> > + * Driver for Mediatek Hardware Random Number Generator
> > + *
> > + * Copyright (C) 2017 Sean Wang <sean.wang-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + */
> > +#define MTK_RNG_DEV KBUILD_MODNAME
> > +
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/err.h>
> > +#include <linux/hw_random.h>
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/platform_device.h>
> > +
> > +#define USEC_POLL 2
> > +#define TIMEOUT_POLL 20
> > +
> > +#define RNG_CTRL 0x00
> > +#define RNG_EN BIT(0)
> > +#define RNG_READY BIT(31)
>
> Keep only one space between define and name
>
> > +
> > +#define RNG_DATA 0x08
> > +
> > +#define to_mtk_rng(p) container_of(p, struct mtk_rng, rng)
> > +
> > +struct mtk_rng {
> > + struct device *dev;
> > + void __iomem *base;
> > + struct clk *clk;
> > + struct hwrng rng;
> > +};
> > +
> > +static int mtk_rng_init(struct hwrng *rng)
> > +{
> > + struct mtk_rng *priv = to_mtk_rng(rng);
> > + u32 val;
> > + int err;
> > +
> > + err = clk_prepare_enable(priv->clk);
> > + if (err)
> > + return err;
> > +
> > + val = readl(priv->base + RNG_CTRL);
> > + val |= RNG_EN;
> > + writel(val, priv->base + RNG_CTRL);
> > +
> > + return 0;
> > +}
> > +
> > +static void mtk_rng_cleanup(struct hwrng *rng)
> > +{
> > + struct mtk_rng *priv = to_mtk_rng(rng);
> > + u32 val;
> > +
> > + val = readl(priv->base + RNG_CTRL);
> > + val &= ~RNG_EN;
> > + writel(val, priv->base + RNG_CTRL);
> > +
> > + clk_disable_unprepare(priv->clk);
> > +}
> > +
> > +static bool mtk_rng_wait_ready(struct hwrng *rng, bool wait)
> > +{
> > + struct mtk_rng *priv = to_mtk_rng(rng);
> > + int ready;
> > +
> > + ready = readl(priv->base + RNG_CTRL) & RNG_READY;
> > + if (!ready && wait)
> > + readl_poll_timeout_atomic(priv->base + RNG_CTRL, ready,
> > + ready & RNG_READY, USEC_POLL,
> > + TIMEOUT_POLL);
> > + return !!ready;
> > +}
> > +
> > +static int mtk_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
> > +{
> > + struct mtk_rng *priv = to_mtk_rng(rng);
> > + int retval = 0;
> > +
> > + while (max >= sizeof(u32)) {
> > + if (!mtk_rng_wait_ready(rng, wait))
> > + break;
> > +
> > + *(u32 *)buf = readl(priv->base + RNG_DATA);
> > + retval += sizeof(u32);
> > + buf += sizeof(u32);
> > + max -= sizeof(u32);
> > + }
> > +
> > + if (unlikely(wait && max))
> > + dev_warn(priv->dev, "timeout might be not properly set\n");
> > +
> > + return retval || !wait ? retval : -EIO;
> > +}
> > +
> > +static int mtk_rng_probe(struct platform_device *pdev)
> > +{
> > + struct resource *res;
> > + int ret;
> > + struct mtk_rng *priv;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + if (!res) {
> > + dev_err(&pdev->dev, "no iomem resource\n");
> > + return -ENXIO;
> > + }
> > +
> > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + priv->dev = &pdev->dev;
> > + priv->rng.name = pdev->name;
> > + priv->rng.init = mtk_rng_init;
> > + priv->rng.cleanup = mtk_rng_cleanup;
> > + priv->rng.read = mtk_rng_read;
> > +
> > + priv->clk = devm_clk_get(&pdev->dev, "rng");
> > + if (IS_ERR(priv->clk)) {
> > + ret = PTR_ERR(priv->clk);
> > + dev_err(&pdev->dev, "no clock for device: %d\n", ret);
> > + return ret;
> > + }
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>
> You get that resource twice
>
> Regards
> Corentin Labbe
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox