From 6360dda569316b7bccb2f8b9e5ebdf1aca045b0f Mon Sep 17 00:00:00 2001 From: xuyan Date: Wed, 18 Jun 2025 15:22:29 +0800 Subject: [PATCH] drm/phytium: Fix some Bugs in Phytium Display Engine phytium inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICG2IH CVE: NA ---------------------------------------------------------- Modified this files to support Phytium Display Engine more. Signed-off-by: Yang Xun Signed-off-by: Chen Baozi Signed-off-by: Wang Yinfeng Signed-off-by: xuyan --- arch/arm64/configs/openeuler_defconfig | 1 + drivers/gpu/drm/phytium/Makefile | 5 + drivers/gpu/drm/phytium/pe220x_dc.c | 122 +++++++++++------ drivers/gpu/drm/phytium/pe220x_dc.h | 7 +- drivers/gpu/drm/phytium/pe220x_dp.c | 64 ++++----- drivers/gpu/drm/phytium/pe220x_dp.h | 3 +- drivers/gpu/drm/phytium/phytium_crtc.c | 125 +++++++++++++++--- drivers/gpu/drm/phytium/phytium_display_drv.c | 15 +++ drivers/gpu/drm/phytium/phytium_display_drv.h | 8 ++ drivers/gpu/drm/phytium/phytium_dp.c | 57 ++++++-- drivers/gpu/drm/phytium/phytium_dp.h | 2 + drivers/gpu/drm/phytium/phytium_gem.c | 6 +- drivers/gpu/drm/phytium/phytium_panel.c | 4 +- drivers/gpu/drm/phytium/phytium_pci.c | 14 +- drivers/gpu/drm/phytium/phytium_plane.c | 47 ++++++- drivers/gpu/drm/phytium/phytium_plane.h | 8 +- drivers/gpu/drm/phytium/phytium_platform.c | 73 ++++++++++ drivers/gpu/drm/phytium/phytium_reg.h | 11 +- drivers/gpu/drm/phytium/px210_dc.c | 2 + drivers/gpu/drm/phytium/px210_dp.h | 1 + 20 files changed, 453 insertions(+), 122 deletions(-) diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index be1faf2da008..5fd09ccb84cd 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -6,6 +6,7 @@ CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_TABLE_SORT=y CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_DRM_PHYTIUM=m # # General setup # diff --git a/drivers/gpu/drm/phytium/Makefile b/drivers/gpu/drm/phytium/Makefile index 2dc7ea1118cd..2e730a02f166 100644 --- a/drivers/gpu/drm/phytium/Makefile +++ b/drivers/gpu/drm/phytium/Makefile @@ -16,3 +16,8 @@ phytium-dc-drm-y := phytium_display_drv.o \ obj-$(CONFIG_DRM_PHYTIUM) += phytium-dc-drm.o CFLAGS_REMOVE_phytium_crtc.o += -mgeneral-regs-only +ifeq ($(ARCH), x86) + FPU_CFLAGS += -mhard-float + FPU_CFLAGS += -msse -msse2 + CFLAGS_phytium_crtc.o += $(FPU_CFLAGS) +endif \ No newline at end of file diff --git a/drivers/gpu/drm/phytium/pe220x_dc.c b/drivers/gpu/drm/phytium/pe220x_dc.c index 8f74199f9a47..88ab5e495e4d 100644 --- a/drivers/gpu/drm/phytium/pe220x_dc.c +++ b/drivers/gpu/drm/phytium/pe220x_dc.c @@ -7,7 +7,9 @@ #include #include +#if defined(__arm__) || defined(__aarch64__) #include +#endif #include #include "phytium_display_drv.h" #include "pe220x_reg.h" @@ -56,6 +58,10 @@ static const unsigned int pe220x_primary_formats[] = { DRM_FORMAT_NV21, }; +static const unsigned int pe220x_bmc_primary_formats[] = { + DRM_FORMAT_XRGB8888, +}; + static uint64_t pe220x_primary_formats_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID @@ -109,49 +115,76 @@ void pe220x_dc_hw_reset(struct drm_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); + if (priv->info.bmc_mode) { + pe220x_dc_hw_disable(crtc); + config &= (~(DC0_CORE_RESET | DC1_CORE_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 | AHB_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 | AHB_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); + } + } 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); + 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); + } } } @@ -216,6 +249,15 @@ void pe220x_dc_hw_plane_get_primary_format(const uint64_t **format_modifiers, *format_count = ARRAY_SIZE(pe220x_primary_formats); } +void pe220x_dc_bmc_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_bmc_primary_formats; + *format_count = ARRAY_SIZE(pe220x_bmc_primary_formats); +} + void pe220x_dc_hw_plane_get_cursor_format(const uint64_t **format_modifiers, const uint32_t **formats, uint32_t *format_count) diff --git a/drivers/gpu/drm/phytium/pe220x_dc.h b/drivers/gpu/drm/phytium/pe220x_dc.h index f88a054cf0d0..ff6480d3e99c 100644 --- a/drivers/gpu/drm/phytium/pe220x_dc.h +++ b/drivers/gpu/drm/phytium/pe220x_dc.h @@ -9,8 +9,8 @@ #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_HDISPLAY_MAX 1920 +#define PE220X_DC_VDISPLAY_MAX 1080 #define PE220X_DC_ADDRESS_MASK 0x7f extern void pe220x_dc_hw_vram_init(struct phytium_display_private *priv, @@ -22,6 +22,9 @@ extern int pe220x_dc_hw_fb_format_check(const struct drm_mode_fb_cmd2 *mode_cmd, 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_bmc_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); diff --git a/drivers/gpu/drm/phytium/pe220x_dp.c b/drivers/gpu/drm/phytium/pe220x_dp.c index 54a6e8ac454b..ac94fb64f4f9 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.c +++ b/drivers/gpu/drm/phytium/pe220x_dp.c @@ -5,6 +5,9 @@ * Copyright (C) 2021-2023, Phytium Technology Co., Ltd. */ +#include +#include +#include #include "phytium_display_drv.h" #include "pe220x_reg.h" #include "phytium_dp.h" @@ -379,13 +382,9 @@ static void pe220x_dp_hw_poweron_panel(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_ENABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_power_en, 1); if (ret < 0) DRM_ERROR("%s: failed to poweron panel\n", __func__); } @@ -394,13 +393,9 @@ static void pe220x_dp_hw_poweroff_panel(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | PANEL_POWER_DISABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_power_en, 0); if (ret < 0) DRM_ERROR("%s: failed to poweroff panel\n", __func__); } @@ -409,12 +404,15 @@ static void pe220x_dp_hw_enable_backlight(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port, ret = 0; + struct pwm_state state; + int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_ENABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + pwm_get_state(phytium_dp->pwm, &state); + state.enabled = true; + pwm_set_relative_duty_cycle(&state, 50, 100); + ret = pwm_apply_state(phytium_dp->pwm, &state); + + gpiod_set_value(priv->edp_bl_en, 1); if (ret < 0) DRM_ERROR("%s: failed to enable backlight\n", __func__); } @@ -423,45 +421,41 @@ static void pe220x_dp_hw_disable_backlight(struct phytium_dp_device *phytium_dp) { struct drm_device *dev = phytium_dp->dev; struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; int ret = 0; - phytium_writel_reg(priv, FLAG_REQUEST | CMD_BACKLIGHT | BACKLIGHT_DISABLE, - 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + gpiod_set_value(priv->edp_bl_en, 0); if (ret < 0) - DRM_ERROR("%s: failed to disable backlight\n", __func__); + DRM_ERROR("%s: failed to disable backlight, ret = %d\n", __func__, ret); } static uint32_t pe220x_dp_hw_get_backlight(struct phytium_dp_device *phytium_dp) { - struct drm_device *dev = phytium_dp->dev; - struct phytium_display_private *priv = dev->dev_private; - int config; - uint32_t group_offset = priv->address_transform_base; + struct pwm_state state; + uint32_t level; - config = phytium_readl_reg(priv, group_offset, PE220X_DC_ADDRESS_TRANSFORM_BACKLIGHT_VALUE); - return ((config >> BACKLIGHT_VALUE_SHIFT) & BACKLIGHT_VALUE_MASK); + pwm_get_state(phytium_dp->pwm, &state); + level = pwm_get_relative_duty_cycle(&state, 100); + return level; } static int pe220x_dp_hw_set_backlight(struct phytium_dp_device *phytium_dp, uint32_t level) { - struct drm_device *dev = phytium_dp->dev; - struct phytium_display_private *priv = dev->dev_private; - int port = phytium_dp->port; - int config = 0; + struct pwm_state state; int ret = 0; if (level > PE220X_DP_BACKLIGHT_MAX) { ret = -EINVAL; goto out; } + pwm_get_state(phytium_dp->pwm, &state); + state.enabled = true; + state.period = phytium_dp->pwm->args.period; + if (state.period == 0) + DRM_ERROR("%s: set pwm period to 0\n", __func__); + + pwm_set_relative_duty_cycle(&state, level, 100); - config = FLAG_REQUEST | CMD_BACKLIGHT | ((level & BACKLIGHT_MASK) << BACKLIGHT_SHIFT); - phytium_writel_reg(priv, config, 0, PE220X_DC_CMD_REGISTER(port)); - ret = phytium_wait_cmd_done(priv, PE220X_DC_CMD_REGISTER(port), - FLAG_REQUEST, FLAG_REPLY); + ret = pwm_apply_state(phytium_dp->pwm, &state); if (ret < 0) DRM_ERROR("%s: failed to set backlight\n", __func__); out: diff --git a/drivers/gpu/drm/phytium/pe220x_dp.h b/drivers/gpu/drm/phytium/pe220x_dp.h index 8e67937dafef..4796b96e106d 100644 --- a/drivers/gpu/drm/phytium/pe220x_dp.h +++ b/drivers/gpu/drm/phytium/pe220x_dp.h @@ -8,7 +8,8 @@ #ifndef __PE220X_DP_H__ #define __PE220X_DP_H__ -#define PE220X_DP_BACKLIGHT_MAX 100 +#define PE220X_DP_BACKLIGHT_MAX 99 +#define PE220X_DP_BACKLIGHT_MIN 2 void pe220x_dp_func_register(struct phytium_dp_device *phytium_dp); #endif /* __PE220X_DP_H__ */ diff --git a/drivers/gpu/drm/phytium/phytium_crtc.c b/drivers/gpu/drm/phytium/phytium_crtc.c index 76074a1d9c2e..96c93e998612 100644 --- a/drivers/gpu/drm/phytium/phytium_crtc.c +++ b/drivers/gpu/drm/phytium/phytium_crtc.c @@ -6,7 +6,11 @@ #include #include +#if defined(__arm__) || defined(__aarch64__) #include +#elif defined(__x86_64) +#include +#endif #include #include "phytium_display_drv.h" #include "phytium_crtc.h" @@ -29,7 +33,7 @@ #define MATH_Add(X, Y) ((float)((X) + (Y))) #define MATH_Multiply(X, Y) ((float)((X) * (Y))) #define MATH_Divide(X, Y) ((float)((X) / (Y))) -#define MATH_DivideFromUInteger(X, Y) ((float)(X) / (float)(Y)) +#define MATH_DivideFromUInteger(X, Y) (((float)(X) / (float)(Y))) #define MATH_I2Float(X) ((float)(X)) struct filter_blit_array { @@ -38,6 +42,7 @@ struct filter_blit_array { uint32_t *kernelStates; }; + static void phytium_crtc_gamma_set(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -45,9 +50,11 @@ static void phytium_crtc_gamma_set(struct drm_crtc *crtc) struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc); int phys_pipe = phytium_crtc->phys_pipe; uint32_t group_offset = priv->dc_reg_base[phys_pipe]; - uint32_t config = 0; + uint32_t config = 0, data; struct drm_crtc_state *state = crtc->state; struct drm_color_lut *lut; + unsigned long flags; + uint32_t active_line = 0, timeout = 500; int i; if (state->gamma_lut) { @@ -55,13 +62,44 @@ static void phytium_crtc_gamma_set(struct drm_crtc *crtc) "gamma size is not match\n")) return; lut = (struct drm_color_lut *)state->gamma_lut->data; + + config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG); + if (config & FRAMEBUFFER_OUTPUT) { + struct drm_display_mode *mode = &state->adjusted_mode; + uint32_t frame_time; + uint32_t value_a, value_b; + + frame_time = mode->crtc_vtotal * mode->crtc_htotal / mode->crtc_clock; + value_b = (frame_time - 2) * mode->crtc_vtotal; + local_irq_save(flags); + do { + active_line = phytium_readl_reg(priv, group_offset, + PHYTIUM_DC_LOCATION); + active_line = active_line >> LOVATION_Y_SHIFT; + value_a = (mode->crtc_vblank_end - mode->crtc_vblank_start + + active_line) * frame_time; + if (value_a < value_b) + break; + local_irq_restore(flags); + udelay(1000); + timeout--; + local_irq_save(flags); + } while (timeout); + + if (timeout == 0) + DRM_ERROR("wait gamma active line timeout\n"); + } + + phytium_writel_reg(priv, 0, group_offset, PHYTIUM_DC_GAMMA_INDEX); for (i = 0; i < GAMMA_INDEX_MAX; i++) { - phytium_writel_reg(priv, i, group_offset, PHYTIUM_DC_GAMMA_INDEX); - config = ((lut[i].red >> 6) & GAMMA_RED_MASK) << GAMMA_RED_SHIFT; - config |= (((lut[i].green >> 6) & GAMMA_GREEN_MASK) << GAMMA_GREEN_SHIFT); - config |= (((lut[i].blue >> 6) & GAMMA_BLUE_MASK) << GAMMA_BLUE_SHIFT); - phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_GAMMA_DATA); + data = ((lut[i].red >> 6) & GAMMA_RED_MASK) << GAMMA_RED_SHIFT; + data |= (((lut[i].green >> 6) & GAMMA_GREEN_MASK) << GAMMA_GREEN_SHIFT); + data |= (((lut[i].blue >> 6) & GAMMA_BLUE_MASK) << GAMMA_BLUE_SHIFT); + phytium_writel_reg(priv, data, group_offset, PHYTIUM_DC_GAMMA_DATA); } + + if (config & FRAMEBUFFER_OUTPUT) + local_irq_restore(flags); } } @@ -72,8 +110,11 @@ static void phytium_crtc_gamma_init(struct drm_crtc *crtc) struct phytium_crtc *phytium_crtc = to_phytium_crtc(crtc); int phys_pipe = phytium_crtc->phys_pipe; uint32_t group_offset = priv->dc_reg_base[phys_pipe]; - uint32_t config = 0; + struct drm_crtc_state *state = crtc->state; + uint32_t config = 0, data; uint16_t *red, *green, *blue; + unsigned long flags; + uint32_t active_line = 0, timeout = 500; int i; if (WARN((crtc->gamma_size != GAMMA_INDEX_MAX), "gamma size is not match\n")) @@ -83,13 +124,42 @@ static void phytium_crtc_gamma_init(struct drm_crtc *crtc) green = red + crtc->gamma_size; blue = green + crtc->gamma_size; + config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG); + if (config & FRAMEBUFFER_OUTPUT) { + struct drm_display_mode *mode = &state->adjusted_mode; + uint32_t frame_time; + uint32_t value_a, value_b; + + frame_time = mode->crtc_vtotal * mode->crtc_htotal / mode->crtc_clock; + value_b = (frame_time - 2) * mode->crtc_vtotal; + local_irq_save(flags); + do { + active_line = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_LOCATION); + active_line = active_line >> LOVATION_Y_SHIFT; + value_a = (mode->crtc_vblank_end - mode->crtc_vblank_start + + active_line) * frame_time; + if (value_a < value_b) + break; + local_irq_restore(flags); + udelay(1000); + timeout--; + local_irq_save(flags); + } while (timeout); + + if (timeout == 0) + DRM_ERROR("wait gamma active line timeout\n"); + } + + phytium_writel_reg(priv, 0, group_offset, PHYTIUM_DC_GAMMA_INDEX); for (i = 0; i < GAMMA_INDEX_MAX; i++) { - phytium_writel_reg(priv, i, group_offset, PHYTIUM_DC_GAMMA_INDEX); - config = ((*red++ >> 6) & GAMMA_RED_MASK) << GAMMA_RED_SHIFT; - config |= (((*green++ >> 6) & GAMMA_GREEN_MASK) << GAMMA_GREEN_SHIFT); - config |= (((*blue++ >> 6) & GAMMA_BLUE_MASK) << GAMMA_BLUE_SHIFT); - phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_GAMMA_DATA); + data = ((*red++ >> 6) & GAMMA_RED_MASK) << GAMMA_RED_SHIFT; + data |= (((*green++ >> 6) & GAMMA_GREEN_MASK) << GAMMA_GREEN_SHIFT); + data |= (((*blue++ >> 6) & GAMMA_BLUE_MASK) << GAMMA_BLUE_SHIFT); + phytium_writel_reg(priv, data, group_offset, PHYTIUM_DC_GAMMA_DATA); } + + if (config & FRAMEBUFFER_OUTPUT) + local_irq_restore(flags); } static void phytium_crtc_destroy(struct drm_crtc *crtc) @@ -197,7 +267,6 @@ phytium_crtc_atomic_enable(struct drm_crtc *crtc, /* config pix clock */ phytium_crtc->dc_hw_config_pix_clock(crtc, mode->clock); - //phytium_dc_scaling_config(crtc, old_state); config = ((mode->crtc_hdisplay & HDISPLAY_END_MASK) << HDISPLAY_END_SHIFT) | ((mode->crtc_htotal&HDISPLAY_TOTAL_MASK) << HDISPLAY_TOTAL_SHIFT); phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_HDISPLAY); @@ -231,11 +300,20 @@ phytium_crtc_atomic_enable(struct drm_crtc *crtc, else config &= (~FRAMEBUFFER_SCALE_ENABLE); + if (!priv->info.bmc_mode) + config |= FRAMEBUFFER_GAMMA_ENABLE; + if (crtc->state->gamma_lut) phytium_crtc_gamma_set(crtc); else phytium_crtc_gamma_init(crtc); + /* enable dither*/ + DRM_DEBUG_KMS("Enable dither on DC-%d\n", phys_pipe); + phytium_writel_reg(priv, DITHER_TABLE_LOW, group_offset, DC_DITHER_TABLE_LOW); + phytium_writel_reg(priv, DITHER_TABLE_HIGH, group_offset, DC_DITHER_TABLE_HIGH); + phytium_writel_reg(priv, ENABLE, group_offset, DC_DITHER_CONFIG); + phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG); drm_crtc_vblank_on(crtc); } @@ -406,6 +484,7 @@ int phytium_crtc_init(struct drm_device *dev, int phys_pipe) struct phytium_crtc_state *phytium_crtc_state; struct phytium_plane *phytium_primary_plane = NULL; struct phytium_plane *phytium_cursor_plane = NULL; + struct drm_plane *cursor_base = NULL; struct phytium_display_private *priv = dev->dev_private; int ret; @@ -448,16 +527,21 @@ int phytium_crtc_init(struct drm_device *dev, int phys_pipe) goto failed_create_primary; } - phytium_cursor_plane = phytium_cursor_plane_create(dev, phys_pipe); - if (IS_ERR(phytium_cursor_plane)) { - ret = PTR_ERR(phytium_cursor_plane); - DRM_ERROR("create cursor plane failed, phys_pipe(%d)\n", phys_pipe); - goto failed_create_cursor; + if (priv->info.bmc_mode) { + cursor_base = NULL; + } else { + phytium_cursor_plane = phytium_cursor_plane_create(dev, phys_pipe); + if (IS_ERR(phytium_cursor_plane)) { + ret = PTR_ERR(phytium_cursor_plane); + DRM_ERROR("create cursor plane failed, phys_pipe(%d)\n", phys_pipe); + goto failed_create_cursor; + } + cursor_base = &phytium_cursor_plane->base; } ret = drm_crtc_init_with_planes(dev, &phytium_crtc->base, &phytium_primary_plane->base, - &phytium_cursor_plane->base, + cursor_base, &phytium_crtc_funcs, "phys_pipe %d", phys_pipe); @@ -471,7 +555,6 @@ int phytium_crtc_init(struct drm_device *dev, int phys_pipe) drm_crtc_enable_color_mgmt(&phytium_crtc->base, 0, false, GAMMA_INDEX_MAX); if (phytium_crtc->dc_hw_reset) phytium_crtc->dc_hw_reset(&phytium_crtc->base); - phytium_crtc_gamma_init(&phytium_crtc->base); return 0; diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.c b/drivers/gpu/drm/phytium/phytium_display_drv.c index 4d813f8f6a9f..24e648173a43 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.c +++ b/drivers/gpu/drm/phytium/phytium_display_drv.c @@ -285,8 +285,11 @@ static void phytium_display_unload(struct drm_device *dev) * The device specific ioctl range is 0x40 to 0x79. */ #define DRM_PHYTIUM_VRAM_TYPE_DEVICE 0x0 +#define DRM_PHYTIUM_BMC_DEVICE 0x1 #define DRM_IOCTL_PHYTIUM_VRAM_TYPE_DEVICE DRM_IO(DRM_COMMAND_BASE\ + DRM_PHYTIUM_VRAM_TYPE_DEVICE) +#define DRM_IOCTL_PHYTIUM_IS_BMC_DEVICE DRM_IO(DRM_COMMAND_BASE\ + + DRM_PHYTIUM_BMC_DEVICE) static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -296,10 +299,20 @@ static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data, return ((priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE) ? 1 : 0); } +static int phytium_ioctl_check_bmc_device(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct phytium_display_private *priv = dev->dev_private; + + return priv->info.bmc_mode ? 1 : 0; +} + static const struct drm_ioctl_desc phytium_ioctls[] = { /* for test, none so far */ DRM_IOCTL_DEF_DRV(PHYTIUM_VRAM_TYPE_DEVICE, phytium_ioctl_check_vram_device, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(PHYTIUM_IS_BMC_DEVICE, phytium_ioctl_check_bmc_device, + DRM_AUTH|DRM_UNLOCKED), }; static const struct file_operations phytium_drm_driver_fops = { @@ -327,6 +340,7 @@ struct drm_driver phytium_display_drm_driver = { .irq_uninstall = phytium_irq_uninstall, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_free_object_unlocked = phytium_gem_free_object, .gem_prime_export = drm_gem_prime_export, .gem_prime_import = drm_gem_prime_import, .gem_prime_import_sg_table = phytium_gem_prime_import_sg_table, @@ -451,5 +465,6 @@ module_init(phytium_display_init); module_exit(phytium_display_exit); MODULE_LICENSE("GPL"); +MODULE_VERSION(DC_DRIVER_VERSION); MODULE_AUTHOR("Yang Xun "); MODULE_DESCRIPTION("Phytium Display Controller"); diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index 9038bf6ebd8c..5285b820e68d 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -8,6 +8,7 @@ #define __PHYTIUM_DISPLAY_DRV_H__ #include +#include #include #define DEBUG_LOG 0 @@ -20,6 +21,7 @@ #define DRV_DATE "20201220" #define DRV_MAJOR 1 #define DRV_MINOR 1 +#define DC_DRIVER_VERSION "1.0.0" /* come from GPU */ #define DRM_FORMAT_MOD_VENDOR_PHYTIUM 0x92 @@ -65,11 +67,15 @@ struct phytium_device_info { unsigned char num_pipes; unsigned char total_pipes; unsigned char edp_mask; + bool bmc_mode; + unsigned char reserve[2]; unsigned int crtc_clock_max; unsigned int hdisplay_max; unsigned int vdisplay_max; unsigned int backlight_max; + unsigned int backlight_min; unsigned long address_mask; + struct pwm_device *pwm; }; struct phytium_display_private { @@ -115,6 +121,8 @@ struct phytium_display_private { /* DMA info */ int dma_inited; struct dma_chan *dma_chan; + /*BL GPIO info*/ + struct gpio_desc *edp_bl_en, *edp_power_en; }; static inline unsigned int diff --git a/drivers/gpu/drm/phytium/phytium_dp.c b/drivers/gpu/drm/phytium/phytium_dp.c index 5372fadb054b..8100c1c0422c 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.c +++ b/drivers/gpu/drm/phytium/phytium_dp.c @@ -25,8 +25,10 @@ static void handle_plugged_change(struct phytium_dp_device *phytium_dp, bool plu static bool phytium_edp_init_connector(struct phytium_dp_device *phytium_dp); static void phytium_edp_fini_connector(struct phytium_dp_device *phytium_dp); static void phytium_edp_panel_poweroff(struct phytium_dp_device *phytium_dp); +static void phytium_dp_audio_codec_fini(struct phytium_dp_device *phytium_dp); static int phytium_rate[] = {162000, 270000, 540000, 810000}; +static int codec_id = PHYTIUM_DP_AUDIO_ID; void phytium_phy_writel(struct phytium_dp_device *phytium_dp, uint32_t address, uint32_t data) { @@ -874,7 +876,10 @@ void phytium_dp_hw_config_video(struct phytium_dp_device *phytium_dp) /* mul 10 for register setting */ data_per_tu = 10*tu_size * date_rate/link_bw; symbols_per_tu = (data_per_tu/10)&0xff; - frac_symbols_per_tu = (data_per_tu%10*16/10) & 0xf; + if (symbols_per_tu == 63) + frac_symbols_per_tu = 0; + else + frac_symbols_per_tu = (data_per_tu%10*16/10) & 0xf; phytium_writel_reg(priv, frac_symbols_per_tu<<24 | symbols_per_tu<<16 | tu_size, group_offset, PHYTIUM_DP_TRANSFER_UNIT_SIZE); @@ -1098,8 +1103,9 @@ static int phytium_dp_dpcd_set_link(struct phytium_dp_device *phytium_dp, link_config[0] = drm_dp_link_rate_to_bw_code(link_rate); link_config[1] = lane_count; - if (drm_dp_enhanced_frame_cap(phytium_dp->dpcd)) + if (drm_dp_enhanced_frame_cap(phytium_dp->dpcd)) { link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + } ret = drm_dp_dpcd_write(&phytium_dp->aux, DP_LINK_BW_SET, link_config, 2); if (ret < 0) { DRM_NOTE("write dpcd DP_LINK_BW_SET fail: ret:%d\n", ret); @@ -1282,7 +1288,6 @@ static bool phytium_dp_link_training_clock_recovery(struct phytium_dp_device *ph max_vswing_tries = 0; for (;;) { unsigned char link_status[DP_LINK_STATUS_SIZE]; - drm_dp_link_train_clock_recovery_delay(phytium_dp->dpcd); /* get link status 0x202-0x207 */ ret = drm_dp_dpcd_read(&phytium_dp->aux, DP_LANE0_1_STATUS, @@ -1723,6 +1728,7 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s enum drm_connector_status status = connector->status; bool video_enable = false; uint32_t index = 0; + struct edid *edid = NULL; if (phytium_dp->is_edp) status = connector_status_connected; @@ -1756,6 +1762,15 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s mdelay(2); phytium_dp_hw_enable_video(phytium_dp); } + + edid = drm_get_edid(connector, &phytium_dp->aux.ddc); + + if (edid && drm_edid_is_valid(edid)) + phytium_dp->has_audio = drm_detect_monitor_audio(edid); + else + phytium_dp->has_audio = false; + + kfree(edid); } out: @@ -2189,8 +2204,9 @@ static void phytium_encoder_enable(struct drm_encoder *encoder) phytium_dp_hw_enable_audio(phytium_dp); } - if (phytium_dp->is_edp) + if (phytium_dp->is_edp) { phytium_edp_backlight_on(phytium_dp); + } } enum drm_mode_status @@ -2206,13 +2222,13 @@ phytium_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display case 8: break; default: - DRM_INFO("not support bpc(%d)\n", display_info->bpc); + DRM_DEBUG_KMS("not support bpc(%d)\n", display_info->bpc); display_info->bpc = 8; break; } if ((display_info->color_formats & DRM_COLOR_FORMAT_RGB444) == 0) { - DRM_INFO("not support color_format(%d)\n", display_info->color_formats); + DRM_DEBUG_KMS("not support color_format(%d)\n", display_info->color_formats); display_info->color_formats = DRM_COLOR_FORMAT_RGB444; } @@ -2250,8 +2266,16 @@ static const struct drm_encoder_helper_funcs phytium_encoder_helper_funcs = { .mode_valid = phytium_encoder_mode_valid, }; +void phytium_dp_encoder_destroy(struct drm_encoder *encoder) +{ + struct phytium_dp_device *phytium_dp = encoder_to_dp_device(encoder); + + phytium_dp_audio_codec_fini(phytium_dp); + drm_encoder_cleanup(encoder); +} + static const struct drm_encoder_funcs phytium_encoder_funcs = { - .destroy = drm_encoder_cleanup, + .destroy = phytium_dp_encoder_destroy, }; static const struct dp_audio_n_m phytium_dp_audio_n_m[] = { @@ -2401,12 +2425,23 @@ static int phytium_dp_audio_codec_init(struct phytium_dp_device *phytium_dp) }; phytium_dp->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, + codec_id, &codec_data, sizeof(codec_data)); + if (!PTR_ERR_OR_ZERO(phytium_dp->audio_pdev)) + codec_id += 1; return PTR_ERR_OR_ZERO(phytium_dp->audio_pdev); } +static void phytium_dp_audio_codec_fini(struct phytium_dp_device *phytium_dp) +{ + + if (!PTR_ERR_OR_ZERO(phytium_dp->audio_pdev)) + platform_device_unregister(phytium_dp->audio_pdev); + phytium_dp->audio_pdev = NULL; + codec_id -= 1; +} + static long phytium_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { struct phytium_dp_device *phytium_dp = container_of(aux, struct phytium_dp_device, aux); @@ -2503,10 +2538,13 @@ static bool phytium_edp_init_connector(struct phytium_dp_device *phytium_dp) static void phytium_edp_fini_connector(struct phytium_dp_device *phytium_dp) { - kfree(phytium_dp->edp_edid); + if (phytium_dp->edp_edid) + kfree(phytium_dp->edp_edid); phytium_dp->edp_edid = NULL; phytium_edp_panel_poweroff(phytium_dp); + + return; } int phytium_dp_resume(struct drm_device *drm_dev) @@ -2560,6 +2598,7 @@ int phytium_dp_init(struct drm_device *dev, int port) if (phytium_dp_is_edp(phytium_dp, port)) { phytium_dp->is_edp = true; type = DRM_MODE_CONNECTOR_eDP; + phytium_dp->pwm = priv->info.pwm; phytium_dp_panel_init_backlight_funcs(phytium_dp); phytium_edp_backlight_off(phytium_dp); phytium_edp_panel_poweroff(phytium_dp); diff --git a/drivers/gpu/drm/phytium/phytium_dp.h b/drivers/gpu/drm/phytium/phytium_dp.h index 3dd788ad74a1..1a279b311912 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.h +++ b/drivers/gpu/drm/phytium/phytium_dp.h @@ -112,6 +112,7 @@ struct phytium_dp_device { struct phytium_panel panel; struct drm_display_mode native_mode; + struct pwm_device *pwm; }; union phytium_phy_tp { @@ -138,6 +139,7 @@ enum phytium_dpcd_phy_tp { PHYTIUM_PHY_TP_CP2520_2, PHYTIUM_PHY_TP_CP2520_3, }; +#define PHYTIUM_DP_AUDIO_ID (('P' << 24) + ('H' << 16) + ('Y' << 8)) #define encoder_to_dp_device(x) container_of(x, struct phytium_dp_device, encoder) #define connector_to_dp_device(x) container_of(x, struct phytium_dp_device, connector) #define panel_to_dp_device(x) container_of(x, struct phytium_dp_device, panel) diff --git a/drivers/gpu/drm/phytium/phytium_gem.c b/drivers/gpu/drm/phytium/phytium_gem.c index abeb096c8ca5..5d7891d2db6a 100644 --- a/drivers/gpu/drm/phytium/phytium_gem.c +++ b/drivers/gpu/drm/phytium/phytium_gem.c @@ -94,7 +94,7 @@ phytium_gem_prime_get_sg_table(struct drm_gem_object *obj) DRM_ERROR("failed to allocate sg\n"); goto sgt_free; } - page = phys_to_page(phytium_gem_obj->phys_addr); + page = pfn_to_page(__phys_to_pfn(phytium_gem_obj->phys_addr)); sg_set_page(sgt->sgl, page, PAGE_ALIGN(phytium_gem_obj->size), 0); } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_UNIFIED) { ret = dma_get_sgtable_attrs(dev->dev, sgt, phytium_gem_obj->vaddr, @@ -166,7 +166,7 @@ void *phytium_gem_prime_vmap(struct drm_gem_object *obj) void phytium_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) { - + return; } int phytium_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) @@ -460,7 +460,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns DRM_ERROR("fail to allocate carveout memory with size %lx\n", size); goto failed_dma_alloc; } - page = phys_to_page(phytium_gem_obj->phys_addr); + page = pfn_to_page(__phys_to_pfn(phytium_gem_obj->phys_addr)); phytium_gem_obj->iova = dma_map_page(dev->dev, page, 0, size, DMA_TO_DEVICE); if (dma_mapping_error(dev->dev, phytium_gem_obj->iova)) { DRM_ERROR("fail to dma map carveout memory with size %lx\n", size); diff --git a/drivers/gpu/drm/phytium/phytium_panel.c b/drivers/gpu/drm/phytium/phytium_panel.c index f9cc98c4e17f..0a8607da8897 100644 --- a/drivers/gpu/drm/phytium/phytium_panel.c +++ b/drivers/gpu/drm/phytium/phytium_panel.c @@ -195,7 +195,7 @@ static void phytium_dp_hw_setup_backlight(struct phytium_panel *panel) struct phytium_display_private *priv = dev->dev_private; panel->max = priv->info.backlight_max; - panel->min = 0; + panel->min = priv->info.backlight_min; panel->level = phytium_dp_hw_get_backlight(panel); } @@ -211,7 +211,7 @@ void phytium_dp_panel_init_backlight_funcs(struct phytium_dp_device *phytium_dp) phytium_dp->panel.set_backlight = phytium_dp_aux_set_backlight; phytium_dp->panel.get_backlight = phytium_dp_aux_get_backlight; } else { - DRM_DEBUG_KMS("SE Backlight Control Supported!\n"); + DRM_DEBUG_KMS("PWM Backlight Control Supported!\n"); phytium_dp->panel.setup_backlight = phytium_dp_hw_setup_backlight; phytium_dp->panel.enable_backlight = phytium_dp_hw_enable_backlight; phytium_dp->panel.disable_backlight = phytium_dp_hw_disable_backlight; diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index 5ac58aed8b5a..b304e954edb0 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -262,6 +262,12 @@ static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct phytium_display_private *priv = NULL; struct drm_device *dev = NULL; int ret = 0; + struct phytium_device_info *phytium_info = (struct phytium_device_info *)ent->driver_data; + + if (phytium_info) { + if (phytium_info->platform_mask & BIT(PHYTIUM_PLATFORM_PE220X)) + phytium_display_drm_driver.name = "pe220x"; + } ret = phytium_kick_out_firmware_fb(pdev); if (ret) @@ -277,14 +283,14 @@ static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_set_master(pdev); ret = pci_enable_device(pdev); if (ret) { - DRM_ERROR("pci enable device fail\n"); + DRM_ERROR("pci enbale device fail\n"); goto failed_enable_device; } if (dc_msi_enable) { ret = pci_enable_msi(pdev); if (ret) - DRM_ERROR("pci enable msi fail\n"); + DRM_ERROR("pci enbale msi fail\n"); } dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); @@ -407,6 +413,8 @@ static const struct phytium_device_info px210_info = { .vdisplay_max = PX210_DC_VDISPLAY_MAX, .address_mask = PX210_DC_ADDRESS_MASK, .backlight_max = PX210_DP_BACKLIGHT_MAX, + .backlight_min = PX210_DP_BACKLIGHT_MIN, + .bmc_mode = false, }; static const struct phytium_device_info pe220x_info = { @@ -417,6 +425,8 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, + .backlight_min = PE220X_DP_BACKLIGHT_MIN, + .bmc_mode = true, }; static const struct pci_device_id phytium_display_pci_ids[] = { diff --git a/drivers/gpu/drm/phytium/phytium_plane.c b/drivers/gpu/drm/phytium/phytium_plane.c index f96ec7e99c17..1228e464912d 100644 --- a/drivers/gpu/drm/phytium/phytium_plane.c +++ b/drivers/gpu/drm/phytium/phytium_plane.c @@ -106,6 +106,35 @@ phytium_plane_atomic_destroy_state(struct drm_plane *plane, struct drm_plane_sta kfree(phytium_state); } +static bool phytium_plane_format_mod_supported(struct drm_plane *plane, + uint32_t format, uint64_t modifier) +{ + if (modifier == DRM_FORMAT_MOD_LINEAR) + return true; + + if (modifier == DRM_FORMAT_MOD_PHYTIUM_TILE_MODE3_FBCDC) { + switch (format) { + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + return true; + default: + return false; + } + } + + return false; +} + const struct drm_plane_funcs phytium_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -115,6 +144,7 @@ const struct drm_plane_funcs phytium_plane_funcs = { .atomic_set_property = phytium_plane_atomic_set_property, .atomic_duplicate_state = phytium_plane_atomic_duplicate_state, .atomic_destroy_state = phytium_plane_atomic_destroy_state, + .format_mod_supported = phytium_plane_format_mod_supported, }; static int phytium_plane_prepare_fb(struct drm_plane *plane, @@ -442,6 +472,16 @@ static void phytium_dc_cursor_plane_update(struct drm_plane *plane) phytium_plane->cursor_x = plane->state->crtc_x + fb->hot_x; phytium_plane->cursor_y = plane->state->crtc_y + fb->hot_y; + if (phytium_plane->cursor_x < 0) { + phytium_plane->cursor_hot_x = plane->state->crtc_w - 1; + phytium_plane->cursor_x = plane->state->crtc_x + phytium_plane->cursor_hot_x; + } + + if (phytium_plane->cursor_y < 0) { + phytium_plane->cursor_hot_y = plane->state->crtc_h - 1; + phytium_plane->cursor_y = plane->state->crtc_y + phytium_plane->cursor_hot_y; + } + config = CURSOR_FORMAT_ARGB8888 | ((phytium_plane->cursor_hot_y & CURSOR_HOT_Y_MASK) << CURSOR_HOT_Y_SHIFT) | ((phytium_plane->cursor_hot_x & CURSOR_HOT_X_MASK) << CURSOR_HOT_X_SHIFT); @@ -551,7 +591,12 @@ struct phytium_plane *phytium_primary_plane_create(struct drm_device *dev, int p phytium_plane->dc_hw_update_primary_hi_addr = px210_dc_hw_update_primary_hi_addr; phytium_plane->dc_hw_update_cursor_hi_addr = NULL; } else if (IS_PE220X(priv)) { - phytium_plane->dc_hw_plane_get_format = pe220x_dc_hw_plane_get_primary_format; + if (priv->info.bmc_mode) + phytium_plane->dc_hw_plane_get_format = + pe220x_dc_bmc_hw_plane_get_primary_format; + else + phytium_plane->dc_hw_plane_get_format = + pe220x_dc_hw_plane_get_primary_format; phytium_plane->dc_hw_update_dcreq = NULL; phytium_plane->dc_hw_update_primary_hi_addr = pe220x_dc_hw_update_primary_hi_addr; phytium_plane->dc_hw_update_cursor_hi_addr = NULL; diff --git a/drivers/gpu/drm/phytium/phytium_plane.h b/drivers/gpu/drm/phytium/phytium_plane.h index 5527579b0348..fe52fd3833d6 100644 --- a/drivers/gpu/drm/phytium/phytium_plane.h +++ b/drivers/gpu/drm/phytium/phytium_plane.h @@ -21,10 +21,10 @@ struct phytium_plane { /* only for cursor */ bool enable; bool reserve[3]; - unsigned int cursor_x; - unsigned int cursor_y; - unsigned int cursor_hot_x; - unsigned int cursor_hot_y; + int cursor_x; + int cursor_y; + int cursor_hot_x; + int cursor_hot_y; void (*dc_hw_plane_get_format)(const uint64_t **format_modifiers, const uint32_t **formats, diff --git a/drivers/gpu/drm/phytium/phytium_platform.c b/drivers/gpu/drm/phytium/phytium_platform.c index d28aadba7c30..5bf6c5067ac4 100644 --- a/drivers/gpu/drm/phytium/phytium_platform.c +++ b/drivers/gpu/drm/phytium/phytium_platform.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include "phytium_display_drv.h" #include "phytium_platform.h" #include "phytium_dp.h" @@ -108,6 +111,29 @@ phytium_platform_private_init(struct platform_device *pdev) dev_err(&pdev->dev, "missing edp_mask property from dts\n"); goto failed; } + if (priv->info.edp_mask) { + priv->info.pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(priv->info.pwm)) { + dev_err(&pdev->dev, "Failed to request PWM device: %ld\n", + PTR_ERR(priv->info.pwm)); + goto failed; + } + priv->edp_bl_en = gpiod_get(&pdev->dev, "edp-bl-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_bl_en)) { + dev_err(&pdev->dev, "Failed to get edp_en gpio\n"); + priv->edp_bl_en = NULL; + goto failed; + } + priv->edp_power_en = gpiod_get(&pdev->dev, "edp-power-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_power_en)) { + dev_err(&pdev->dev, "Failed to get edp_pwr_en gpio\n"); + priv->edp_power_en = NULL; + goto failed_gpio_power_init; + } + // set GPIO pin output + gpiod_direction_output(priv->edp_power_en, 0); + gpiod_direction_output(priv->edp_bl_en, 0); + } } else if (has_acpi_companion(&pdev->dev)) { phytium_info = (struct phytium_device_info *)acpi_device_get_match_data(&pdev->dev); if (!phytium_info) { @@ -127,6 +153,29 @@ phytium_platform_private_init(struct platform_device *pdev) dev_err(&pdev->dev, "missing edp_mask property from acpi\n"); goto failed; } + if (priv->info.edp_mask) { + priv->info.pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(priv->info.pwm)) { + dev_err(&pdev->dev, "Failed to request PWM device: %ld\n", + PTR_ERR(priv->info.pwm)); + goto failed; + } + priv->edp_bl_en = gpiod_get(&pdev->dev, "edp-bl-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_bl_en)) { + dev_err(&pdev->dev, "Failed to get edp_en gpio\n"); + priv->edp_bl_en = NULL; + goto failed; + } + priv->edp_power_en = gpiod_get(&pdev->dev, "edp-power-en", GPIOD_OUT_HIGH); + if (IS_ERR(priv->edp_power_en)) { + dev_err(&pdev->dev, "Failed to get edp_pwr_en gpio\n"); + priv->edp_power_en = NULL; + goto failed_gpio_power_init; + } + // set GPIO pin output + gpiod_direction_output(priv->edp_power_en, 0); + gpiod_direction_output(priv->edp_bl_en, 0); + } } priv->info.num_pipes = 0; @@ -157,6 +206,8 @@ phytium_platform_private_init(struct platform_device *pdev) return priv; +failed_gpio_power_init: + gpiod_put(priv->edp_bl_en); failed: devm_kfree(&pdev->dev, platform_priv); exit: @@ -169,6 +220,11 @@ static void phytium_platform_private_fini(struct platform_device *pdev) struct phytium_display_private *priv = dev->dev_private; struct phytium_platform_private *platform_priv = to_platform_priv(priv); + if (priv->edp_power_en) + gpiod_put(priv->edp_power_en); + if (priv->edp_bl_en) + gpiod_put(priv->edp_bl_en); + devm_kfree(&pdev->dev, platform_priv); } @@ -176,8 +232,23 @@ static int phytium_platform_probe(struct platform_device *pdev) { struct phytium_display_private *priv = NULL; struct drm_device *dev = NULL; + struct phytium_device_info *phytium_info = NULL; int ret = 0; + if (pdev->dev.of_node) { + phytium_info = (struct phytium_device_info *)of_device_get_match_data(&pdev->dev); + if (phytium_info) { + if (phytium_info->platform_mask & BIT(PHYTIUM_PLATFORM_PE220X)) + phytium_display_drm_driver.name = "pe220x"; + } + } else if (has_acpi_companion(&pdev->dev)) { + phytium_info = (struct phytium_device_info *)acpi_device_get_match_data(&pdev->dev); + if (phytium_info) { + if (phytium_info->platform_mask & BIT(PHYTIUM_PLATFORM_PE220X)) + phytium_display_drm_driver.name = "pe220x"; + } + } + dev = drm_dev_alloc(&phytium_display_drm_driver, &pdev->dev); if (IS_ERR(dev)) { DRM_ERROR("failed to allocate drm_device\n"); @@ -270,6 +341,8 @@ static const struct phytium_device_info pe220x_info = { .vdisplay_max = PE220X_DC_VDISPLAY_MAX, .address_mask = PE220X_DC_ADDRESS_MASK, .backlight_max = PE220X_DP_BACKLIGHT_MAX, + .backlight_min = PE220X_DP_BACKLIGHT_MIN, + .bmc_mode = false, }; static const struct of_device_id display_of_match[] = { diff --git a/drivers/gpu/drm/phytium/phytium_reg.h b/drivers/gpu/drm/phytium/phytium_reg.h index 99ac9d4cb4d9..e23ac74d4c78 100644 --- a/drivers/gpu/drm/phytium/phytium_reg.h +++ b/drivers/gpu/drm/phytium/phytium_reg.h @@ -29,6 +29,12 @@ #define PANEL_DATAENABLE_ENABLE (1<<0) #define PANEL_DATA_ENABLE (1<<4) #define PANEL_CLOCK_ENABLE (1<<8) +#define DC_DITHER_CONFIG 0X1410 + #define ENABLE 0x80000000 +#define DC_DITHER_TABLE_LOW 0x1420 + #define DITHER_TABLE_LOW 0x7B48F3C0 +#define DC_DITHER_TABLE_HIGH 0X1428 + #define DITHER_TABLE_HIGH 0x596AD1E2 #define PHYTIUM_DC_HDISPLAY 0x1430 #define HDISPLAY_END_SHIFT 0 #define HDISPLAY_END_MASK 0x7fff @@ -53,7 +59,8 @@ #define VSYNC_END_MASK 0x7fff #define VSYNC_PULSE_ENABLED (1<<30) #define VSYNC_NEGATIVE (1<<31) -#define PHYTIUM_DC_DISPLAY_CURRENT_LOCATION 0x1450 +#define PHYTIUM_DC_LOCATION 0x1450 + #define LOVATION_Y_SHIFT 16 #define PHYTIUM_DC_GAMMA_INDEX 0x1458 #define GAMMA_INDEX_MAX 256 #define PHYTIUM_DC_GAMMA_DATA 0x1460 @@ -267,7 +274,7 @@ #define PHYTIUM_DP_INTERRUPT_MASK 0x0144 #define HPD_IRQ_MASK (1<<1) #define HPD_EVENT_MASK (1<<0) - #define HPD_OTHER_MASK 0x3c + #define HPD_OTHER_MASK 0x7c #define PHYTIUM_DP_AUX_REPLY_DATA_COUNT 0x0148 #define PHYTIUM_DP_AUX_STATUS 0x014C #define REPLY_RECEIVED 0x1 diff --git a/drivers/gpu/drm/phytium/px210_dc.c b/drivers/gpu/drm/phytium/px210_dc.c index ae022f9fe3fb..6769c71352bd 100644 --- a/drivers/gpu/drm/phytium/px210_dc.c +++ b/drivers/gpu/drm/phytium/px210_dc.c @@ -6,7 +6,9 @@ #include #include +#if defined(__arm__) || defined(__aarch64__) #include +#endif #include #include "phytium_display_drv.h" #include "px210_reg.h" diff --git a/drivers/gpu/drm/phytium/px210_dp.h b/drivers/gpu/drm/phytium/px210_dp.h index f2436ace1845..f59c93eafe3e 100644 --- a/drivers/gpu/drm/phytium/px210_dp.h +++ b/drivers/gpu/drm/phytium/px210_dp.h @@ -8,6 +8,7 @@ #define __PX210_DP_H__ #define PX210_DP_BACKLIGHT_MAX 100 +#define PX210_DP_BACKLIGHT_MIN 0 void px210_dp_func_register(struct phytium_dp_device *phytium_dp); #endif /* __PX210_DP_H__ */ -- Gitee