From a189d28e5edea70f20995547ddc84c79b2f76c03 Mon Sep 17 00:00:00 2001 From: Ruud Derwig Date: Mon, 6 Jun 2016 10:47:46 +0300 Subject: [PATCH 1/3] drm/arcpgu: Make ARC PGU usable on simulation platforms In case of simulation there's no real encoder/transmitter device because in the model's virtual LCD we're rendering whatever appears in frame-buffer memory. Signed-off-by: Ruud Derwig Signed-off-by: Alexey Brodkin Acked-by: Daniel Vetter --- drivers/gpu/drm/arc/Makefile | 2 +- drivers/gpu/drm/arc/arcpgu.h | 1 + drivers/gpu/drm/arc/arcpgu_drv.c | 15 ++-- drivers/gpu/drm/arc/arcpgu_sim.c | 128 +++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 8 deletions(-) create mode 100644 drivers/gpu/drm/arc/arcpgu_sim.c diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile index d48fda70f857d..73de56a0139a8 100644 --- a/drivers/gpu/drm/arc/Makefile +++ b/drivers/gpu/drm/arc/Makefile @@ -1,2 +1,2 @@ -arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_drv.o +arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_sim.o arcpgu_drv.o obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h index 86574b698a785..329ac75709113 100644 --- a/drivers/gpu/drm/arc/arcpgu.h +++ b/drivers/gpu/drm/arc/arcpgu.h @@ -43,6 +43,7 @@ static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, int arc_pgu_setup_crtc(struct drm_device *dev); int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np); +int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np); struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev, unsigned int preferred_bpp, unsigned int num_crtc, unsigned int max_conn_count); diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 7675bbc701333..07c1bdeca4895 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -149,15 +149,16 @@ static int arcpgu_load(struct drm_device *drm) /* find the encoder node and initialize it */ encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0); - if (!encoder_node) { - dev_err(drm->dev, "failed to get an encoder slave node\n"); - return -ENODEV; + if (encoder_node) { + ret = arcpgu_drm_hdmi_init(drm, encoder_node); + if (ret < 0) + return ret; + } else { + ret = arcpgu_drm_sim_init(drm, 0); + if (ret < 0) + return ret; } - ret = arcpgu_drm_hdmi_init(drm, encoder_node); - if (ret < 0) - return ret; - drm_mode_config_reset(drm); drm_kms_helper_poll_init(drm); diff --git a/drivers/gpu/drm/arc/arcpgu_sim.c b/drivers/gpu/drm/arc/arcpgu_sim.c new file mode 100644 index 0000000000000..2bf06d71556af --- /dev/null +++ b/drivers/gpu/drm/arc/arcpgu_sim.c @@ -0,0 +1,128 @@ +/* + * ARC PGU DRM driver. + * + * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include + +#include "arcpgu.h" + +#define XRES_DEF 640 +#define YRES_DEF 480 + +#define XRES_MAX 8192 +#define YRES_MAX 8192 + + +struct arcpgu_drm_connector { + struct drm_connector connector; + struct drm_encoder_slave *encoder_slave; +}; + +static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) +{ + int count; + + count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); + drm_set_preferred_mode(connector, XRES_DEF, YRES_DEF); + return count; +} + +static enum drm_connector_status +arcpgu_drm_connector_detect(struct drm_connector *connector, bool force) +{ + return connector_status_connected; +} + +static void arcpgu_drm_connector_destroy(struct drm_connector *connector) +{ + drm_connector_unregister(connector); + drm_connector_cleanup(connector); +} + +static const struct drm_connector_helper_funcs +arcpgu_drm_connector_helper_funcs = { + .get_modes = arcpgu_drm_connector_get_modes, +}; + +static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .reset = drm_atomic_helper_connector_reset, + .detect = arcpgu_drm_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = arcpgu_drm_connector_destroy, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +int arcpgu_drm_sim_init(struct drm_device *drm, struct device_node *np) +{ + struct arcpgu_drm_connector *arcpgu_connector; + struct drm_encoder_slave *encoder; + struct drm_connector *connector; + int ret; + + encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL); + if (encoder == NULL) + return -ENOMEM; + + encoder->base.possible_crtcs = 1; + encoder->base.possible_clones = 0; + + ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs, + DRM_MODE_ENCODER_VIRTUAL, NULL); + if (ret) + return ret; + + arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector), + GFP_KERNEL); + if (!arcpgu_connector) { + ret = -ENOMEM; + goto error_encoder_cleanup; + } + + connector = &arcpgu_connector->connector; + drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs); + + ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL); + if (ret < 0) { + dev_err(drm->dev, "failed to initialize drm connector\n"); + goto error_encoder_cleanup; + } + + ret = drm_mode_connector_attach_encoder(connector, &encoder->base); + if (ret < 0) { + dev_err(drm->dev, "could not attach connector to encoder\n"); + drm_connector_unregister(connector); + goto error_connector_cleanup; + } + + arcpgu_connector->encoder_slave = encoder; + + return 0; + +error_connector_cleanup: + drm_connector_cleanup(connector); + +error_encoder_cleanup: + drm_encoder_cleanup(&encoder->base); + return ret; +} From c8f1daa8ba27742f8b6c01048b0a01e20f3211da Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Mon, 6 Jun 2016 10:52:51 +0300 Subject: [PATCH 2/3] ARCv2: [vdk] Enable ARC PGU on HS38 VDK With required ARC PGU updates that allow it to be used on simulation platforms we may finally utilize ARC PGU in HS38 VDK with modern Linux kernels. Signed-off-by: Alexey Brodkin --- arch/arc/boot/dts/vdk_axs10x_mb.dtsi | 13 +++++++++---- arch/arc/boot/dts/vdk_hs38_smp.dts | 2 +- arch/arc/configs/vdk_hs38_smp_defconfig | 7 ++----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi index 45cd665fca232..99498a4b42161 100644 --- a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi +++ b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi @@ -23,6 +23,11 @@ #clock-cells = <0>; }; + pguclk: pguclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25175000>; + }; }; ethernet@0x18000 { @@ -75,11 +80,11 @@ }; /* PGU output directly sent to virtual LCD screen; hdmi controller not modelled */ - pgu@0x17000 { - compatible = "snps,arcpgufb"; + pgu@17000 { + compatible = "snps,arcpgu"; reg = <0x17000 0x400>; - clock-frequency = <51000000>; /* PGU'clock is initated in init function */ - /* interrupts = <5>; PGU interrupts not used, this vector is used for ps2 below */ + clocks = <&pguclk>; + clock-names = "pxlclk"; }; /* VDK has additional ps2 keyboard/mouse interface integrated in LCD screen model */ diff --git a/arch/arc/boot/dts/vdk_hs38_smp.dts b/arch/arc/boot/dts/vdk_hs38_smp.dts index 031a5bc79b3e5..2ba60c399d994 100644 --- a/arch/arc/boot/dts/vdk_hs38_smp.dts +++ b/arch/arc/boot/dts/vdk_hs38_smp.dts @@ -16,6 +16,6 @@ compatible = "snps,axs103"; chosen { - bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0"; + bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0 video=640x480-24"; }; }; diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig index 52ec315dc5c95..969b206d6c67b 100644 --- a/arch/arc/configs/vdk_hs38_smp_defconfig +++ b/arch/arc/configs/vdk_hs38_smp_defconfig @@ -63,12 +63,9 @@ CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -CONFIG_FB=y -CONFIG_ARCPGU_RGB888=y -CONFIG_ARCPGU_DISPTYPE=0 -# CONFIG_VGA_CONSOLE is not set +CONFIG_DRM=y +CONFIG_DRM_ARCPGU=y CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set From 830c6578481e3b8649261062dfc5b0ac3c9374f8 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Mon, 6 Jun 2016 10:56:53 +0300 Subject: [PATCH 3/3] ARC: [nsimosci] Enable ARC PGU on nSIM OSCI virtual platforms With required ARC PGU updates that allow it to be used on simulation platforms we may finally utilize ARC PGU in nSIM OSCI virtual platforms with modern Linux kernels. Signed-off-by: Alexey Brodkin --- arch/arc/boot/dts/nsimosci.dts | 14 +++++++++++--- arch/arc/boot/dts/nsimosci_hs.dts | 14 +++++++++++--- arch/arc/boot/dts/nsimosci_hs_idu.dts | 14 +++++++++++--- arch/arc/configs/nsimosci_defconfig | 3 ++- arch/arc/configs/nsimosci_hs_defconfig | 3 ++- arch/arc/configs/nsimosci_hs_smp_defconfig | 3 ++- 6 files changed, 39 insertions(+), 12 deletions(-) diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts index b5b060adce8a6..37c416defe903 100644 --- a/arch/arc/boot/dts/nsimosci.dts +++ b/arch/arc/boot/dts/nsimosci.dts @@ -20,7 +20,7 @@ /* this is for console on PGU */ /* bootargs = "console=tty0 consoleblank=0"; */ /* this is for console on serial */ - bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug"; + bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug video=640x480-24"; }; aliases { @@ -58,9 +58,17 @@ no-loopback-test = <1>; }; - pgu0: pgu@f9000000 { - compatible = "snps,arcpgufb"; + pguclk: pguclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25175000>; + }; + + pgu@f9000000 { + compatible = "snps,arcpgu"; reg = <0xf9000000 0x400>; + clocks = <&pguclk>; + clock-names = "pxlclk"; }; ps2: ps2@f9001000 { diff --git a/arch/arc/boot/dts/nsimosci_hs.dts b/arch/arc/boot/dts/nsimosci_hs.dts index 325e73090a181..f2a22c49541d0 100644 --- a/arch/arc/boot/dts/nsimosci_hs.dts +++ b/arch/arc/boot/dts/nsimosci_hs.dts @@ -20,7 +20,7 @@ /* this is for console on PGU */ /* bootargs = "console=tty0 consoleblank=0"; */ /* this is for console on serial */ - bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug"; + bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblank=0 debug video=640x480-24"; }; aliases { @@ -58,9 +58,17 @@ no-loopback-test = <1>; }; - pgu0: pgu@f9000000 { - compatible = "snps,arcpgufb"; + pguclk: pguclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25175000>; + }; + + pgu@f9000000 { + compatible = "snps,arcpgu"; reg = <0xf9000000 0x400>; + clocks = <&pguclk>; + clock-names = "pxlclk"; }; ps2: ps2@f9001000 { diff --git a/arch/arc/boot/dts/nsimosci_hs_idu.dts b/arch/arc/boot/dts/nsimosci_hs_idu.dts index ee03d71265816..34457a5e7706b 100644 --- a/arch/arc/boot/dts/nsimosci_hs_idu.dts +++ b/arch/arc/boot/dts/nsimosci_hs_idu.dts @@ -18,7 +18,7 @@ chosen { /* this is for console on serial */ - bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblan=0 debug"; + bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=tty0 console=ttyS0,115200n8 consoleblan=0 debug video=640x480-24"; }; aliases { @@ -77,9 +77,17 @@ no-loopback-test = <1>; }; - pgu0: pgu@f9000000 { - compatible = "snps,arcpgufb"; + pguclk: pguclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <25175000>; + }; + + pgu@f9000000 { + compatible = "snps,arcpgu"; reg = <0xf9000000 0x400>; + clocks = <&pguclk>; + clock-names = "pxlclk"; }; ps2: ps2@f9001000 { diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig index 42bafa552498f..98cf20933bbb3 100644 --- a/arch/arc/configs/nsimosci_defconfig +++ b/arch/arc/configs/nsimosci_defconfig @@ -58,7 +58,8 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -CONFIG_FB=y +CONFIG_DRM=y +CONFIG_DRM_ARCPGU=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_HID is not set diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig index 4bb60c1cd4a2f..ddf8b96d494e9 100644 --- a/arch/arc/configs/nsimosci_hs_defconfig +++ b/arch/arc/configs/nsimosci_hs_defconfig @@ -57,7 +57,8 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -CONFIG_FB=y +CONFIG_DRM=y +CONFIG_DRM_ARCPGU=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_HID is not set diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig index 7e88f4c720f80..ceb90745326e5 100644 --- a/arch/arc/configs/nsimosci_hs_smp_defconfig +++ b/arch/arc/configs/nsimosci_hs_smp_defconfig @@ -70,7 +70,8 @@ CONFIG_SERIAL_8250_DW=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set -CONFIG_FB=y +CONFIG_DRM=y +CONFIG_DRM_ARCPGU=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_HID is not set