diff --git a/arch/riscv/boot/dts/canaan/k230.dtsi b/arch/riscv/boot/dts/canaan/k230.dtsi index b1594dec49f28..3d66be43dca06 100644 --- a/arch/riscv/boot/dts/canaan/k230.dtsi +++ b/arch/riscv/boot/dts/canaan/k230.dtsi @@ -401,6 +401,92 @@ clock-names = "vglite"; status = "okay"; }; + + display: display-subsystem { + compatible = "canaan,display-subsystem"; + ports = <&vo_out>; + status = "okay"; + power-domains = <&sysctl_power K230_PM_DOMAIN_DISP>; + }; + + vo: vo@90840000 { + compatible = "canaan,k230-vo"; + reg = <0x0 0x90840000 0x0 0x10000>; + interrupts = <133 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; + + background = <0xffffff>; + vth_line = <11>; + + vo_out: port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + dsi: dsi@90850000 { + compatible = "canaan,k230-mipi-dsi"; + reg = <0x0 0x90850000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + panel@0 { + compatible = "canaan,universal"; + reg = <0>; + panel-width-mm = <1080>; + panel-height-mm = <1920>; + panel-dsi-lane = <4>; + dsi_reset-gpios = <&gpio0_ports 9 GPIO_ACTIVE_HIGH>; + backlight_gpio-gpios = <&gpio0_ports 31 GPIO_ACTIVE_HIGH>; + + panel-init-sequence = [ + 39 00 04 B9 FF 83 99 + 39 00 02 D2 AA + 39 00 10 B1 02 04 71 91 01 32 33 11 11 ab 4d 56 73 02 02 + 39 00 10 B2 00 80 80 ae 05 07 5a 11 00 00 10 1e 70 03 d4 + 39 00 2d B4 00 FF 02 C0 02 c0 00 00 08 00 04 06 00 32 04 0a + 08 21 03 01 + 00 0f b8 8b 02 c0 02 c0 00 00 08 00 04 06 00 32 04 0a 08 01 + 00 0f b8 01 + 39 00 22 D3 00 00 00 00 00 00 06 00 00 10 04 00 04 00 00 00 + 00 00 00 00 00 00 00 01 00 05 05 07 00 00 00 05 40 + 39 00 21 D5 18 18 19 19 18 18 21 20 01 00 07 06 05 04 03 02 + 18 18 18 18 18 18 2f 2f 30 30 31 31 18 18 18 18 + 39 00 21 D6 18 18 19 19 40 40 20 21 02 03 04 05 06 07 00 01 + 40 40 40 40 40 40 2f 2f 30 30 31 31 40 40 40 40 + 39 00 11 D8 a2 aa 02 a0 a2 a8 02 a0 b0 00 00 00 b0 00 00 00 + 39 00 02 BD 01 + 39 00 11 D8 B0 00 00 00 B0 00 00 00 E2 AA 03 F0 E2 AA 03 F0 + 39 00 02 BD 02 + 39 00 09 D8 E2 AA 03 F0 E2 AA 03 F0 + 39 00 02 BD 00 + 39 00 03 B6 8D 8D + 39 00 02 CC 04 + 39 00 03 C6 FF F9 + 39 00 37 E0 00 12 1f 1a 40 4a 59 55 5e 67 6f 75 7a 82 8b 90 + 95 9f a3 ad a2 b2 B6 5e 5a 65 77 00 12 1f 1a 40 4a 59 55 5e + 67 6f 75 7a 82 8b 90 95 + 9f a3 ad a2 b2 B6 5e 5a 65 77 + 39 ff 01 11 + 39 ff 01 29 + ]; + + display-timings { + timing-0 { + clock-frequency = <74250000>; + hactive = <1080>; + vactive = <1920>; + hfront-porch = <40>; + hback-porch = <20>; + hsync-len = <20>; + vfront-porch = <206>; + vback-porch = <8>; + vsync-len = <5>; + }; + }; + }; + }; }; }; #include "k230_clock_provider.dtsi" diff --git a/arch/riscv/boot/dts/canaan/k230d-canmv.dts b/arch/riscv/boot/dts/canaan/k230d-canmv.dts index e0c4cde421b9b..1bcac71923b9e 100644 --- a/arch/riscv/boot/dts/canaan/k230d-canmv.dts +++ b/arch/riscv/boot/dts/canaan/k230d-canmv.dts @@ -47,3 +47,78 @@ interrupts = <22 IRQ_TYPE_EDGE_FALLING>; }; }; + +&vo { + vth_line = <10>; +}; + +&dsi { + panel@0 { + panel-width-mm = <480>; + panel-height-mm = <800>; + panel-dsi-lane = <2>; + dsi_reset-gpios = <&gpio0_ports 24 GPIO_ACTIVE_HIGH>; + backlight_gpio-gpios = <&gpio0_ports 25 GPIO_ACTIVE_HIGH>; + + panel-init-sequence = [ + 39 00 06 ff 77 01 00 00 13 + 39 00 02 ef 08 + 39 00 06 ff 77 01 00 00 10 + 39 00 03 c0 63 00 + 39 00 03 c1 10 02 + 39 00 03 c2 31 02 + 39 00 02 cc 10 + 39 00 11 b0 c0 0c 92 0c 10 05 02 0d 07 21 04 53 11 6a 32 1f + 39 00 11 b1 c0 87 cf 0c 10 06 00 03 08 1d 06 54 12 e6 ec 0f + 39 00 06 ff 77 01 00 00 11 + 39 00 02 b0 5d + 39 00 02 b1 62 + 39 00 02 b2 82 + 39 00 02 b3 80 + 39 00 02 b5 42 + 39 00 02 b7 85 + 39 00 02 b8 20 + 39 00 02 c0 09 + 39 00 02 c1 78 + 39 00 02 c2 78 + 39 00 02 d0 88 + 39 ff 02 ee 42 + 39 00 04 e0 00 00 02 + 39 00 0c e1 04 a0 06 a0 05 a0 07 a0 00 44 44 + 39 00 0d e2 00 00 33 33 01 a0 00 00 01 a0 00 00 + 39 00 05 e3 00 00 33 33 + 39 00 03 e4 44 44 + 39 00 11 e5 0c 30 a0 a0 0e 32 a0 a0 08 2c a0 a0 0a 2e a0 a0 + 39 00 05 e6 00 00 33 33 + 39 00 03 e7 44 44 + 39 00 11 e8 0d 31 a0 a0 0f 33 a0 a0 09 2d a0 a0 0b 2f a0 a0 + 39 00 08 eb 00 01 e4 e4 44 88 00 + 39 00 11 ed ff f5 47 6f 0b a1 a2 bf fb 2a 1a b0 f6 74 5f ff + 39 00 07 ef 08 08 08 40 3f 64 + 39 00 06 ff 77 01 00 00 13 + 39 00 03 e8 00 0e + 39 00 06 ff 77 01 00 00 00 + 39 ff 01 11 + 39 00 06 ff 77 01 00 00 13 + 39 ff 03 e8 00 0c + 39 00 03 e8 00 00 + 39 00 06 ff 77 01 00 00 00 + 39 00 02 3a 50 + 39 ff 01 29 + ]; + + display-timings { + timing-0 { + clock-frequency = <39600000>; + hactive = <480>; + vactive = <800>; + hfront-porch = <80>; + hback-porch = <20>; + hsync-len = <20>; + vfront-porch = <220>; + vback-porch = <70>; + vsync-len = <10>; + }; + }; + }; +}; diff --git a/arch/riscv/configs/k230_defconfig b/arch/riscv/configs/k230_defconfig index 3e7d0cacbbf81..a6c85b75daabf 100644 --- a/arch/riscv/configs/k230_defconfig +++ b/arch/riscv/configs/k230_defconfig @@ -278,3 +278,4 @@ CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_EDT_FT5X06=y CONFIG_INPUT_EVDEV=y CONFIG_GPU_VGLITE=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index de1853c07f994..9599d3cfe953f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -390,6 +390,8 @@ source "drivers/gpu/drm/sprd/Kconfig" source "drivers/gpu/drm/verisilicon/Kconfig" +source "drivers/gpu/drm/canaan/Kconfig" + config DRM_HYPERV tristate "DRM Support for Hyper-V synthetic video device" depends on DRM && PCI && MMU && HYPERV diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a0902298f98ff..92906a06447d4 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -199,3 +199,4 @@ obj-y += solomon/ obj-$(CONFIG_DRM_SPRD) += sprd/ obj-$(CONFIG_DRM_LOONGSON) += loongson/ obj-$(CONFIG_DRM_VERISILICON) += verisilicon/ +obj-y += canaan/ diff --git a/drivers/gpu/drm/canaan/Kconfig b/drivers/gpu/drm/canaan/Kconfig new file mode 100644 index 0000000000000..60f4899ccabe2 --- /dev/null +++ b/drivers/gpu/drm/canaan/Kconfig @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-only +config DRM_CANAAN + bool "DRM Support for Canaan K230 Display Controller" + depends on OF + depends on COMMON_CLK + select DRM + select DRM_KMS_HELPER + select DRM_KMS_DMA_HELPER + select DRM_GEM_DMA_HELPER + select VIDEOMODE_HELPERS + default ARCH_CANAAN + help + Choose this option if you have a Canaan K230 soc chipset. + This driver provides kernel mode setting and buffer + management to userspace. This driver does not provide + 2D or 3D acceleration; acceleration is performed by other + IP found on the SoC. + +if DRM_CANAAN + +config DRM_CANAAN_DSI + bool "Canaan K230 MIPI-DSI Controller Support" + select DRM_MIPI_DSI + default DRM_CANAAN + help + Choose this option if you have a Canaan K230 soc chipset. + This driver provides MIPI-DSI controller for DRM. + This driver does not provide 2D or 3D acceleration; + acceleration is performed by other + IP found on the SoC. + +endif diff --git a/drivers/gpu/drm/canaan/Makefile b/drivers/gpu/drm/canaan/Makefile new file mode 100644 index 0000000000000..e547cca4c4da1 --- /dev/null +++ b/drivers/gpu/drm/canaan/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +canaan-drm-y := \ + canaan_drv.o \ + canaan_vo.o \ + canaan_crtc.o \ + canaan_plane.o \ + canaan_phy.o + +obj-$(CONFIG_DRM_CANAAN) += canaan-drm.o +obj-$(CONFIG_DRM_CANAAN_DSI) += canaan_dsi.o diff --git a/drivers/gpu/drm/canaan/canaan_crtc.c b/drivers/gpu/drm/canaan/canaan_crtc.c new file mode 100644 index 0000000000000..4beb0443edcf6 --- /dev/null +++ b/drivers/gpu/drm/canaan/canaan_crtc.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022, Canaan Bright Sight Co., Ltd + * + * All enquiries to https://www.canaan-creative.com/ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "canaan_vo.h" +#include "canaan_crtc.h" +#include "canaan_plane.h" + +static int canaan_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct canaan_crtc *canaan_crtc = to_canaan_crtc(crtc); + struct canaan_vo *vo = canaan_crtc->vo; + + DRM_DEBUG_DRIVER("Enable vblank on CRTC:%d\n", crtc->base.id); + return canaan_vo_enable_vblank(vo); +} + +static void canaan_crtc_disable_vblank(struct drm_crtc *crtc) +{ + struct canaan_crtc *canaan_crtc = to_canaan_crtc(crtc); + struct canaan_vo *vo = canaan_crtc->vo; + + DRM_DEBUG_DRIVER("Disable vblank on CRTC:%d\n", crtc->base.id); + canaan_vo_disable_vblank(vo); +} + +static void canaan_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *old_crtc_state) +{ + struct canaan_crtc *canaan_crtc = to_canaan_crtc(crtc); + struct canaan_vo *vo = canaan_crtc->vo; + struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode; + + DRM_DEBUG_DRIVER("Enable the CRTC:%d\n", crtc->base.id); + + canaan_vo_enable_crtc(vo, canaan_crtc, adjusted_mode); + drm_crtc_vblank_on(crtc); +} + +static void canaan_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *old_crtc_state) +{ + struct canaan_crtc *canaan_crtc = to_canaan_crtc(crtc); + struct canaan_vo *vo = canaan_crtc->vo; + + DRM_DEBUG_DRIVER("Disable the CRTC:%d\n", crtc->base.id); + drm_crtc_vblank_off(crtc); + canaan_vo_disable_crtc(vo, canaan_crtc); + + if (crtc->state->event && !crtc->state->active) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + spin_unlock_irq(&crtc->dev->event_lock); + + crtc->state->event = NULL; + } +} + +static void canaan_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *old_crtc_state) +{ + struct canaan_crtc *canaan_crtc = to_canaan_crtc(crtc); + struct canaan_vo *vo = canaan_crtc->vo; + struct drm_pending_vblank_event *event = crtc->state->event; + + DRM_DEBUG_DRIVER("Flush the configuration\n"); + canaan_vo_flush_config(vo); + + if (event) { + WARN_ON(drm_crtc_vblank_get(crtc) != 0); + + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_arm_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + crtc->state->event = NULL; + } +} + +static const struct drm_crtc_funcs canaan_crtc_funcs = { + .reset = drm_atomic_helper_crtc_reset, + .destroy = drm_crtc_cleanup, + .set_config = drm_atomic_helper_set_config, + .page_flip = drm_atomic_helper_page_flip, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, + .enable_vblank = canaan_crtc_enable_vblank, + .disable_vblank = canaan_crtc_disable_vblank, +}; + +static const struct drm_crtc_helper_funcs canaan_crtc_helper_funcs = { + .atomic_enable = canaan_crtc_atomic_enable, + .atomic_disable = canaan_crtc_atomic_disable, + .atomic_flush = canaan_crtc_atomic_flush, +}; + +struct canaan_crtc *canaan_crtc_create(struct drm_device *drm_dev, + struct drm_plane *primary, + struct drm_plane *cursor, + struct canaan_vo *vo) +{ + int ret = 0; + struct canaan_crtc *canaan_crtc = NULL; + struct drm_crtc *crtc = NULL; + struct device *dev = vo->dev; + + canaan_crtc = devm_kzalloc(dev, sizeof(struct canaan_crtc), GFP_KERNEL); + if (!canaan_crtc) + return ERR_PTR(-ENOMEM); + canaan_crtc->vo = vo; + crtc = &canaan_crtc->base; + + ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, + &canaan_crtc_funcs, "canaan_crtc"); + if (ret) { + return ERR_PTR(ret); + DRM_DEV_ERROR(dev, "Failed to init CRTC\n"); + } + + drm_crtc_helper_add(crtc, &canaan_crtc_helper_funcs); + + drm_mode_crtc_set_gamma_size(crtc, 256); + drm_crtc_enable_color_mgmt(crtc, 0, false, 256); + DRM_DEBUG_DRIVER("Create the CRTC:%d\n", crtc->base.id); + + return canaan_crtc; +} diff --git a/drivers/gpu/drm/canaan/canaan_crtc.h b/drivers/gpu/drm/canaan/canaan_crtc.h new file mode 100644 index 0000000000000..8f6af93309ef7 --- /dev/null +++ b/drivers/gpu/drm/canaan/canaan_crtc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022, Canaan Bright Sight Co., Ltd + * + * All enquiries to https://www.canaan-creative.com/ + * + */ + +#ifndef __CANAAN_CRTC_H__ +#define __CANAAN_CRTC_H__ + +struct canaan_crtc { + struct drm_crtc base; + struct canaan_vo *vo; + struct drm_pending_vblank_event *event; +}; + +static inline struct canaan_crtc *to_canaan_crtc(struct drm_crtc *crtc) +{ + return container_of(crtc, struct canaan_crtc, base); +} + +struct canaan_crtc *canaan_crtc_create(struct drm_device *drm_dev, + struct drm_plane *primary, + struct drm_plane *cursor, + struct canaan_vo *vo); + +#endif /* __CANAAN_CRTC_H__ */ diff --git a/drivers/gpu/drm/canaan/canaan_drv.c b/drivers/gpu/drm/canaan/canaan_drv.c new file mode 100644 index 0000000000000..019ac99163c53 --- /dev/null +++ b/drivers/gpu/drm/canaan/canaan_drv.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022, Canaan Bright Sight Co., Ltd + * + * All enquiries to https://www.canaan-creative.com/ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "canaan_drv.h" +#include "canaan_vo.h" + +static int canaan_drm_open(struct inode *inode, struct file *filp); +static int canaan_drm_release(struct inode *inode, struct file *filp); + +static const struct file_operations canaan_drm_fops = { + .owner = THIS_MODULE, + .open = canaan_drm_open, + .release = canaan_drm_release, + .unlocked_ioctl = drm_ioctl, + .compat_ioctl = drm_compat_ioctl, + .poll = drm_poll, + .read = drm_read, + .llseek = noop_llseek, + .mmap = drm_gem_mmap, + DRM_GEM_DMA_UNMAPPED_AREA_FOPS +}; + +static struct drm_driver canaan_drm_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, + DRM_GEM_DMA_DRIVER_OPS_VMAP, + .fops = &canaan_drm_fops, + .name = "canaan-drm", + .desc = "Canaan K230 DRM driver", + .date = "20230501", + .major = 1, + .minor = 0, +}; + +static const struct drm_mode_config_funcs canaan_drm_mode_config_funcs = { + .fb_create = drm_gem_fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static const struct drm_mode_config_helper_funcs + canaan_drm_mode_config_helpers = { + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, + }; + +static struct device *disp_dev; + +static int canaan_drm_open(struct inode *inode, struct file *filp) +{ + int ret; + + pm_runtime_get_sync(disp_dev); + ret = drm_open(inode, filp); + + return ret; +} + +static int canaan_drm_release(struct inode *inode, struct file *filp) +{ + int ret; + + ret = drm_release(inode, filp); + // pm_runtime_put_sync(disp_dev); + + return ret; +} + +static int canaan_drm_bind(struct device *dev) +{ + int ret = 0; + struct drm_device *drm_dev; + + drm_dev = drm_dev_alloc(&canaan_drm_driver, dev); + if (IS_ERR(drm_dev)) + return PTR_ERR(drm_dev); + dev_set_drvdata(dev, drm_dev); + + drm_mode_config_init(drm_dev); + drm_dev->mode_config.min_width = 16; + drm_dev->mode_config.min_height = 16; + drm_dev->mode_config.max_width = 4096; + drm_dev->mode_config.max_height = 4096; + drm_dev->mode_config.normalize_zpos = true; + drm_dev->mode_config.funcs = &canaan_drm_mode_config_funcs; + drm_dev->mode_config.helper_private = &canaan_drm_mode_config_helpers; + + ret = component_bind_all(dev, drm_dev); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to bind all components\n"); + goto cleanup_mode_config; + } + + ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to init vblank\n"); + goto unbind_all; + } + + drm_mode_config_reset(drm_dev); + drm_kms_helper_poll_init(drm_dev); + + ret = drm_dev_register(drm_dev, 0); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to register drm device\n"); + goto finish_poll; + } + + drm_fbdev_generic_setup(drm_dev, 32); + DRM_DEV_INFO(dev, "Canaan K230 DRM driver register successfully\n"); + + return 0; + +finish_poll: + drm_kms_helper_poll_fini(drm_dev); +unbind_all: + component_unbind_all(dev, drm_dev); +cleanup_mode_config: + drm_mode_config_cleanup(drm_dev); + + dev_set_drvdata(dev, NULL); + drm_dev_put(drm_dev); + return ret; +} + +static void canaan_drm_unbind(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + drm_dev_unregister(drm_dev); + drm_kms_helper_poll_fini(drm_dev); + drm_atomic_helper_shutdown(drm_dev); + component_unbind_all(dev, drm_dev); + drm_mode_config_cleanup(drm_dev); + dev_set_drvdata(dev, NULL); + drm_dev_put(drm_dev); +} + +static const struct component_master_ops canaan_drm_master_ops = { + .bind = canaan_drm_bind, + .unbind = canaan_drm_unbind, +}; + +static struct platform_driver *const component_drivers[] = { + &canaan_vo_driver, + &canaan_dsi_driver, +}; + +static int compare_dev(struct device *dev, void *data) +{ + return dev == (struct device *)data; +} + +static struct component_match *canaan_drm_match_add(struct device *dev) +{ + int i = 0; + struct component_match *match = NULL; + + for (i = 0; i < ARRAY_SIZE(component_drivers); i++) { + struct device_driver *driver = &component_drivers[i]->driver; + struct device *p = NULL, *d; + + while ((d = platform_find_device_by_driver(p, driver))) { + put_device(p); + component_match_add(dev, &match, compare_dev, d); + p = d; + } + put_device(p); + } + + return match ?: ERR_PTR(-ENODEV); +} + +static int canaan_drm_platform_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct component_match *match = NULL; + + disp_dev = dev; + pm_runtime_enable(disp_dev); + match = canaan_drm_match_add(dev); + if (IS_ERR(match)) + return PTR_ERR(match); + + return component_master_add_with_match(dev, &canaan_drm_master_ops, + match); +} + +static int canaan_drm_platform_remove(struct platform_device *pdev) +{ + component_master_del(&pdev->dev, &canaan_drm_master_ops); + + return 0; +} + +static const struct of_device_id canaan_drm_of_table[] = { + { + .compatible = "canaan,display-subsystem", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, canaan_drm_of_table); + +static struct platform_driver canaan_drm_platform_driver = { + .probe = canaan_drm_platform_probe, + .remove = canaan_drm_platform_remove, + .driver = { + .name = "canaan-drm", + .of_match_table = canaan_drm_of_table, + }, +}; + +static int __init canaan_drm_init(void) +{ + int ret = 0; + + ret = platform_register_drivers(component_drivers, + ARRAY_SIZE(component_drivers)); + if (ret) + return ret; + + ret = platform_driver_register(&canaan_drm_platform_driver); + if (ret) + platform_unregister_drivers(component_drivers, + ARRAY_SIZE(component_drivers)); + + return ret; +} + +static void __exit canaan_drm_exit(void) +{ + platform_unregister_drivers(component_drivers, + ARRAY_SIZE(component_drivers)); + platform_driver_unregister(&canaan_drm_platform_driver); +} + +module_init(canaan_drm_init); +module_exit(canaan_drm_exit); + +MODULE_DESCRIPTION("Canaan K230 DRM driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/canaan/canaan_drv.h b/drivers/gpu/drm/canaan/canaan_drv.h new file mode 100644 index 0000000000000..646a25453ec08 --- /dev/null +++ b/drivers/gpu/drm/canaan/canaan_drv.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022, Canaan Bright Sight Co., Ltd + * + * All enquiries to https://www.canaan-creative.com/ + * + */ + +#ifndef __CANAAN_DRV_H__ +#define __CANAAN_DRV_H__ + +extern struct platform_driver canaan_vo_driver; +extern struct platform_driver canaan_dsi_driver; + +#endif /* __CANAAN_DRV_H__ */ diff --git a/drivers/gpu/drm/canaan/canaan_dsi.c b/drivers/gpu/drm/canaan/canaan_dsi.c new file mode 100644 index 0000000000000..582a8d6e305d1 --- /dev/null +++ b/drivers/gpu/drm/canaan/canaan_dsi.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022, Canaan Bright Sight Co., Ltd + * + * All enquiries to https://www.canaan-creative.com/ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "canaan_dsi.h" +#include