Skip to content

Commit

Permalink
drivers: gpu: add K230 video output & DSI
Browse files Browse the repository at this point in the history
Signed-off-by: 黄子懿 <[email protected]>
  • Loading branch information
MrThanlon authored and RevySR committed Jun 29, 2024
1 parent ceffd2d commit e8dde9a
Show file tree
Hide file tree
Showing 23 changed files with 3,292 additions and 0 deletions.
86 changes: 86 additions & 0 deletions arch/riscv/boot/dts/canaan/k230.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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"
75 changes: 75 additions & 0 deletions arch/riscv/boot/dts/canaan/k230d-canmv.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
};
};
};
};
1 change: 1 addition & 0 deletions arch/riscv/configs/k230_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions drivers/gpu/drm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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/
32 changes: 32 additions & 0 deletions drivers/gpu/drm/canaan/Kconfig
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions drivers/gpu/drm/canaan/Makefile
Original file line number Diff line number Diff line change
@@ -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
157 changes: 157 additions & 0 deletions drivers/gpu/drm/canaan/canaan_crtc.c
Original file line number Diff line number Diff line change
@@ -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 <linux/version.h>
#include <linux/module.h>
#include <linux/component.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_vblank.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_print.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_plane.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>

#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;
}
Loading

0 comments on commit e8dde9a

Please sign in to comment.