From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 31 Jan 2024 03:29:01 +0000 Subject: [PATCH] add lvds1024*800 --- kernel/drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 98 insertions(+), 22 deletions(-) diff --git a/kernel/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/kernel/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index aef487d..c277d2f 100644 --- a/kernel/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/kernel/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -1,16 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-only /* drivers/gpu/drm/exynos5433_drm_decon.c * * Copyright (C) 2015 Samsung Electronics Co.Ltd * Authors: * Joonyoung Shim <jy0922.shim@samsung.com> * Hyungwon Hwang <human.hwang@samsung.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 Foundationr */ -#include <linux/platform_device.h> #include <linux/clk.h> #include <linux/component.h> #include <linux/iopoll.h> @@ -18,14 +14,17 @@ #include <linux/mfd/syscon.h> #include <linux/of_device.h> #include <linux/of_gpio.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> -#include "exynos_drm_drv.h" +#include <drm/drm_fourcc.h> +#include <drm/drm_vblank.h> + #include "exynos_drm_crtc.h" +#include "exynos_drm_drv.h" #include "exynos_drm_fb.h" #include "exynos_drm_plane.h" -#include "exynos_drm_iommu.h" #include "regs-decon5433.h" #define DSD_CFG_MUX 0x1004 @@ -56,6 +55,7 @@ struct decon_context { struct device *dev; struct drm_device *drm_dev; + void *dma_priv; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[WINDOWS_NR]; struct exynos_drm_plane_config configs[WINDOWS_NR]; @@ -82,6 +82,14 @@ static const enum drm_plane_type decon_win_types[WINDOWS_NR] = { [PRIMARY_WIN] = DRM_PLANE_TYPE_PRIMARY, [CURSON_WIN] = DRM_PLANE_TYPE_CURSOR, +}; + +static const unsigned int capabilities[WINDOWS_NR] = { + 0, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, }; static inline void decon_set_bits(struct decon_context *ctx, u32 reg, u32 mask, @@ -181,7 +189,7 @@ if (regmap_update_bits(ctx->sysreg, DSD_CFG_MUX, DSD_CFG_MUX_TE_UNMASK_GLOBAL, ~0)) - DRM_ERROR("Cannot update sysreg.\n"); + DRM_DEV_ERROR(ctx->dev, "Cannot update sysreg.\n"); } static void decon_commit(struct exynos_drm_crtc *crtc) @@ -252,10 +260,75 @@ decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0); } +static void decon_win_set_bldeq(struct decon_context *ctx, unsigned int win, + unsigned int alpha, unsigned int pixel_alpha) +{ + u32 mask = BLENDERQ_A_FUNC_F(0xf) | BLENDERQ_B_FUNC_F(0xf); + u32 val = 0; + + switch (pixel_alpha) { + case DRM_MODE_BLEND_PIXEL_NONE: + case DRM_MODE_BLEND_COVERAGE: + val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA_A); + val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A); + break; + case DRM_MODE_BLEND_PREMULTI: + default: + if (alpha != DRM_BLEND_ALPHA_OPAQUE) { + val |= BLENDERQ_A_FUNC_F(BLENDERQ_ALPHA0); + val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A); + } else { + val |= BLENDERQ_A_FUNC_F(BLENDERQ_ONE); + val |= BLENDERQ_B_FUNC_F(BLENDERQ_ONE_MINUS_ALPHA_A); + } + break; + } + decon_set_bits(ctx, DECON_BLENDERQx(win), mask, val); +} + +static void decon_win_set_bldmod(struct decon_context *ctx, unsigned int win, + unsigned int alpha, unsigned int pixel_alpha) +{ + u32 win_alpha = alpha >> 8; + u32 val = 0; + + switch (pixel_alpha) { + case DRM_MODE_BLEND_PIXEL_NONE: + break; + case DRM_MODE_BLEND_COVERAGE: + case DRM_MODE_BLEND_PREMULTI: + default: + val |= WINCONx_ALPHA_SEL_F; + val |= WINCONx_BLD_PIX_F; + val |= WINCONx_ALPHA_MUL_F; + break; + } + decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_BLEND_MODE_MASK, val); + + if (alpha != DRM_BLEND_ALPHA_OPAQUE) { + val = VIDOSD_Wx_ALPHA_R_F(win_alpha) | + VIDOSD_Wx_ALPHA_G_F(win_alpha) | + VIDOSD_Wx_ALPHA_B_F(win_alpha); + decon_set_bits(ctx, DECON_VIDOSDxC(win), + VIDOSDxC_ALPHA0_RGB_MASK, val); + decon_set_bits(ctx, DECON_BLENDCON, BLEND_NEW, BLEND_NEW); + } +} + static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, struct drm_framebuffer *fb) { + struct exynos_drm_plane plane = ctx->planes[win]; + struct exynos_drm_plane_state *state = + to_exynos_plane_state(plane.base.state); + unsigned int alpha = state->base.alpha; + unsigned int pixel_alpha; unsigned long val; + + if (fb->format->has_alpha) + pixel_alpha = state->base.pixel_blend_mode; + else + pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE; val = readl(ctx->addr + DECON_WINCONx(win)); val &= WINCONx_ENWIN_F; @@ -279,12 +352,12 @@ case DRM_FORMAT_ARGB8888: default: val |= WINCONx_BPPMODE_32BPP_A8888; - val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F; + val |= WINCONx_WSWP_F; val |= WINCONx_BURSTLEN_16WORD; break; } - DRM_DEBUG_KMS("cpp = %u\n", fb->format->cpp[0]); + DRM_DEV_DEBUG_KMS(ctx->dev, "cpp = %u\n", fb->format->cpp[0]); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -298,8 +371,12 @@ val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_8WORD; } + decon_set_bits(ctx, DECON_WINCONx(win), ~WINCONx_BLEND_MODE_MASK, val); - writel(val, ctx->addr + DECON_WINCONx(win)); + if (win > 0) { + decon_win_set_bldmod(ctx, win, alpha, pixel_alpha); + decon_win_set_bldeq(ctx, win, alpha, pixel_alpha); + } } static void decon_shadow_protect(struct decon_context *ctx, bool protect) @@ -434,7 +511,7 @@ ctx->addr + DECON_CRCCTRL); } -static void decon_enable(struct exynos_drm_crtc *crtc) +static void decon_atomic_enable(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; @@ -447,7 +524,7 @@ decon_commit(ctx->crtc); } -static void decon_disable(struct exynos_drm_crtc *crtc) +static void decon_atomic_disable(struct exynos_drm_crtc *crtc) { struct decon_context *ctx = crtc->ctx; int i; @@ -484,8 +561,6 @@ { struct decon_context *ctx = crtc->ctx; int win, i, ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) { ret = clk_prepare_enable(ctx->clks[i]); @@ -525,8 +600,8 @@ } static const struct exynos_drm_crtc_ops decon_crtc_ops = { - .enable = decon_enable, - .disable = decon_disable, + .atomic_enable = decon_atomic_enable, + .atomic_disable = decon_atomic_disable, .enable_vblank = decon_enable_vblank, .disable_vblank = decon_disable_vblank, .atomic_begin = decon_atomic_begin, @@ -552,6 +627,7 @@ ctx->configs[win].num_pixel_formats = ARRAY_SIZE(decon_formats); ctx->configs[win].zpos = win - ctx->first_win; ctx->configs[win].type = decon_win_types[win]; + ctx->configs[win].capabilities = capabilities[win]; ret = exynos_plane_init(drm_dev, &ctx->planes[win], win, &ctx->configs[win]); @@ -569,17 +645,17 @@ decon_clear_channels(ctx->crtc); - return drm_iommu_attach_device(drm_dev, dev); + return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv); } static void decon_unbind(struct device *dev, struct device *master, void *data) { struct decon_context *ctx = dev_get_drvdata(dev); - decon_disable(ctx->crtc); + decon_atomic_disable(ctx->crtc); /* detach this sub driver from iommu mapping if supported. */ - drm_iommu_detach_device(ctx->drm_dev, ctx->dev); + exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv); } static const struct component_ops decon_component_ops = { @@ -699,8 +775,8 @@ return irq; } } - irq_set_status_flags(irq, IRQ_NOAUTOEN); - ret = devm_request_irq(ctx->dev, irq, handler, flags, "drm_decon", ctx); + ret = devm_request_irq(ctx->dev, irq, handler, + flags | IRQF_NO_AUTOEN, "drm_decon", ctx); if (ret < 0) { dev_err(ctx->dev, "IRQ %s request failed\n", name); return ret; -- Gitblit v1.6.2