Skip to content

Commit

Permalink
Merge pull request deepin-community#300 from ls1156563722/DC6.6
Browse files Browse the repository at this point in the history
DRM: Phytium display engine driver
  • Loading branch information
Avenger-285714 authored Jul 2, 2024
2 parents 166e797 + bb280b7 commit a5eb928
Show file tree
Hide file tree
Showing 38 changed files with 10,435 additions and 0 deletions.
35 changes: 35 additions & 0 deletions Documentation/devicetree/bindings/gpu/phytium,dc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/phytium,dc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Phytium Display Controller

maintainers:
- Dai Jingtao <[email protected]>

properties:
compatible:
enum:
- phytium,dc

reg:
items:
- description: DC registers

interrupts:
maxItems: 1

required:
- compatible
- reg
- interrupts

examples:
- |
dc@32000000 {
compatible = "phytium,dc";
reg = <0x0 0x32000000 0x0 0x8000>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
};
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/solomon/Kconfig"

source "drivers/gpu/drm/sprd/Kconfig"

source "drivers/gpu/drm/phytium/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-$(CONFIG_DRM_HYPERV) += hyperv/
obj-y += solomon/
obj-$(CONFIG_DRM_SPRD) += sprd/
obj-$(CONFIG_DRM_LOONGSON) += loongson/
obj-$(CONFIG_DRM_PHYTIUM) += phytium/
12 changes: 12 additions & 0 deletions drivers/gpu/drm/phytium/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
config DRM_PHYTIUM
tristate "DRM Support for Phytium Graphics Card"
depends on DRM && ARCH_PHYTIUM
select DRM_KMS_HELPER
select DRM_DISPLAY_HELPER
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
help
Choose this option if you have a phytium graphics card.
Phytium graphics card include display controller for X100 and E2000 devices.
In addition,the driver also supports the display of E2000S BMC.
This driver provides kernel mode setting and buffer management to userspace.
18 changes: 18 additions & 0 deletions drivers/gpu/drm/phytium/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
phytium-dc-drm-y := phytium_display_drv.o \
phytium_plane.o \
phytium_crtc.o \
phytium_dp.o \
phytium_fb.o \
phytium_gem.o \
phytium_fbdev.o \
phytium_debugfs.o \
px210_dp.o \
phytium_panel.o \
px210_dc.o \
phytium_pci.o \
pe220x_dp.o \
pe220x_dc.o \
phytium_platform.o

obj-$(CONFIG_DRM_PHYTIUM) += phytium-dc-drm.o
CFLAGS_REMOVE_phytium_crtc.o += -mgeneral-regs-only
255 changes: 255 additions & 0 deletions drivers/gpu/drm/phytium/pe220x_dc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Phytium Pe220x display controller DRM driver
*
* Copyright (C) 2021-2023, Phytium Technology Co., Ltd.
*/

#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <asm/neon.h>
#include <linux/delay.h>
#include "phytium_display_drv.h"
#include "pe220x_reg.h"
#include "phytium_crtc.h"
#include "phytium_plane.h"
#include "phytium_fb.h"
#include "phytium_gem.h"

void pe220x_dc_hw_disable(struct drm_crtc *crtc);

static const unsigned int pe220x_primary_formats[] = {
DRM_FORMAT_ARGB2101010,
DRM_FORMAT_ABGR2101010,
DRM_FORMAT_RGBA1010102,
DRM_FORMAT_BGRA1010102,
DRM_FORMAT_ARGB8888,
DRM_FORMAT_ABGR8888,
DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRA8888,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_ARGB4444,
DRM_FORMAT_ABGR4444,
DRM_FORMAT_RGBA4444,
DRM_FORMAT_BGRA4444,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_XBGR4444,
DRM_FORMAT_RGBX4444,
DRM_FORMAT_BGRX4444,
DRM_FORMAT_ARGB1555,
DRM_FORMAT_ABGR1555,
DRM_FORMAT_RGBA5551,
DRM_FORMAT_BGRA5551,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_XBGR1555,
DRM_FORMAT_RGBX5551,
DRM_FORMAT_BGRX5551,
DRM_FORMAT_RGB565,
DRM_FORMAT_BGR565,
DRM_FORMAT_YUYV,
DRM_FORMAT_UYVY,
DRM_FORMAT_NV16,
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
};

static uint64_t pe220x_primary_formats_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};

static uint64_t pe220x_cursor_formats_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};

static const unsigned int pe220x_cursor_formats[] = {
DRM_FORMAT_ARGB8888,
};

void pe220x_dc_hw_vram_init(struct phytium_display_private *priv, resource_size_t vram_addr,
resource_size_t vram_size)
{
uint32_t config;
uint32_t group_offset = priv->address_transform_base;

phytium_writel_reg(priv, (vram_addr & SRC_ADDR_MASK) >> SRC_ADDR_OFFSET,
group_offset, PE220X_DC_ADDRESS_TRANSFORM_SRC_ADDR);
phytium_writel_reg(priv, (vram_size >> SIZE_OFFSET) | ADDRESS_TRANSFORM_ENABLE,
group_offset, PE220X_DC_ADDRESS_TRANSFORM_SIZE);
config = phytium_readl_reg(priv, group_offset, PE220X_DC_ADDRESS_TRANSFORM_DST_ADDR);
phytium_writel_reg(priv, config, group_offset, PE220X_DC_ADDRESS_TRANSFORM_DST_ADDR);
}

void pe220x_dc_hw_config_pix_clock(struct drm_crtc *crtc, int clock)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int phys_pipe = phytium_crtc->phys_pipe;
int ret = 0;

/* config pix clock */
phytium_writel_reg(priv, FLAG_REQUEST | CMD_PIXEL_CLOCK | (clock & PIXEL_CLOCK_MASK),
0, PE220X_DC_CMD_REGISTER(phys_pipe));
ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(phys_pipe),
FLAG_REQUEST, FLAG_REPLY);
if (ret < 0)
DRM_ERROR("%s: failed to set pixel clock\n", __func__);
}

void pe220x_dc_hw_reset(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int config = 0;
int phys_pipe = phytium_crtc->phys_pipe;

/* disable pixel clock for bmc mode */
if (phys_pipe == 0)
pe220x_dc_hw_disable(crtc);

config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL);
config &= (~(DC0_CORE_RESET | DC1_CORE_RESET | AXI_RESET | AHB_RESET));

if (phys_pipe == 0) {
phytium_writel_reg(priv, config | DC0_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET | AHB_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC0_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
} else {
phytium_writel_reg(priv, config | DC1_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET | AHB_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET | AXI_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config | DC1_CORE_RESET,
0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
}
}

void pe220x_dc_hw_disable(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc);
int config = 0;
int phys_pipe = phytium_crtc->phys_pipe;

/* clear framebuffer */
phytium_writel_reg(priv, CLEAR_VALUE_BLACK, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CLEARVALUE);
config = phytium_readl_reg(priv, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);
config |= FRAMEBUFFER_CLEAR;
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe],
PHYTIUM_DC_FRAMEBUFFER_CONFIG);

/* disable cursor */
config = phytium_readl_reg(priv, priv->dc_reg_base[phys_pipe], PHYTIUM_DC_CURSOR_CONFIG);
config = ((config & (~CURSOR_FORMAT_MASK)) | CURSOR_FORMAT_DISABLED);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe], PHYTIUM_DC_CURSOR_CONFIG);
mdelay(20);

/* reset pix clock */
pe220x_dc_hw_config_pix_clock(crtc, 0);

if (phys_pipe == 0) {
config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL);
phytium_writel_reg(priv, config | DC0_CORE_RESET, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config & (~DC0_CORE_RESET), 0, PE220X_DC_CLOCK_CONTROL);
} else {
config = phytium_readl_reg(priv, 0, PE220X_DC_CLOCK_CONTROL);
phytium_writel_reg(priv, config | DC1_CORE_RESET, 0, PE220X_DC_CLOCK_CONTROL);
udelay(20);
phytium_writel_reg(priv, config & (~DC1_CORE_RESET), 0, PE220X_DC_CLOCK_CONTROL);
}
udelay(20);
}

int pe220x_dc_hw_fb_format_check(const struct drm_mode_fb_cmd2 *mode_cmd, int count)
{
int ret = 0;

if (mode_cmd->modifier[count] != DRM_FORMAT_MOD_LINEAR) {
DRM_ERROR("unsupported fb modifier 0x%llx\n", mode_cmd->modifier[count]);
ret = -EINVAL;
}

return ret;
}

void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count)
{
*format_modifiers = pe220x_primary_formats_modifiers;
*formats = pe220x_primary_formats;
*format_count = ARRAY_SIZE(pe220x_primary_formats);
}

void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count)
{
*format_modifiers = pe220x_cursor_formats_modifiers;
*formats = pe220x_cursor_formats;
*format_count = ARRAY_SIZE(pe220x_cursor_formats);
}

void pe220x_dc_hw_update_primary_hi_addr(struct drm_plane *plane)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
int phys_pipe = phytium_plane->phys_pipe;

phytium_writel_reg(priv, (phytium_plane->iova[0] >> PREFIX_SHIFT) & PREFIX_MASK,
priv->dc_reg_base[phys_pipe], PE220X_DC_FRAMEBUFFER_Y_HI_ADDRESS);

phytium_writel_reg(priv, (phytium_plane->iova[1] >> U_PREFIX_SHIFT) & U_PREFIX_MASK,
priv->dc_reg_base[phys_pipe], PE220X_DC_FRAMEBUFFER_U_HI_ADDRESS);

phytium_writel_reg(priv, (phytium_plane->iova[2] >> V_PREFIX_SHIFT) & V_PREFIX_MASK,
priv->dc_reg_base[phys_pipe], PE220X_DC_FRAMEBUFFER_V_HI_ADDRESS);
}

void pe220x_dc_hw_update_cursor_hi_addr(struct drm_plane *plane, uint64_t iova)
{
struct drm_device *dev = plane->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_plane *phytium_plane = to_phytium_plane(plane);
int phys_pipe = phytium_plane->phys_pipe;
int config;

config = ((iova >> CURSOR_PREFIX_SHIFT) & CURSOR_PREFIX_MASK);
phytium_writel_reg(priv, config, priv->dc_reg_base[phys_pipe], PE220X_DC_CURSOR_HI_ADDRESS);
}
31 changes: 31 additions & 0 deletions drivers/gpu/drm/phytium/pe220x_dc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Phytium Pe220x display controller DRM driver
*
* Copyright (C) 2021-2023, Phytium Technology Co., Ltd.
*/

#ifndef __PE220X_DC_H__
#define __PE220X_DC_H__

#define PE220X_DC_PIX_CLOCK_MAX (594000)
#define PE220X_DC_HDISPLAY_MAX 3840
#define PE220X_DC_VDISPLAY_MAX 2160
#define PE220X_DC_ADDRESS_MASK 0x7f

extern void pe220x_dc_hw_vram_init(struct phytium_display_private *priv,
resource_size_t vram_addr,
resource_size_t vram_size);
extern void pe220x_dc_hw_config_pix_clock(struct drm_crtc *crtc, int clock);
extern void pe220x_dc_hw_disable(struct drm_crtc *crtc);
extern int pe220x_dc_hw_fb_format_check(const struct drm_mode_fb_cmd2 *mode_cmd, int count);
extern void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count);
extern void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers,
const uint32_t **formats,
uint32_t *format_count);
extern void pe220x_dc_hw_update_primary_hi_addr(struct drm_plane *plane);
extern void pe220x_dc_hw_update_cursor_hi_addr(struct drm_plane *plane, uint64_t iova);
void pe220x_dc_hw_reset(struct drm_crtc *crtc);
#endif /* __PE220X_DC_H__ */
Loading

0 comments on commit a5eb928

Please sign in to comment.