mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 22:50:41 +00:00
Mediatek DRM Next for Linux 5.12
1. Decouple Mediatek DRM sub driver 2. Share mtk mutex driver for both DRM and MDP 3. Add support for SoC MT8183 -----BEGIN PGP SIGNATURE----- iQJMBAABCgA2FiEEACwLKSDmq+9RDv5P4cpzo8lZTiQFAmAcDQgYHGNodW5rdWFu Zy5odUBrZXJuZWwub3JnAAoJEOHKc6PJWU4kE48P/jSb7PhZYvEiPdjsPHxIEHa7 01Qc2gNDXkYkt+circ0NtDu3CH1DB5U2b5lITUy8McMM486N4vBNisPM3oId18ik lCinMehSGvlVxHmxOBEJAj6G/rLrw4lBflDHnV38WrzWgPU/DFXQQy0kjI92T5R5 YswWYG2skAU5GX3r8i8p8PibwlA3aH9aVpgE/iDsCbpljmpJktqVYkfijAuK8phP WVxBHQaa7N6KNxQmaVZtylz2GhtSwhx4omV/TNbJYFniLqzpTnFfxmkp161V1dL7 eUteuXwwmBpQAb/jYIilYEkLKBff6XTsl5wGzeIn2o/eAiD2jPUp6BOrxl87OXBM yd61mNP56aF1mgJ3bH6Qbs/qenSP5ptVKVSl983crzLCHpDOHX4ToG39TIGX6m9M o7vHYEZQznLKWcAJmV40oPDKuIaKbL9I0ZxTVSjK8Lw75kOfOssbztHQlJkMJHiG /2FF08Klk5oMP7SsUjVgasGqrVEamv1kkmtmK218tz2QJ6cksJsydvlwhxbIVvE6 mgH2WSVI+CRKakB4+bhCg5v1zl7tM4s5aUtoqz2cHxlMABt0mtvunoB9wt4LIIks z6V7myU05q5nGhD1ClmKU5F1Fnw1J6IIECb1lmrJSCOrl0mAWqlezVDSTu8v+7Yi 7rgviHqtdRoAdZSb1u6w =s8K8 -----END PGP SIGNATURE----- Merge tag 'mediatek-drm-next-5.12' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-next Mediatek DRM Next for Linux 5.12 1. Decouple Mediatek DRM sub driver 2. Share mtk mutex driver for both DRM and MDP 3. Add support for SoC MT8183 Signed-off-by: Dave Airlie <airlied@redhat.com> From: Chun-Kuang Hu <chunkuang.hu@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20210204151750.7550-1-chunkuang.hu@kernel.org
This commit is contained in:
commit
54c820d05e
@ -37,13 +37,14 @@ Required properties (all function blocks):
|
||||
"mediatek,<chip>-disp-aal" - adaptive ambient light controller
|
||||
"mediatek,<chip>-disp-gamma" - gamma correction
|
||||
"mediatek,<chip>-disp-merge" - merge streams from two RDMA sources
|
||||
"mediatek,<chip>-disp-postmask" - control round corner for display frame
|
||||
"mediatek,<chip>-disp-split" - split stream to two encoders
|
||||
"mediatek,<chip>-disp-ufoe" - data compression engine
|
||||
"mediatek,<chip>-dsi" - DSI controller, see mediatek,dsi.txt
|
||||
"mediatek,<chip>-dpi" - DPI controller, see mediatek,dpi.txt
|
||||
"mediatek,<chip>-disp-mutex" - display mutex
|
||||
"mediatek,<chip>-disp-od" - overdrive
|
||||
the supported chips are mt2701, mt7623, mt2712, mt8167 and mt8173.
|
||||
the supported chips are mt2701, mt7623, mt2712, mt8167, mt8173, mt8183 and mt8192.
|
||||
- reg: Physical base address and length of the function block register space
|
||||
- interrupts: The interrupt signal from the function block (required, except for
|
||||
merge and split function blocks).
|
||||
@ -66,6 +67,14 @@ Required properties (DMA function blocks):
|
||||
argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
|
||||
for details.
|
||||
|
||||
Optional properties (RDMA function blocks):
|
||||
- mediatek,rdma-fifo-size: rdma fifo size may be different even in same SOC, add this
|
||||
property to the corresponding rdma
|
||||
the value is the Max value which defined in hardware data sheet.
|
||||
mediatek,rdma-fifo-size of mt8173-rdma0 is 8K
|
||||
mediatek,rdma-fifo-size of mt8183-rdma0 is 5K
|
||||
mediatek,rdma-fifo-size of mt8183-rdma1 is 2K
|
||||
|
||||
Examples:
|
||||
|
||||
mmsys: clock-controller@14000000 {
|
||||
@ -103,6 +112,7 @@ rdma0: rdma@1400e000 {
|
||||
clocks = <&mmsys CLK_MM_DISP_RDMA0>;
|
||||
iommus = <&iommu M4U_PORT_DISP_RDMA0>;
|
||||
mediatek,larb = <&larb0>;
|
||||
mediatek,rdma-fifosize = <8192>;
|
||||
};
|
||||
|
||||
rdma1: rdma@1400f000 {
|
||||
|
@ -1,10 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
mediatek-drm-y := mtk_disp_color.o \
|
||||
mediatek-drm-y := mtk_disp_ccorr.o \
|
||||
mtk_disp_color.o \
|
||||
mtk_disp_gamma.o \
|
||||
mtk_disp_ovl.o \
|
||||
mtk_disp_rdma.o \
|
||||
mtk_drm_crtc.o \
|
||||
mtk_drm_ddp.o \
|
||||
mtk_drm_ddp_comp.o \
|
||||
mtk_drm_drv.o \
|
||||
mtk_drm_gem.o \
|
||||
|
223
drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
Normal file
223
drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
Normal file
@ -0,0 +1,223 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
#define DISP_CCORR_EN 0x0000
|
||||
#define CCORR_EN BIT(0)
|
||||
#define DISP_CCORR_CFG 0x0020
|
||||
#define CCORR_RELAY_MODE BIT(0)
|
||||
#define CCORR_ENGINE_EN BIT(1)
|
||||
#define CCORR_GAMMA_OFF BIT(2)
|
||||
#define CCORR_WGAMUT_SRC_CLIP BIT(3)
|
||||
#define DISP_CCORR_SIZE 0x0030
|
||||
#define DISP_CCORR_COEF_0 0x0080
|
||||
#define DISP_CCORR_COEF_1 0x0084
|
||||
#define DISP_CCORR_COEF_2 0x0088
|
||||
#define DISP_CCORR_COEF_3 0x008C
|
||||
#define DISP_CCORR_COEF_4 0x0090
|
||||
|
||||
struct mtk_disp_ccorr_data {
|
||||
u32 matrix_bits;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_disp_ccorr - DISP_CCORR driver structure
|
||||
* @ddp_comp - structure containing type enum and hardware resources
|
||||
* @crtc - associated crtc to report irq events to
|
||||
*/
|
||||
struct mtk_disp_ccorr {
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
const struct mtk_disp_ccorr_data *data;
|
||||
};
|
||||
|
||||
int mtk_ccorr_clk_enable(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(ccorr->clk);
|
||||
}
|
||||
|
||||
void mtk_ccorr_clk_disable(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(ccorr->clk);
|
||||
}
|
||||
|
||||
void mtk_ccorr_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, w << 16 | h, &ccorr->cmdq_reg, ccorr->regs,
|
||||
DISP_CCORR_SIZE);
|
||||
mtk_ddp_write(cmdq_pkt, CCORR_ENGINE_EN, &ccorr->cmdq_reg, ccorr->regs,
|
||||
DISP_CCORR_CFG);
|
||||
}
|
||||
|
||||
void mtk_ccorr_start(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
|
||||
|
||||
writel(CCORR_EN, ccorr->regs + DISP_CCORR_EN);
|
||||
}
|
||||
|
||||
void mtk_ccorr_stop(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
|
||||
|
||||
writel_relaxed(0x0, ccorr->regs + DISP_CCORR_EN);
|
||||
}
|
||||
|
||||
/* Converts a DRM S31.32 value to the HW S1.n format. */
|
||||
static u16 mtk_ctm_s31_32_to_s1_n(u64 in, u32 n)
|
||||
{
|
||||
u16 r;
|
||||
|
||||
/* Sign bit. */
|
||||
r = in & BIT_ULL(63) ? BIT(n + 1) : 0;
|
||||
|
||||
if ((in & GENMASK_ULL(62, 33)) > 0) {
|
||||
/* identity value 0x100000000 -> 0x400(mt8183), */
|
||||
/* identity value 0x100000000 -> 0x800(mt8192), */
|
||||
/* if bigger this, set it to max 0x7ff. */
|
||||
r |= GENMASK(n, 0);
|
||||
} else {
|
||||
/* take the n+1 most important bits. */
|
||||
r |= (in >> (32 - n)) & GENMASK(n, 0);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state)
|
||||
{
|
||||
struct mtk_disp_ccorr *ccorr = dev_get_drvdata(dev);
|
||||
struct drm_property_blob *blob = state->ctm;
|
||||
struct drm_color_ctm *ctm;
|
||||
const u64 *input;
|
||||
uint16_t coeffs[9] = { 0 };
|
||||
int i;
|
||||
struct cmdq_pkt *cmdq_pkt = NULL;
|
||||
u32 matrix_bits = ccorr->data->matrix_bits;
|
||||
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
ctm = (struct drm_color_ctm *)blob->data;
|
||||
input = ctm->matrix;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeffs); i++)
|
||||
coeffs[i] = mtk_ctm_s31_32_to_s1_n(input[i], matrix_bits);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[0] << 16 | coeffs[1],
|
||||
&ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_0);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[2] << 16 | coeffs[3],
|
||||
&ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_1);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[4] << 16 | coeffs[5],
|
||||
&ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_2);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[6] << 16 | coeffs[7],
|
||||
&ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_3);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[8] << 16,
|
||||
&ccorr->cmdq_reg, ccorr->regs, DISP_CCORR_COEF_4);
|
||||
}
|
||||
|
||||
static int mtk_disp_ccorr_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_disp_ccorr_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_disp_ccorr_component_ops = {
|
||||
.bind = mtk_disp_ccorr_bind,
|
||||
.unbind = mtk_disp_ccorr_unbind,
|
||||
};
|
||||
|
||||
static int mtk_disp_ccorr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_disp_ccorr *priv;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get ccorr clk\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "failed to ioremap ccorr\n");
|
||||
return PTR_ERR(priv->regs);
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
|
||||
if (ret)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = component_add(dev, &mtk_disp_ccorr_component_ops);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to add component: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtk_disp_ccorr_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &mtk_disp_ccorr_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtk_disp_ccorr_data mt8183_ccorr_driver_data = {
|
||||
.matrix_bits = 10,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_disp_ccorr_driver_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt8183-disp-ccorr",
|
||||
.data = &mt8183_ccorr_driver_data},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_disp_ccorr_driver_dt_match);
|
||||
|
||||
struct platform_driver mtk_disp_ccorr_driver = {
|
||||
.probe = mtk_disp_ccorr_probe,
|
||||
.remove = mtk_disp_ccorr_remove,
|
||||
.driver = {
|
||||
.name = "mediatek-disp-ccorr",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = mtk_disp_ccorr_driver_dt_match,
|
||||
},
|
||||
};
|
@ -11,6 +11,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
@ -36,64 +37,55 @@ struct mtk_disp_color_data {
|
||||
* @data: platform colour driver data
|
||||
*/
|
||||
struct mtk_disp_color {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct drm_crtc *crtc;
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
const struct mtk_disp_color_data *data;
|
||||
};
|
||||
|
||||
static inline struct mtk_disp_color *comp_to_color(struct mtk_ddp_comp *comp)
|
||||
int mtk_color_clk_enable(struct device *dev)
|
||||
{
|
||||
return container_of(comp, struct mtk_disp_color, ddp_comp);
|
||||
struct mtk_disp_color *color = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(color->clk);
|
||||
}
|
||||
|
||||
static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_color_clk_disable(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_color *color = comp_to_color(comp);
|
||||
struct mtk_disp_color *color = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, w, comp, DISP_COLOR_WIDTH(color));
|
||||
mtk_ddp_write(cmdq_pkt, h, comp, DISP_COLOR_HEIGHT(color));
|
||||
clk_disable_unprepare(color->clk);
|
||||
}
|
||||
|
||||
static void mtk_color_start(struct mtk_ddp_comp *comp)
|
||||
void mtk_color_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_disp_color *color = comp_to_color(comp);
|
||||
struct mtk_disp_color *color = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, w, &color->cmdq_reg, color->regs, DISP_COLOR_WIDTH(color));
|
||||
mtk_ddp_write(cmdq_pkt, h, &color->cmdq_reg, color->regs, DISP_COLOR_HEIGHT(color));
|
||||
}
|
||||
|
||||
void mtk_color_start(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_color *color = dev_get_drvdata(dev);
|
||||
|
||||
writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL,
|
||||
comp->regs + DISP_COLOR_CFG_MAIN);
|
||||
writel(0x1, comp->regs + DISP_COLOR_START(color));
|
||||
color->regs + DISP_COLOR_CFG_MAIN);
|
||||
writel(0x1, color->regs + DISP_COLOR_START(color));
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs mtk_disp_color_funcs = {
|
||||
.config = mtk_color_config,
|
||||
.start = mtk_color_start,
|
||||
};
|
||||
|
||||
static int mtk_disp_color_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_disp_color *priv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register component %pOF: %d\n",
|
||||
dev->of_node, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_disp_color_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_disp_color *priv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
|
||||
mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp);
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_disp_color_component_ops = {
|
||||
@ -105,31 +97,32 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_disp_color *priv;
|
||||
int comp_id;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_COLOR);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
return comp_id;
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get color clk\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
|
||||
&mtk_disp_color_funcs);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to initialize component: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "failed to ioremap color\n");
|
||||
return PTR_ERR(priv->regs);
|
||||
}
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
|
||||
if (ret)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = component_add(dev, &mtk_disp_color_component_ops);
|
||||
@ -141,8 +134,6 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
|
||||
|
||||
static int mtk_disp_color_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &mtk_disp_color_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
92
drivers/gpu/drm/mediatek/mtk_disp_drv.h
Normal file
92
drivers/gpu/drm/mediatek/mtk_disp_drv.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef _MTK_DISP_DRV_H_
|
||||
#define _MTK_DISP_DRV_H_
|
||||
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
#include "mtk_drm_plane.h"
|
||||
|
||||
void mtk_ccorr_ctm_set(struct device *dev, struct drm_crtc_state *state);
|
||||
int mtk_ccorr_clk_enable(struct device *dev);
|
||||
void mtk_ccorr_clk_disable(struct device *dev);
|
||||
void mtk_ccorr_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
|
||||
void mtk_ccorr_start(struct device *dev);
|
||||
void mtk_ccorr_stop(struct device *dev);
|
||||
|
||||
void mtk_color_bypass_shadow(struct device *dev);
|
||||
int mtk_color_clk_enable(struct device *dev);
|
||||
void mtk_color_clk_disable(struct device *dev);
|
||||
void mtk_color_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
|
||||
void mtk_color_start(struct device *dev);
|
||||
|
||||
void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
|
||||
unsigned int bpc, unsigned int cfg,
|
||||
unsigned int dither_en, struct cmdq_pkt *cmdq_pkt);
|
||||
|
||||
void mtk_dpi_start(struct device *dev);
|
||||
void mtk_dpi_stop(struct device *dev);
|
||||
|
||||
void mtk_dsi_ddp_start(struct device *dev);
|
||||
void mtk_dsi_ddp_stop(struct device *dev);
|
||||
|
||||
int mtk_gamma_clk_enable(struct device *dev);
|
||||
void mtk_gamma_clk_disable(struct device *dev);
|
||||
void mtk_gamma_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
|
||||
void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state);
|
||||
void mtk_gamma_set_common(void __iomem *regs, struct drm_crtc_state *state);
|
||||
void mtk_gamma_start(struct device *dev);
|
||||
void mtk_gamma_stop(struct device *dev);
|
||||
|
||||
void mtk_ovl_bgclr_in_on(struct device *dev);
|
||||
void mtk_ovl_bgclr_in_off(struct device *dev);
|
||||
void mtk_ovl_bypass_shadow(struct device *dev);
|
||||
int mtk_ovl_clk_enable(struct device *dev);
|
||||
void mtk_ovl_clk_disable(struct device *dev);
|
||||
void mtk_ovl_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
|
||||
int mtk_ovl_layer_check(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *mtk_state);
|
||||
void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt);
|
||||
unsigned int mtk_ovl_layer_nr(struct device *dev);
|
||||
void mtk_ovl_layer_on(struct device *dev, unsigned int idx,
|
||||
struct cmdq_pkt *cmdq_pkt);
|
||||
void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
|
||||
struct cmdq_pkt *cmdq_pkt);
|
||||
void mtk_ovl_start(struct device *dev);
|
||||
void mtk_ovl_stop(struct device *dev);
|
||||
unsigned int mtk_ovl_supported_rotations(struct device *dev);
|
||||
void mtk_ovl_enable_vblank(struct device *dev,
|
||||
void (*vblank_cb)(void *),
|
||||
void *vblank_cb_data);
|
||||
void mtk_ovl_disable_vblank(struct device *dev);
|
||||
|
||||
void mtk_rdma_bypass_shadow(struct device *dev);
|
||||
int mtk_rdma_clk_enable(struct device *dev);
|
||||
void mtk_rdma_clk_disable(struct device *dev);
|
||||
void mtk_rdma_config(struct device *dev, unsigned int width,
|
||||
unsigned int height, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
|
||||
unsigned int mtk_rdma_layer_nr(struct device *dev);
|
||||
void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt);
|
||||
void mtk_rdma_start(struct device *dev);
|
||||
void mtk_rdma_stop(struct device *dev);
|
||||
void mtk_rdma_enable_vblank(struct device *dev,
|
||||
void (*vblank_cb)(void *),
|
||||
void *vblank_cb_data);
|
||||
void mtk_rdma_disable_vblank(struct device *dev);
|
||||
|
||||
#endif
|
197
drivers/gpu/drm/mediatek/mtk_disp_gamma.c
Normal file
197
drivers/gpu/drm/mediatek/mtk_disp_gamma.c
Normal file
@ -0,0 +1,197 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2021 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
#define DISP_GAMMA_EN 0x0000
|
||||
#define GAMMA_EN BIT(0)
|
||||
#define DISP_GAMMA_CFG 0x0020
|
||||
#define GAMMA_LUT_EN BIT(1)
|
||||
#define GAMMA_DITHERING BIT(2)
|
||||
#define DISP_GAMMA_SIZE 0x0030
|
||||
#define DISP_GAMMA_LUT 0x0700
|
||||
|
||||
#define LUT_10BIT_MASK 0x03ff
|
||||
|
||||
struct mtk_disp_gamma_data {
|
||||
bool has_dither;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_disp_gamma - DISP_GAMMA driver structure
|
||||
* @ddp_comp - structure containing type enum and hardware resources
|
||||
* @crtc - associated crtc to report irq events to
|
||||
*/
|
||||
struct mtk_disp_gamma {
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
const struct mtk_disp_gamma_data *data;
|
||||
};
|
||||
|
||||
int mtk_gamma_clk_enable(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(gamma->clk);
|
||||
}
|
||||
|
||||
void mtk_gamma_clk_disable(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(gamma->clk);
|
||||
}
|
||||
|
||||
void mtk_gamma_set_common(void __iomem *regs, struct drm_crtc_state *state)
|
||||
{
|
||||
unsigned int i, reg;
|
||||
struct drm_color_lut *lut;
|
||||
void __iomem *lut_base;
|
||||
u32 word;
|
||||
|
||||
if (state->gamma_lut) {
|
||||
reg = readl(regs + DISP_GAMMA_CFG);
|
||||
reg = reg | GAMMA_LUT_EN;
|
||||
writel(reg, regs + DISP_GAMMA_CFG);
|
||||
lut_base = regs + DISP_GAMMA_LUT;
|
||||
lut = (struct drm_color_lut *)state->gamma_lut->data;
|
||||
for (i = 0; i < MTK_LUT_SIZE; i++) {
|
||||
word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) +
|
||||
(((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) +
|
||||
((lut[i].blue >> 6) & LUT_10BIT_MASK);
|
||||
writel(word, (lut_base + i * 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mtk_gamma_set(struct device *dev, struct drm_crtc_state *state)
|
||||
{
|
||||
struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
|
||||
|
||||
mtk_gamma_set_common(gamma->regs, state);
|
||||
}
|
||||
|
||||
void mtk_gamma_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, h << 16 | w, &gamma->cmdq_reg, gamma->regs,
|
||||
DISP_GAMMA_SIZE);
|
||||
if (gamma->data && gamma->data->has_dither)
|
||||
mtk_dither_set_common(gamma->regs, &gamma->cmdq_reg, bpc,
|
||||
DISP_GAMMA_CFG, GAMMA_DITHERING, cmdq_pkt);
|
||||
}
|
||||
|
||||
void mtk_gamma_start(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
|
||||
|
||||
writel(GAMMA_EN, gamma->regs + DISP_GAMMA_EN);
|
||||
}
|
||||
|
||||
void mtk_gamma_stop(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_gamma *gamma = dev_get_drvdata(dev);
|
||||
|
||||
writel_relaxed(0x0, gamma->regs + DISP_GAMMA_EN);
|
||||
}
|
||||
|
||||
static int mtk_disp_gamma_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_disp_gamma_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_disp_gamma_component_ops = {
|
||||
.bind = mtk_disp_gamma_bind,
|
||||
.unbind = mtk_disp_gamma_unbind,
|
||||
};
|
||||
|
||||
static int mtk_disp_gamma_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_disp_gamma *priv;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get gamma clk\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "failed to ioremap gamma\n");
|
||||
return PTR_ERR(priv->regs);
|
||||
}
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
|
||||
if (ret)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = component_add(dev, &mtk_disp_gamma_component_ops);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to add component: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtk_disp_gamma_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &mtk_disp_gamma_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtk_disp_gamma_data mt8173_gamma_driver_data = {
|
||||
.has_dither = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_disp_gamma_driver_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt8173-disp-gamma",
|
||||
.data = &mt8173_gamma_driver_data},
|
||||
{ .compatible = "mediatek,mt8183-disp-gamma"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_disp_gamma_driver_dt_match);
|
||||
|
||||
struct platform_driver mtk_disp_gamma_driver = {
|
||||
.probe = mtk_disp_gamma_probe,
|
||||
.remove = mtk_disp_gamma_remove,
|
||||
.driver = {
|
||||
.name = "mediatek-disp-gamma",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = mtk_disp_gamma_driver_dt_match,
|
||||
},
|
||||
};
|
@ -13,6 +13,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
@ -23,6 +24,7 @@
|
||||
#define DISP_REG_OVL_RST 0x0014
|
||||
#define DISP_REG_OVL_ROI_SIZE 0x0020
|
||||
#define DISP_REG_OVL_DATAPATH_CON 0x0024
|
||||
#define OVL_LAYER_SMI_ID_EN BIT(0)
|
||||
#define OVL_BGCLR_SEL_IN BIT(2)
|
||||
#define DISP_REG_OVL_ROI_BGCLR 0x0028
|
||||
#define DISP_REG_OVL_SRC_CON 0x002c
|
||||
@ -61,6 +63,7 @@ struct mtk_disp_ovl_data {
|
||||
unsigned int gmc_bits;
|
||||
unsigned int layer_nr;
|
||||
bool fmt_rgb565_is_0;
|
||||
bool smi_id_en;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -70,88 +73,124 @@ struct mtk_disp_ovl_data {
|
||||
* @data: platform data
|
||||
*/
|
||||
struct mtk_disp_ovl {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct drm_crtc *crtc;
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
const struct mtk_disp_ovl_data *data;
|
||||
void (*vblank_cb)(void *data);
|
||||
void *vblank_cb_data;
|
||||
};
|
||||
|
||||
static inline struct mtk_disp_ovl *comp_to_ovl(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
return container_of(comp, struct mtk_disp_ovl, ddp_comp);
|
||||
}
|
||||
|
||||
static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct mtk_disp_ovl *priv = dev_id;
|
||||
struct mtk_ddp_comp *ovl = &priv->ddp_comp;
|
||||
|
||||
/* Clear frame completion interrupt */
|
||||
writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA);
|
||||
writel(0x0, priv->regs + DISP_REG_OVL_INTSTA);
|
||||
|
||||
if (!priv->crtc)
|
||||
if (!priv->vblank_cb)
|
||||
return IRQ_NONE;
|
||||
|
||||
mtk_crtc_ddp_irq(priv->crtc, ovl);
|
||||
priv->vblank_cb(priv->vblank_cb_data);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc *crtc)
|
||||
void mtk_ovl_enable_vblank(struct device *dev,
|
||||
void (*vblank_cb)(void *),
|
||||
void *vblank_cb_data)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
ovl->crtc = crtc;
|
||||
writel(0x0, comp->regs + DISP_REG_OVL_INTSTA);
|
||||
writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN);
|
||||
ovl->vblank_cb = vblank_cb;
|
||||
ovl->vblank_cb_data = vblank_cb_data;
|
||||
writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA);
|
||||
writel_relaxed(OVL_FME_CPL_INT, ovl->regs + DISP_REG_OVL_INTEN);
|
||||
}
|
||||
|
||||
static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp)
|
||||
void mtk_ovl_disable_vblank(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
ovl->crtc = NULL;
|
||||
writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN);
|
||||
ovl->vblank_cb = NULL;
|
||||
ovl->vblank_cb_data = NULL;
|
||||
writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_INTEN);
|
||||
}
|
||||
|
||||
static void mtk_ovl_start(struct mtk_ddp_comp *comp)
|
||||
int mtk_ovl_clk_enable(struct device *dev)
|
||||
{
|
||||
writel_relaxed(0x1, comp->regs + DISP_REG_OVL_EN);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(ovl->clk);
|
||||
}
|
||||
|
||||
static void mtk_ovl_stop(struct mtk_ddp_comp *comp)
|
||||
void mtk_ovl_clk_disable(struct device *dev)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_REG_OVL_EN);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(ovl->clk);
|
||||
}
|
||||
|
||||
static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_ovl_start(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
if (ovl->data->smi_id_en) {
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = reg | OVL_LAYER_SMI_ID_EN;
|
||||
writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
}
|
||||
writel_relaxed(0x1, ovl->regs + DISP_REG_OVL_EN);
|
||||
}
|
||||
|
||||
void mtk_ovl_stop(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
writel_relaxed(0x0, ovl->regs + DISP_REG_OVL_EN);
|
||||
if (ovl->data->smi_id_en) {
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = reg & ~OVL_LAYER_SMI_ID_EN;
|
||||
writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mtk_ovl_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
if (w != 0 && h != 0)
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_ROI_SIZE);
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, 0x0, comp, DISP_REG_OVL_ROI_BGCLR);
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_ROI_BGCLR);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, 0x1, comp, DISP_REG_OVL_RST);
|
||||
mtk_ddp_write(cmdq_pkt, 0x0, comp, DISP_REG_OVL_RST);
|
||||
mtk_ddp_write(cmdq_pkt, 0x1, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RST);
|
||||
mtk_ddp_write(cmdq_pkt, 0x0, &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RST);
|
||||
}
|
||||
|
||||
static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp)
|
||||
unsigned int mtk_ovl_layer_nr(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
return ovl->data->layer_nr;
|
||||
}
|
||||
|
||||
static unsigned int mtk_ovl_supported_rotations(struct mtk_ddp_comp *comp)
|
||||
unsigned int mtk_ovl_supported_rotations(struct device *dev)
|
||||
{
|
||||
return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
|
||||
DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
|
||||
}
|
||||
|
||||
static int mtk_ovl_layer_check(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct mtk_plane_state *mtk_state)
|
||||
int mtk_ovl_layer_check(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *mtk_state)
|
||||
{
|
||||
struct drm_plane_state *state = &mtk_state->base;
|
||||
unsigned int rotation = 0;
|
||||
@ -178,15 +217,15 @@ static int mtk_ovl_layer_check(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_ovl_layer_on(struct device *dev, unsigned int idx,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
unsigned int gmc_thrshd_l;
|
||||
unsigned int gmc_thrshd_h;
|
||||
unsigned int gmc_value;
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, 0x1, comp,
|
||||
mtk_ddp_write(cmdq_pkt, 0x1, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_RDMA_CTRL(idx));
|
||||
gmc_thrshd_l = GMC_THRESHOLD_LOW >>
|
||||
(GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
|
||||
@ -198,17 +237,19 @@ static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
gmc_value = gmc_thrshd_l | gmc_thrshd_l << 8 |
|
||||
gmc_thrshd_h << 16 | gmc_thrshd_h << 24;
|
||||
mtk_ddp_write(cmdq_pkt, gmc_value,
|
||||
comp, DISP_REG_OVL_RDMA_GMC(idx));
|
||||
mtk_ddp_write_mask(cmdq_pkt, BIT(idx), comp,
|
||||
&ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_RDMA_GMC(idx));
|
||||
mtk_ddp_write_mask(cmdq_pkt, BIT(idx), &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_SRC_CON, BIT(idx));
|
||||
}
|
||||
|
||||
static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_ovl_layer_off(struct device *dev, unsigned int idx,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
mtk_ddp_write_mask(cmdq_pkt, 0, comp,
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write_mask(cmdq_pkt, 0, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_SRC_CON, BIT(idx));
|
||||
mtk_ddp_write(cmdq_pkt, 0, comp,
|
||||
mtk_ddp_write(cmdq_pkt, 0, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_RDMA_CTRL(idx));
|
||||
}
|
||||
|
||||
@ -248,11 +289,11 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
struct mtk_plane_pending_state *pending = &state->pending;
|
||||
unsigned int addr = pending->addr;
|
||||
unsigned int pitch = pending->pitch & 0xffff;
|
||||
@ -262,12 +303,12 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
unsigned int con;
|
||||
|
||||
if (!pending->enable) {
|
||||
mtk_ovl_layer_off(comp, idx, cmdq_pkt);
|
||||
mtk_ovl_layer_off(dev, idx, cmdq_pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
con = ovl_fmt_convert(ovl, fmt);
|
||||
if (state->base.fb->format->has_alpha)
|
||||
if (state->base.fb && state->base.fb->format->has_alpha)
|
||||
con |= OVL_CON_AEN | OVL_CON_ALPHA;
|
||||
|
||||
if (pending->rotation & DRM_MODE_REFLECT_Y) {
|
||||
@ -280,76 +321,49 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
addr += pending->pitch - 1;
|
||||
}
|
||||
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, con, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_CON(idx));
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, pitch, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, pitch, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_PITCH(idx));
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, src_size, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_SRC_SIZE(idx));
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, offset, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, offset, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_OFFSET(idx));
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, addr, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs,
|
||||
DISP_REG_OVL_ADDR(ovl, idx));
|
||||
|
||||
mtk_ovl_layer_on(comp, idx, cmdq_pkt);
|
||||
mtk_ovl_layer_on(dev, idx, cmdq_pkt);
|
||||
}
|
||||
|
||||
static void mtk_ovl_bgclr_in_on(struct mtk_ddp_comp *comp)
|
||||
void mtk_ovl_bgclr_in_on(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = reg | OVL_BGCLR_SEL_IN;
|
||||
writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
writel(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
}
|
||||
|
||||
static void mtk_ovl_bgclr_in_off(struct mtk_ddp_comp *comp)
|
||||
void mtk_ovl_bgclr_in_off(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
|
||||
unsigned int reg;
|
||||
|
||||
reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = readl(ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
reg = reg & ~OVL_BGCLR_SEL_IN;
|
||||
writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
writel(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
|
||||
.config = mtk_ovl_config,
|
||||
.start = mtk_ovl_start,
|
||||
.stop = mtk_ovl_stop,
|
||||
.enable_vblank = mtk_ovl_enable_vblank,
|
||||
.disable_vblank = mtk_ovl_disable_vblank,
|
||||
.supported_rotations = mtk_ovl_supported_rotations,
|
||||
.layer_nr = mtk_ovl_layer_nr,
|
||||
.layer_check = mtk_ovl_layer_check,
|
||||
.layer_config = mtk_ovl_layer_config,
|
||||
.bgclr_in_on = mtk_ovl_bgclr_in_on,
|
||||
.bgclr_in_off = mtk_ovl_bgclr_in_off,
|
||||
};
|
||||
|
||||
static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register component %pOF: %d\n",
|
||||
dev->of_node, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_disp_ovl_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
|
||||
mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp);
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_disp_ovl_component_ops = {
|
||||
@ -361,7 +375,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_disp_ovl *priv;
|
||||
int comp_id;
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
@ -373,27 +387,25 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get ovl clk\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "failed to ioremap ovl\n");
|
||||
return PTR_ERR(priv->regs);
|
||||
}
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
|
||||
if (ret)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
priv->data = of_device_get_match_data(dev);
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node,
|
||||
priv->data->layer_nr == 4 ?
|
||||
MTK_DISP_OVL :
|
||||
MTK_DISP_OVL_2L);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
return comp_id;
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
|
||||
&mtk_disp_ovl_funcs);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to initialize component: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
|
||||
@ -412,8 +424,6 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
|
||||
|
||||
static int mtk_disp_ovl_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -431,11 +441,29 @@ static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
|
||||
.fmt_rgb565_is_0 = true,
|
||||
};
|
||||
|
||||
static const struct mtk_disp_ovl_data mt8183_ovl_driver_data = {
|
||||
.addr = DISP_REG_OVL_ADDR_MT8173,
|
||||
.gmc_bits = 10,
|
||||
.layer_nr = 4,
|
||||
.fmt_rgb565_is_0 = true,
|
||||
};
|
||||
|
||||
static const struct mtk_disp_ovl_data mt8183_ovl_2l_driver_data = {
|
||||
.addr = DISP_REG_OVL_ADDR_MT8173,
|
||||
.gmc_bits = 10,
|
||||
.layer_nr = 2,
|
||||
.fmt_rgb565_is_0 = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt2701-disp-ovl",
|
||||
.data = &mt2701_ovl_driver_data},
|
||||
{ .compatible = "mediatek,mt8173-disp-ovl",
|
||||
.data = &mt8173_ovl_driver_data},
|
||||
{ .compatible = "mediatek,mt8183-disp-ovl",
|
||||
.data = &mt8183_ovl_driver_data},
|
||||
{ .compatible = "mediatek,mt8183-disp-ovl-2l",
|
||||
.data = &mt8183_ovl_2l_driver_data},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
@ -61,83 +62,105 @@ struct mtk_disp_rdma_data {
|
||||
* @data: local driver data
|
||||
*/
|
||||
struct mtk_disp_rdma {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct drm_crtc *crtc;
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
const struct mtk_disp_rdma_data *data;
|
||||
void (*vblank_cb)(void *data);
|
||||
void *vblank_cb_data;
|
||||
u32 fifo_size;
|
||||
};
|
||||
|
||||
static inline struct mtk_disp_rdma *comp_to_rdma(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
return container_of(comp, struct mtk_disp_rdma, ddp_comp);
|
||||
}
|
||||
|
||||
static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct mtk_disp_rdma *priv = dev_id;
|
||||
struct mtk_ddp_comp *rdma = &priv->ddp_comp;
|
||||
|
||||
/* Clear frame completion interrupt */
|
||||
writel(0x0, rdma->regs + DISP_REG_RDMA_INT_STATUS);
|
||||
writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
|
||||
|
||||
if (!priv->crtc)
|
||||
if (!priv->vblank_cb)
|
||||
return IRQ_NONE;
|
||||
|
||||
mtk_crtc_ddp_irq(priv->crtc, rdma);
|
||||
priv->vblank_cb(priv->vblank_cb_data);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void rdma_update_bits(struct mtk_ddp_comp *comp, unsigned int reg,
|
||||
static void rdma_update_bits(struct device *dev, unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
unsigned int tmp = readl(comp->regs + reg);
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
unsigned int tmp = readl(rdma->regs + reg);
|
||||
|
||||
tmp = (tmp & ~mask) | (val & mask);
|
||||
writel(tmp, comp->regs + reg);
|
||||
writel(tmp, rdma->regs + reg);
|
||||
}
|
||||
|
||||
static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc *crtc)
|
||||
void mtk_rdma_enable_vblank(struct device *dev,
|
||||
void (*vblank_cb)(void *),
|
||||
void *vblank_cb_data)
|
||||
{
|
||||
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
|
||||
rdma->crtc = crtc;
|
||||
rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
|
||||
rdma->vblank_cb = vblank_cb;
|
||||
rdma->vblank_cb_data = vblank_cb_data;
|
||||
rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
|
||||
RDMA_FRAME_END_INT);
|
||||
}
|
||||
|
||||
static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp)
|
||||
void mtk_rdma_disable_vblank(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
|
||||
rdma->crtc = NULL;
|
||||
rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
|
||||
rdma->vblank_cb = NULL;
|
||||
rdma->vblank_cb_data = NULL;
|
||||
rdma_update_bits(dev, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
|
||||
}
|
||||
|
||||
static void mtk_rdma_start(struct mtk_ddp_comp *comp)
|
||||
int mtk_rdma_clk_enable(struct device *dev)
|
||||
{
|
||||
rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN,
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(rdma->clk);
|
||||
}
|
||||
|
||||
void mtk_rdma_clk_disable(struct device *dev)
|
||||
{
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(rdma->clk);
|
||||
}
|
||||
|
||||
void mtk_rdma_start(struct device *dev)
|
||||
{
|
||||
rdma_update_bits(dev, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN,
|
||||
RDMA_ENGINE_EN);
|
||||
}
|
||||
|
||||
static void mtk_rdma_stop(struct mtk_ddp_comp *comp)
|
||||
void mtk_rdma_stop(struct device *dev)
|
||||
{
|
||||
rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN, 0);
|
||||
rdma_update_bits(dev, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN, 0);
|
||||
}
|
||||
|
||||
static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
|
||||
unsigned int height, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_rdma_config(struct device *dev, unsigned int width,
|
||||
unsigned int height, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
unsigned int threshold;
|
||||
unsigned int reg;
|
||||
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
u32 rdma_fifo_size;
|
||||
|
||||
mtk_ddp_write_mask(cmdq_pkt, width, comp,
|
||||
mtk_ddp_write_mask(cmdq_pkt, width, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_REG_RDMA_SIZE_CON_0, 0xfff);
|
||||
mtk_ddp_write_mask(cmdq_pkt, height, comp,
|
||||
mtk_ddp_write_mask(cmdq_pkt, height, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_REG_RDMA_SIZE_CON_1, 0xfffff);
|
||||
|
||||
if (rdma->fifo_size)
|
||||
rdma_fifo_size = rdma->fifo_size;
|
||||
else
|
||||
rdma_fifo_size = RDMA_FIFO_SIZE(rdma);
|
||||
|
||||
/*
|
||||
* Enable FIFO underflow since DSI and DPI can't be blocked.
|
||||
* Keep the FIFO pseudo size reset default of 8 KiB. Set the
|
||||
@ -146,9 +169,9 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
|
||||
*/
|
||||
threshold = width * height * vrefresh * 4 * 7 / 1000000;
|
||||
reg = RDMA_FIFO_UNDERFLOW_EN |
|
||||
RDMA_FIFO_PSEUDO_SIZE(RDMA_FIFO_SIZE(rdma)) |
|
||||
RDMA_FIFO_PSEUDO_SIZE(rdma_fifo_size) |
|
||||
RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
|
||||
mtk_ddp_write(cmdq_pkt, reg, comp, DISP_REG_RDMA_FIFO_CON);
|
||||
mtk_ddp_write(cmdq_pkt, reg, &rdma->cmdq_reg, rdma->regs, DISP_REG_RDMA_FIFO_CON);
|
||||
}
|
||||
|
||||
static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma,
|
||||
@ -188,16 +211,16 @@ static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma,
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int mtk_rdma_layer_nr(struct mtk_ddp_comp *comp)
|
||||
unsigned int mtk_rdma_layer_nr(struct device *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
void mtk_rdma_layer_config(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_disp_rdma *rdma = comp_to_rdma(comp);
|
||||
struct mtk_disp_rdma *rdma = dev_get_drvdata(dev);
|
||||
struct mtk_plane_pending_state *pending = &state->pending;
|
||||
unsigned int addr = pending->addr;
|
||||
unsigned int pitch = pending->pitch & 0xffff;
|
||||
@ -205,53 +228,34 @@ static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
unsigned int con;
|
||||
|
||||
con = rdma_fmt_convert(rdma, fmt);
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, con, comp, DISP_RDMA_MEM_CON);
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, con, &rdma->cmdq_reg, rdma->regs, DISP_RDMA_MEM_CON);
|
||||
|
||||
if (fmt == DRM_FORMAT_UYVY || fmt == DRM_FORMAT_YUYV) {
|
||||
mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_ENABLE, comp,
|
||||
mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_ENABLE, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_REG_RDMA_SIZE_CON_0,
|
||||
RDMA_MATRIX_ENABLE);
|
||||
mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_INT_MTX_BT601_to_RGB,
|
||||
comp, DISP_REG_RDMA_SIZE_CON_0,
|
||||
&rdma->cmdq_reg, rdma->regs, DISP_REG_RDMA_SIZE_CON_0,
|
||||
RDMA_MATRIX_INT_MTX_SEL);
|
||||
} else {
|
||||
mtk_ddp_write_mask(cmdq_pkt, 0, comp,
|
||||
mtk_ddp_write_mask(cmdq_pkt, 0, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_REG_RDMA_SIZE_CON_0,
|
||||
RDMA_MATRIX_ENABLE);
|
||||
}
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, addr, comp, DISP_RDMA_MEM_START_ADDR);
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, pitch, comp, DISP_RDMA_MEM_SRC_PITCH);
|
||||
mtk_ddp_write(cmdq_pkt, RDMA_MEM_GMC, comp,
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, addr, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_RDMA_MEM_START_ADDR);
|
||||
mtk_ddp_write_relaxed(cmdq_pkt, pitch, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_RDMA_MEM_SRC_PITCH);
|
||||
mtk_ddp_write(cmdq_pkt, RDMA_MEM_GMC, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_RDMA_MEM_GMC_SETTING_0);
|
||||
mtk_ddp_write_mask(cmdq_pkt, RDMA_MODE_MEMORY, comp,
|
||||
mtk_ddp_write_mask(cmdq_pkt, RDMA_MODE_MEMORY, &rdma->cmdq_reg, rdma->regs,
|
||||
DISP_REG_RDMA_GLOBAL_CON, RDMA_MODE_MEMORY);
|
||||
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = {
|
||||
.config = mtk_rdma_config,
|
||||
.start = mtk_rdma_start,
|
||||
.stop = mtk_rdma_stop,
|
||||
.enable_vblank = mtk_rdma_enable_vblank,
|
||||
.disable_vblank = mtk_rdma_disable_vblank,
|
||||
.layer_nr = mtk_rdma_layer_nr,
|
||||
.layer_config = mtk_rdma_layer_config,
|
||||
};
|
||||
|
||||
static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register component %pOF: %d\n",
|
||||
dev->of_node, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -259,10 +263,6 @@ static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
|
||||
static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
|
||||
mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp);
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_disp_rdma_component_ops = {
|
||||
@ -274,7 +274,7 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_disp_rdma *priv;
|
||||
int comp_id;
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
@ -286,25 +286,37 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_RDMA);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
return comp_id;
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get rdma clk\n");
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
|
||||
&mtk_disp_rdma_funcs);
|
||||
if (ret) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to initialize component: %d\n",
|
||||
ret);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->regs)) {
|
||||
dev_err(dev, "failed to ioremap rdma\n");
|
||||
return PTR_ERR(priv->regs);
|
||||
}
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
|
||||
if (ret)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
if (of_find_property(dev->of_node, "mediatek,rdma-fifo-size", &ret)) {
|
||||
ret = of_property_read_u32(dev->of_node,
|
||||
"mediatek,rdma-fifo-size",
|
||||
&priv->fifo_size);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get rdma fifo size\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable and clear pending interrupts */
|
||||
writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_ENABLE);
|
||||
writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_STATUS);
|
||||
writel(0x0, priv->regs + DISP_REG_RDMA_INT_ENABLE);
|
||||
writel(0x0, priv->regs + DISP_REG_RDMA_INT_STATUS);
|
||||
|
||||
ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
|
||||
IRQF_TRIGGER_NONE, dev_name(dev), priv);
|
||||
@ -339,11 +351,17 @@ static const struct mtk_disp_rdma_data mt8173_rdma_driver_data = {
|
||||
.fifo_size = SZ_8K,
|
||||
};
|
||||
|
||||
static const struct mtk_disp_rdma_data mt8183_rdma_driver_data = {
|
||||
.fifo_size = 5 * SZ_1K,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt2701-disp-rdma",
|
||||
.data = &mt2701_rdma_driver_data},
|
||||
{ .compatible = "mediatek,mt8173-disp-rdma",
|
||||
.data = &mt8173_rdma_driver_data},
|
||||
{ .compatible = "mediatek,mt8183-disp-rdma",
|
||||
.data = &mt8183_rdma_driver_data},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
|
||||
|
@ -20,10 +20,12 @@
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_bridge_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_dpi_regs.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
@ -62,10 +64,10 @@ enum mtk_dpi_out_color_format {
|
||||
};
|
||||
|
||||
struct mtk_dpi {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct drm_encoder encoder;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *next_bridge;
|
||||
struct drm_connector *connector;
|
||||
void __iomem *regs;
|
||||
struct device *dev;
|
||||
struct clk *engine_clk;
|
||||
@ -562,53 +564,50 @@ static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = {
|
||||
.enable = mtk_dpi_bridge_enable,
|
||||
};
|
||||
|
||||
static void mtk_dpi_start(struct mtk_ddp_comp *comp)
|
||||
void mtk_dpi_start(struct device *dev)
|
||||
{
|
||||
struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
|
||||
struct mtk_dpi *dpi = dev_get_drvdata(dev);
|
||||
|
||||
mtk_dpi_power_on(dpi);
|
||||
}
|
||||
|
||||
static void mtk_dpi_stop(struct mtk_ddp_comp *comp)
|
||||
void mtk_dpi_stop(struct device *dev)
|
||||
{
|
||||
struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
|
||||
struct mtk_dpi *dpi = dev_get_drvdata(dev);
|
||||
|
||||
mtk_dpi_power_off(dpi);
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = {
|
||||
.start = mtk_dpi_start,
|
||||
.stop = mtk_dpi_stop,
|
||||
};
|
||||
|
||||
static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
struct mtk_dpi *dpi = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
int ret;
|
||||
|
||||
ret = mtk_ddp_comp_register(drm_dev, &dpi->ddp_comp);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register component %pOF: %d\n",
|
||||
dev->of_node, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_simple_encoder_init(drm_dev, &dpi->encoder,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize decoder: %d\n", ret);
|
||||
goto err_unregister;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->ddp_comp);
|
||||
dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->dev);
|
||||
|
||||
ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL, 0);
|
||||
ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL,
|
||||
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to attach bridge: %d\n", ret);
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
dpi->connector = drm_bridge_connector_init(drm_dev, &dpi->encoder);
|
||||
if (IS_ERR(dpi->connector)) {
|
||||
dev_err(dev, "Unable to create bridge connector\n");
|
||||
ret = PTR_ERR(dpi->connector);
|
||||
goto err_cleanup;
|
||||
}
|
||||
drm_connector_attach_encoder(dpi->connector, &dpi->encoder);
|
||||
|
||||
dpi->bit_num = MTK_DPI_OUT_BIT_NUM_8BITS;
|
||||
dpi->channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB;
|
||||
dpi->yc_map = MTK_DPI_OUT_YC_MAP_RGB;
|
||||
@ -618,8 +617,6 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
|
||||
|
||||
err_cleanup:
|
||||
drm_encoder_cleanup(&dpi->encoder);
|
||||
err_unregister:
|
||||
mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -627,10 +624,8 @@ static void mtk_dpi_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct mtk_dpi *dpi = dev_get_drvdata(dev);
|
||||
struct drm_device *drm_dev = data;
|
||||
|
||||
drm_encoder_cleanup(&dpi->encoder);
|
||||
mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp);
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_dpi_component_ops = {
|
||||
@ -691,7 +686,6 @@ static int mtk_dpi_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_dpi *dpi;
|
||||
struct resource *mem;
|
||||
int comp_id;
|
||||
int ret;
|
||||
|
||||
dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
|
||||
@ -769,19 +763,6 @@ static int mtk_dpi_probe(struct platform_device *pdev)
|
||||
|
||||
dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node);
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
return comp_id;
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev, dev->of_node, &dpi->ddp_comp, comp_id,
|
||||
&mtk_dpi_funcs);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize component: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dpi);
|
||||
|
||||
dpi->bridge.funcs = &mtk_dpi_bridge_funcs;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
#include <linux/soc/mediatek/mtk-mmsys.h>
|
||||
#include <linux/soc/mediatek/mtk-mutex.h>
|
||||
|
||||
#include <asm/barrier.h>
|
||||
#include <soc/mediatek/smi.h>
|
||||
@ -19,7 +20,6 @@
|
||||
|
||||
#include "mtk_drm_drv.h"
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
#include "mtk_drm_gem.h"
|
||||
#include "mtk_drm_plane.h"
|
||||
@ -55,7 +55,7 @@ struct mtk_drm_crtc {
|
||||
#endif
|
||||
|
||||
struct device *mmsys_dev;
|
||||
struct mtk_disp_mutex *mutex;
|
||||
struct mtk_mutex *mutex;
|
||||
unsigned int ddp_comp_nr;
|
||||
struct mtk_ddp_comp **ddp_comp;
|
||||
|
||||
@ -107,7 +107,7 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
|
||||
mtk_disp_mutex_put(mtk_crtc->mutex);
|
||||
mtk_mutex_put(mtk_crtc->mutex);
|
||||
|
||||
drm_crtc_cleanup(crtc);
|
||||
}
|
||||
@ -169,31 +169,13 @@ static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
state->pending_config = true;
|
||||
}
|
||||
|
||||
static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
|
||||
mtk_ddp_comp_enable_vblank(comp, &mtk_crtc->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
|
||||
mtk_ddp_comp_disable_vblank(comp);
|
||||
}
|
||||
|
||||
static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
|
||||
ret = clk_prepare_enable(mtk_crtc->ddp_comp[i]->clk);
|
||||
ret = mtk_ddp_comp_clk_enable(mtk_crtc->ddp_comp[i]);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
|
||||
goto err;
|
||||
@ -203,7 +185,7 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
|
||||
return 0;
|
||||
err:
|
||||
while (--i >= 0)
|
||||
clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
|
||||
mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -212,7 +194,7 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
|
||||
clk_disable_unprepare(mtk_crtc->ddp_comp[i]->clk);
|
||||
mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
|
||||
}
|
||||
|
||||
static
|
||||
@ -283,7 +265,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mtk_disp_mutex_prepare(mtk_crtc->mutex);
|
||||
ret = mtk_mutex_prepare(mtk_crtc->mutex);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
|
||||
goto err_pm_runtime_put;
|
||||
@ -299,11 +281,11 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
|
||||
mtk_crtc->ddp_comp[i]->id,
|
||||
mtk_crtc->ddp_comp[i + 1]->id);
|
||||
mtk_disp_mutex_add_comp(mtk_crtc->mutex,
|
||||
mtk_mutex_add_comp(mtk_crtc->mutex,
|
||||
mtk_crtc->ddp_comp[i]->id);
|
||||
}
|
||||
mtk_disp_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
|
||||
mtk_disp_mutex_enable(mtk_crtc->mutex);
|
||||
mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
|
||||
mtk_mutex_enable(mtk_crtc->mutex);
|
||||
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
|
||||
@ -332,7 +314,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
|
||||
return 0;
|
||||
|
||||
err_mutex_unprepare:
|
||||
mtk_disp_mutex_unprepare(mtk_crtc->mutex);
|
||||
mtk_mutex_unprepare(mtk_crtc->mutex);
|
||||
err_pm_runtime_put:
|
||||
pm_runtime_put(crtc->dev->dev);
|
||||
return ret;
|
||||
@ -351,19 +333,19 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
|
||||
}
|
||||
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
|
||||
mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
|
||||
mtk_mutex_remove_comp(mtk_crtc->mutex,
|
||||
mtk_crtc->ddp_comp[i]->id);
|
||||
mtk_disp_mutex_disable(mtk_crtc->mutex);
|
||||
mtk_mutex_disable(mtk_crtc->mutex);
|
||||
for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
|
||||
mtk_mmsys_ddp_disconnect(mtk_crtc->mmsys_dev,
|
||||
mtk_crtc->ddp_comp[i]->id,
|
||||
mtk_crtc->ddp_comp[i + 1]->id);
|
||||
mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
|
||||
mtk_mutex_remove_comp(mtk_crtc->mutex,
|
||||
mtk_crtc->ddp_comp[i]->id);
|
||||
}
|
||||
mtk_disp_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
|
||||
mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
|
||||
mtk_crtc_ddp_clk_disable(mtk_crtc);
|
||||
mtk_disp_mutex_unprepare(mtk_crtc->mutex);
|
||||
mtk_mutex_unprepare(mtk_crtc->mutex);
|
||||
|
||||
pm_runtime_put(drm->dev);
|
||||
|
||||
@ -475,9 +457,9 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
|
||||
mtk_crtc->pending_async_planes = true;
|
||||
|
||||
if (priv->data->shadow_register) {
|
||||
mtk_disp_mutex_acquire(mtk_crtc->mutex);
|
||||
mtk_mutex_acquire(mtk_crtc->mutex);
|
||||
mtk_crtc_ddp_config(crtc, NULL);
|
||||
mtk_disp_mutex_release(mtk_crtc->mutex);
|
||||
mtk_mutex_release(mtk_crtc->mutex);
|
||||
}
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (mtk_crtc->cmdq_client) {
|
||||
@ -493,6 +475,40 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
|
||||
mutex_unlock(&mtk_crtc->hw_lock);
|
||||
}
|
||||
|
||||
static void mtk_crtc_ddp_irq(void *data)
|
||||
{
|
||||
struct drm_crtc *crtc = data;
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_drm_private *priv = crtc->dev->dev_private;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
|
||||
#else
|
||||
if (!priv->data->shadow_register)
|
||||
#endif
|
||||
mtk_crtc_ddp_config(crtc, NULL);
|
||||
|
||||
mtk_drm_finish_page_flip(mtk_crtc);
|
||||
}
|
||||
|
||||
static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
|
||||
mtk_ddp_comp_enable_vblank(comp, mtk_crtc_ddp_irq, &mtk_crtc->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
|
||||
|
||||
mtk_ddp_comp_disable_vblank(comp);
|
||||
}
|
||||
|
||||
int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
|
||||
struct mtk_plane_state *state)
|
||||
{
|
||||
@ -661,21 +677,6 @@ err_cleanup_crtc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp)
|
||||
{
|
||||
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
|
||||
struct mtk_drm_private *priv = crtc->dev->dev_private;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
|
||||
#else
|
||||
if (!priv->data->shadow_register)
|
||||
#endif
|
||||
mtk_crtc_ddp_config(crtc, NULL);
|
||||
|
||||
mtk_drm_finish_page_flip(mtk_crtc);
|
||||
}
|
||||
|
||||
static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc,
|
||||
int comp_idx)
|
||||
{
|
||||
@ -771,7 +772,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
if (!mtk_crtc->ddp_comp)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_crtc->mutex = mtk_disp_mutex_get(priv->mutex_dev, pipe);
|
||||
mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
|
||||
if (IS_ERR(mtk_crtc->mutex)) {
|
||||
ret = PTR_ERR(mtk_crtc->mutex);
|
||||
dev_err(dev, "Failed to get mutex: %d\n", ret);
|
||||
@ -784,7 +785,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
struct device_node *node;
|
||||
|
||||
node = priv->comp_node[comp_id];
|
||||
comp = priv->ddp_comp[comp_id];
|
||||
comp = &priv->ddp_comp[comp_id];
|
||||
if (!comp) {
|
||||
dev_err(dev, "Component %pOF not initialized\n", node);
|
||||
ret = -ENODEV;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#define MTK_MIN_BPC 3
|
||||
|
||||
void mtk_drm_crtc_commit(struct drm_crtc *crtc);
|
||||
void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp);
|
||||
int mtk_drm_crtc_create(struct drm_device *drm_dev,
|
||||
const enum mtk_ddp_comp_id *path,
|
||||
unsigned int path_len);
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef MTK_DRM_DDP_H
|
||||
#define MTK_DRM_DDP_H
|
||||
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
struct regmap;
|
||||
struct device;
|
||||
struct mtk_disp_mutex;
|
||||
|
||||
struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id);
|
||||
int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex);
|
||||
void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id);
|
||||
void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex);
|
||||
void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex);
|
||||
void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id);
|
||||
void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex);
|
||||
void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex);
|
||||
void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex);
|
||||
void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex);
|
||||
|
||||
#endif /* MTK_DRM_DDP_H */
|
@ -9,12 +9,12 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_drv.h"
|
||||
#include "mtk_drm_plane.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
@ -35,31 +35,13 @@
|
||||
#define DISP_AAL_EN 0x0000
|
||||
#define DISP_AAL_SIZE 0x0030
|
||||
|
||||
#define DISP_CCORR_EN 0x0000
|
||||
#define CCORR_EN BIT(0)
|
||||
#define DISP_CCORR_CFG 0x0020
|
||||
#define CCORR_RELAY_MODE BIT(0)
|
||||
#define CCORR_ENGINE_EN BIT(1)
|
||||
#define CCORR_GAMMA_OFF BIT(2)
|
||||
#define CCORR_WGAMUT_SRC_CLIP BIT(3)
|
||||
#define DISP_CCORR_SIZE 0x0030
|
||||
#define DISP_CCORR_COEF_0 0x0080
|
||||
#define DISP_CCORR_COEF_1 0x0084
|
||||
#define DISP_CCORR_COEF_2 0x0088
|
||||
#define DISP_CCORR_COEF_3 0x008C
|
||||
#define DISP_CCORR_COEF_4 0x0090
|
||||
|
||||
#define DISP_DITHER_EN 0x0000
|
||||
#define DITHER_EN BIT(0)
|
||||
#define DISP_DITHER_CFG 0x0020
|
||||
#define DITHER_RELAY_MODE BIT(0)
|
||||
#define DITHER_ENGINE_EN BIT(1)
|
||||
#define DISP_DITHER_SIZE 0x0030
|
||||
|
||||
#define DISP_GAMMA_EN 0x0000
|
||||
#define DISP_GAMMA_CFG 0x0020
|
||||
#define DISP_GAMMA_SIZE 0x0030
|
||||
#define DISP_GAMMA_LUT 0x0700
|
||||
|
||||
#define LUT_10BIT_MASK 0x03ff
|
||||
|
||||
#define OD_RELAYMODE BIT(0)
|
||||
@ -68,9 +50,6 @@
|
||||
|
||||
#define AAL_EN BIT(0)
|
||||
|
||||
#define GAMMA_EN BIT(0)
|
||||
#define GAMMA_LUT_EN BIT(1)
|
||||
|
||||
#define DISP_DITHERING BIT(2)
|
||||
#define DITHER_LSB_ERR_SHIFT_R(x) (((x) & 0x7) << 28)
|
||||
#define DITHER_OVFLW_BIT_R(x) (((x) & 0x7) << 24)
|
||||
@ -86,262 +65,233 @@
|
||||
#define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4)
|
||||
#define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0)
|
||||
|
||||
struct mtk_ddp_comp_dev {
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
};
|
||||
|
||||
void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
|
||||
struct mtk_ddp_comp *comp, unsigned int offset)
|
||||
struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
|
||||
unsigned int offset)
|
||||
{
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (cmdq_pkt)
|
||||
cmdq_pkt_write(cmdq_pkt, comp->subsys,
|
||||
comp->regs_pa + offset, value);
|
||||
cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
|
||||
cmdq_reg->offset + offset, value);
|
||||
else
|
||||
#endif
|
||||
writel(value, comp->regs + offset);
|
||||
writel(value, regs + offset);
|
||||
}
|
||||
|
||||
void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
|
||||
struct mtk_ddp_comp *comp,
|
||||
struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
|
||||
unsigned int offset)
|
||||
{
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (cmdq_pkt)
|
||||
cmdq_pkt_write(cmdq_pkt, comp->subsys,
|
||||
comp->regs_pa + offset, value);
|
||||
cmdq_pkt_write(cmdq_pkt, cmdq_reg->subsys,
|
||||
cmdq_reg->offset + offset, value);
|
||||
else
|
||||
#endif
|
||||
writel_relaxed(value, comp->regs + offset);
|
||||
writel_relaxed(value, regs + offset);
|
||||
}
|
||||
|
||||
void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt,
|
||||
unsigned int value,
|
||||
struct mtk_ddp_comp *comp,
|
||||
unsigned int offset,
|
||||
unsigned int mask)
|
||||
void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
|
||||
struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
|
||||
unsigned int offset, unsigned int mask)
|
||||
{
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (cmdq_pkt) {
|
||||
cmdq_pkt_write_mask(cmdq_pkt, comp->subsys,
|
||||
comp->regs_pa + offset, value, mask);
|
||||
cmdq_pkt_write_mask(cmdq_pkt, cmdq_reg->subsys,
|
||||
cmdq_reg->offset + offset, value, mask);
|
||||
} else {
|
||||
#endif
|
||||
u32 tmp = readl(comp->regs + offset);
|
||||
u32 tmp = readl(regs + offset);
|
||||
|
||||
tmp = (tmp & ~mask) | (value & mask);
|
||||
writel(tmp, comp->regs + offset);
|
||||
writel(tmp, regs + offset);
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
|
||||
unsigned int CFG, struct cmdq_pkt *cmdq_pkt)
|
||||
static int mtk_ddp_clk_enable(struct device *dev)
|
||||
{
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
return clk_prepare_enable(priv->clk);
|
||||
}
|
||||
|
||||
static void mtk_ddp_clk_disable(struct device *dev)
|
||||
{
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(priv->clk);
|
||||
}
|
||||
|
||||
void mtk_dither_set_common(void __iomem *regs, struct cmdq_client_reg *cmdq_reg,
|
||||
unsigned int bpc, unsigned int cfg,
|
||||
unsigned int dither_en, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
/* If bpc equal to 0, the dithering function didn't be enabled */
|
||||
if (bpc == 0)
|
||||
return;
|
||||
|
||||
if (bpc >= MTK_MIN_BPC) {
|
||||
mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_5);
|
||||
mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_7);
|
||||
mtk_ddp_write(cmdq_pkt, 0, cmdq_reg, regs, DISP_DITHER_5);
|
||||
mtk_ddp_write(cmdq_pkt, 0, cmdq_reg, regs, DISP_DITHER_7);
|
||||
mtk_ddp_write(cmdq_pkt,
|
||||
DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
|
||||
DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
|
||||
DITHER_NEW_BIT_MODE,
|
||||
comp, DISP_DITHER_15);
|
||||
cmdq_reg, regs, DISP_DITHER_15);
|
||||
mtk_ddp_write(cmdq_pkt,
|
||||
DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
|
||||
DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
|
||||
DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
|
||||
DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
|
||||
comp, DISP_DITHER_16);
|
||||
mtk_ddp_write(cmdq_pkt, DISP_DITHERING, comp, CFG);
|
||||
cmdq_reg, regs, DISP_DITHER_16);
|
||||
mtk_ddp_write(cmdq_pkt, dither_en, cmdq_reg, regs, cfg);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
static void mtk_dither_set(struct device *dev, unsigned int bpc,
|
||||
unsigned int cfg, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, cfg,
|
||||
DISP_DITHERING, cmdq_pkt);
|
||||
}
|
||||
|
||||
static void mtk_od_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
mtk_ddp_write(cmdq_pkt, w << 16 | h, comp, DISP_OD_SIZE);
|
||||
mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, comp, DISP_OD_CFG);
|
||||
mtk_dither_set(comp, bpc, DISP_OD_CFG, cmdq_pkt);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_OD_SIZE);
|
||||
mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, &priv->cmdq_reg, priv->regs, DISP_OD_CFG);
|
||||
mtk_dither_set(dev, bpc, DISP_OD_CFG, cmdq_pkt);
|
||||
}
|
||||
|
||||
static void mtk_od_start(struct mtk_ddp_comp *comp)
|
||||
static void mtk_od_start(struct device *dev)
|
||||
{
|
||||
writel(1, comp->regs + DISP_OD_EN);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
writel(1, priv->regs + DISP_OD_EN);
|
||||
}
|
||||
|
||||
static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
|
||||
static void mtk_ufoe_start(struct device *dev)
|
||||
{
|
||||
writel(UFO_BYPASS, comp->regs + DISP_REG_UFO_START);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
writel(UFO_BYPASS, priv->regs + DISP_REG_UFO_START);
|
||||
}
|
||||
|
||||
static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
static void mtk_aal_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_AAL_SIZE);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_SIZE);
|
||||
}
|
||||
|
||||
static void mtk_aal_start(struct mtk_ddp_comp *comp)
|
||||
static void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
|
||||
{
|
||||
writel(AAL_EN, comp->regs + DISP_AAL_EN);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
mtk_gamma_set_common(priv->regs, state);
|
||||
}
|
||||
|
||||
static void mtk_aal_stop(struct mtk_ddp_comp *comp)
|
||||
static void mtk_aal_start(struct device *dev)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_AAL_EN);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
writel(AAL_EN, priv->regs + DISP_AAL_EN);
|
||||
}
|
||||
|
||||
static void mtk_ccorr_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
static void mtk_aal_stop(struct device *dev)
|
||||
{
|
||||
mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_CCORR_SIZE);
|
||||
mtk_ddp_write(cmdq_pkt, CCORR_ENGINE_EN, comp, DISP_CCORR_CFG);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
writel_relaxed(0x0, priv->regs + DISP_AAL_EN);
|
||||
}
|
||||
|
||||
static void mtk_ccorr_start(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel(CCORR_EN, comp->regs + DISP_CCORR_EN);
|
||||
}
|
||||
|
||||
static void mtk_ccorr_stop(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_CCORR_EN);
|
||||
}
|
||||
|
||||
/* Converts a DRM S31.32 value to the HW S1.10 format. */
|
||||
static u16 mtk_ctm_s31_32_to_s1_10(u64 in)
|
||||
{
|
||||
u16 r;
|
||||
|
||||
/* Sign bit. */
|
||||
r = in & BIT_ULL(63) ? BIT(11) : 0;
|
||||
|
||||
if ((in & GENMASK_ULL(62, 33)) > 0) {
|
||||
/* identity value 0x100000000 -> 0x400, */
|
||||
/* if bigger this, set it to max 0x7ff. */
|
||||
r |= GENMASK(10, 0);
|
||||
} else {
|
||||
/* take the 11 most important bits. */
|
||||
r |= (in >> 22) & GENMASK(10, 0);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void mtk_ccorr_ctm_set(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct drm_property_blob *blob = state->ctm;
|
||||
struct drm_color_ctm *ctm;
|
||||
const u64 *input;
|
||||
uint16_t coeffs[9] = { 0 };
|
||||
int i;
|
||||
struct cmdq_pkt *cmdq_pkt = NULL;
|
||||
|
||||
if (!blob)
|
||||
return;
|
||||
|
||||
ctm = (struct drm_color_ctm *)blob->data;
|
||||
input = ctm->matrix;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(coeffs); i++)
|
||||
coeffs[i] = mtk_ctm_s31_32_to_s1_10(input[i]);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[0] << 16 | coeffs[1],
|
||||
comp, DISP_CCORR_COEF_0);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[2] << 16 | coeffs[3],
|
||||
comp, DISP_CCORR_COEF_1);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[4] << 16 | coeffs[5],
|
||||
comp, DISP_CCORR_COEF_2);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[6] << 16 | coeffs[7],
|
||||
comp, DISP_CCORR_COEF_3);
|
||||
mtk_ddp_write(cmdq_pkt, coeffs[8] << 16,
|
||||
comp, DISP_CCORR_COEF_4);
|
||||
}
|
||||
|
||||
static void mtk_dither_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
static void mtk_dither_config(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_DITHER_SIZE);
|
||||
mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, comp, DISP_DITHER_CFG);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs, DISP_DITHER_SIZE);
|
||||
mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, &priv->cmdq_reg, priv->regs, DISP_DITHER_CFG);
|
||||
mtk_dither_set_common(priv->regs, &priv->cmdq_reg, bpc, DISP_DITHER_CFG,
|
||||
DITHER_ENGINE_EN, cmdq_pkt);
|
||||
}
|
||||
|
||||
static void mtk_dither_start(struct mtk_ddp_comp *comp)
|
||||
static void mtk_dither_start(struct device *dev)
|
||||
{
|
||||
writel(DITHER_EN, comp->regs + DISP_DITHER_EN);
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
writel(DITHER_EN, priv->regs + DISP_DITHER_EN);
|
||||
}
|
||||
|
||||
static void mtk_dither_stop(struct mtk_ddp_comp *comp)
|
||||
static void mtk_dither_stop(struct device *dev)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_DITHER_EN);
|
||||
}
|
||||
struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
|
||||
|
||||
static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_GAMMA_SIZE);
|
||||
mtk_dither_set(comp, bpc, DISP_GAMMA_CFG, cmdq_pkt);
|
||||
}
|
||||
|
||||
static void mtk_gamma_start(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel(GAMMA_EN, comp->regs + DISP_GAMMA_EN);
|
||||
}
|
||||
|
||||
static void mtk_gamma_stop(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
writel_relaxed(0x0, comp->regs + DISP_GAMMA_EN);
|
||||
}
|
||||
|
||||
static void mtk_gamma_set(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
unsigned int i, reg;
|
||||
struct drm_color_lut *lut;
|
||||
void __iomem *lut_base;
|
||||
u32 word;
|
||||
|
||||
if (state->gamma_lut) {
|
||||
reg = readl(comp->regs + DISP_GAMMA_CFG);
|
||||
reg = reg | GAMMA_LUT_EN;
|
||||
writel(reg, comp->regs + DISP_GAMMA_CFG);
|
||||
lut_base = comp->regs + DISP_GAMMA_LUT;
|
||||
lut = (struct drm_color_lut *)state->gamma_lut->data;
|
||||
for (i = 0; i < MTK_LUT_SIZE; i++) {
|
||||
word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) +
|
||||
(((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) +
|
||||
((lut[i].blue >> 6) & LUT_10BIT_MASK);
|
||||
writel(word, (lut_base + i * 4));
|
||||
}
|
||||
}
|
||||
writel_relaxed(0x0, priv->regs + DISP_DITHER_EN);
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_aal = {
|
||||
.gamma_set = mtk_gamma_set,
|
||||
.clk_enable = mtk_ddp_clk_enable,
|
||||
.clk_disable = mtk_ddp_clk_disable,
|
||||
.gamma_set = mtk_aal_gamma_set,
|
||||
.config = mtk_aal_config,
|
||||
.start = mtk_aal_start,
|
||||
.stop = mtk_aal_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_ccorr = {
|
||||
.clk_enable = mtk_ccorr_clk_enable,
|
||||
.clk_disable = mtk_ccorr_clk_disable,
|
||||
.config = mtk_ccorr_config,
|
||||
.start = mtk_ccorr_start,
|
||||
.stop = mtk_ccorr_stop,
|
||||
.ctm_set = mtk_ccorr_ctm_set,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_color = {
|
||||
.clk_enable = mtk_color_clk_enable,
|
||||
.clk_disable = mtk_color_clk_disable,
|
||||
.config = mtk_color_config,
|
||||
.start = mtk_color_start,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_dither = {
|
||||
.clk_enable = mtk_ddp_clk_enable,
|
||||
.clk_disable = mtk_ddp_clk_disable,
|
||||
.config = mtk_dither_config,
|
||||
.start = mtk_dither_start,
|
||||
.stop = mtk_dither_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_dpi = {
|
||||
.start = mtk_dpi_start,
|
||||
.stop = mtk_dpi_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_dsi = {
|
||||
.start = mtk_dsi_ddp_start,
|
||||
.stop = mtk_dsi_ddp_stop,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_gamma = {
|
||||
.clk_enable = mtk_gamma_clk_enable,
|
||||
.clk_disable = mtk_gamma_clk_disable,
|
||||
.gamma_set = mtk_gamma_set,
|
||||
.config = mtk_gamma_config,
|
||||
.start = mtk_gamma_start,
|
||||
@ -349,11 +299,43 @@ static const struct mtk_ddp_comp_funcs ddp_gamma = {
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_od = {
|
||||
.clk_enable = mtk_ddp_clk_enable,
|
||||
.clk_disable = mtk_ddp_clk_disable,
|
||||
.config = mtk_od_config,
|
||||
.start = mtk_od_start,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_ovl = {
|
||||
.clk_enable = mtk_ovl_clk_enable,
|
||||
.clk_disable = mtk_ovl_clk_disable,
|
||||
.config = mtk_ovl_config,
|
||||
.start = mtk_ovl_start,
|
||||
.stop = mtk_ovl_stop,
|
||||
.enable_vblank = mtk_ovl_enable_vblank,
|
||||
.disable_vblank = mtk_ovl_disable_vblank,
|
||||
.supported_rotations = mtk_ovl_supported_rotations,
|
||||
.layer_nr = mtk_ovl_layer_nr,
|
||||
.layer_check = mtk_ovl_layer_check,
|
||||
.layer_config = mtk_ovl_layer_config,
|
||||
.bgclr_in_on = mtk_ovl_bgclr_in_on,
|
||||
.bgclr_in_off = mtk_ovl_bgclr_in_off,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_rdma = {
|
||||
.clk_enable = mtk_rdma_clk_enable,
|
||||
.clk_disable = mtk_rdma_clk_disable,
|
||||
.config = mtk_rdma_config,
|
||||
.start = mtk_rdma_start,
|
||||
.stop = mtk_rdma_stop,
|
||||
.enable_vblank = mtk_rdma_enable_vblank,
|
||||
.disable_vblank = mtk_rdma_disable_vblank,
|
||||
.layer_nr = mtk_rdma_layer_nr,
|
||||
.layer_config = mtk_rdma_layer_config,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_comp_funcs ddp_ufoe = {
|
||||
.clk_enable = mtk_ddp_clk_enable,
|
||||
.clk_disable = mtk_ddp_clk_disable,
|
||||
.start = mtk_ufoe_start,
|
||||
};
|
||||
|
||||
@ -387,36 +369,37 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
|
||||
[DDP_COMPONENT_AAL1] = { MTK_DISP_AAL, 1, &ddp_aal },
|
||||
[DDP_COMPONENT_BLS] = { MTK_DISP_BLS, 0, NULL },
|
||||
[DDP_COMPONENT_CCORR] = { MTK_DISP_CCORR, 0, &ddp_ccorr },
|
||||
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, NULL },
|
||||
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, NULL },
|
||||
[DDP_COMPONENT_COLOR0] = { MTK_DISP_COLOR, 0, &ddp_color },
|
||||
[DDP_COMPONENT_COLOR1] = { MTK_DISP_COLOR, 1, &ddp_color },
|
||||
[DDP_COMPONENT_DITHER] = { MTK_DISP_DITHER, 0, &ddp_dither },
|
||||
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, NULL },
|
||||
[DDP_COMPONENT_DPI1] = { MTK_DPI, 1, NULL },
|
||||
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, NULL },
|
||||
[DDP_COMPONENT_DSI1] = { MTK_DSI, 1, NULL },
|
||||
[DDP_COMPONENT_DSI2] = { MTK_DSI, 2, NULL },
|
||||
[DDP_COMPONENT_DSI3] = { MTK_DSI, 3, NULL },
|
||||
[DDP_COMPONENT_DPI0] = { MTK_DPI, 0, &ddp_dpi },
|
||||
[DDP_COMPONENT_DPI1] = { MTK_DPI, 1, &ddp_dpi },
|
||||
[DDP_COMPONENT_DSI0] = { MTK_DSI, 0, &ddp_dsi },
|
||||
[DDP_COMPONENT_DSI1] = { MTK_DSI, 1, &ddp_dsi },
|
||||
[DDP_COMPONENT_DSI2] = { MTK_DSI, 2, &ddp_dsi },
|
||||
[DDP_COMPONENT_DSI3] = { MTK_DSI, 3, &ddp_dsi },
|
||||
[DDP_COMPONENT_GAMMA] = { MTK_DISP_GAMMA, 0, &ddp_gamma },
|
||||
[DDP_COMPONENT_OD0] = { MTK_DISP_OD, 0, &ddp_od },
|
||||
[DDP_COMPONENT_OD1] = { MTK_DISP_OD, 1, &ddp_od },
|
||||
[DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, NULL },
|
||||
[DDP_COMPONENT_OVL1] = { MTK_DISP_OVL, 1, NULL },
|
||||
[DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L, 0, NULL },
|
||||
[DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L, 1, NULL },
|
||||
[DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, &ddp_ovl },
|
||||
[DDP_COMPONENT_OVL1] = { MTK_DISP_OVL, 1, &ddp_ovl },
|
||||
[DDP_COMPONENT_OVL_2L0] = { MTK_DISP_OVL_2L, 0, &ddp_ovl },
|
||||
[DDP_COMPONENT_OVL_2L1] = { MTK_DISP_OVL_2L, 1, &ddp_ovl },
|
||||
[DDP_COMPONENT_PWM0] = { MTK_DISP_PWM, 0, NULL },
|
||||
[DDP_COMPONENT_PWM1] = { MTK_DISP_PWM, 1, NULL },
|
||||
[DDP_COMPONENT_PWM2] = { MTK_DISP_PWM, 2, NULL },
|
||||
[DDP_COMPONENT_RDMA0] = { MTK_DISP_RDMA, 0, NULL },
|
||||
[DDP_COMPONENT_RDMA1] = { MTK_DISP_RDMA, 1, NULL },
|
||||
[DDP_COMPONENT_RDMA2] = { MTK_DISP_RDMA, 2, NULL },
|
||||
[DDP_COMPONENT_RDMA0] = { MTK_DISP_RDMA, 0, &ddp_rdma },
|
||||
[DDP_COMPONENT_RDMA1] = { MTK_DISP_RDMA, 1, &ddp_rdma },
|
||||
[DDP_COMPONENT_RDMA2] = { MTK_DISP_RDMA, 2, &ddp_rdma },
|
||||
[DDP_COMPONENT_UFOE] = { MTK_DISP_UFOE, 0, &ddp_ufoe },
|
||||
[DDP_COMPONENT_WDMA0] = { MTK_DISP_WDMA, 0, NULL },
|
||||
[DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL },
|
||||
};
|
||||
|
||||
static bool mtk_drm_find_comp_in_ddp(struct mtk_ddp_comp ddp_comp,
|
||||
static bool mtk_drm_find_comp_in_ddp(struct device *dev,
|
||||
const enum mtk_ddp_comp_id *path,
|
||||
unsigned int path_len)
|
||||
unsigned int path_len,
|
||||
struct mtk_ddp_comp *ddp_comp)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@ -424,7 +407,7 @@ static bool mtk_drm_find_comp_in_ddp(struct mtk_ddp_comp ddp_comp,
|
||||
return false;
|
||||
|
||||
for (i = 0U; i < path_len; i++)
|
||||
if (ddp_comp.id == path[i])
|
||||
if (dev == ddp_comp[path[i]].dev)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -446,18 +429,19 @@ int mtk_ddp_comp_get_id(struct device_node *node,
|
||||
}
|
||||
|
||||
unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
|
||||
struct mtk_ddp_comp ddp_comp)
|
||||
struct device *dev)
|
||||
{
|
||||
struct mtk_drm_private *private = drm->dev_private;
|
||||
unsigned int ret = 0;
|
||||
|
||||
if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->main_path, private->data->main_len))
|
||||
if (mtk_drm_find_comp_in_ddp(dev, private->data->main_path, private->data->main_len,
|
||||
private->ddp_comp))
|
||||
ret = BIT(0);
|
||||
else if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->ext_path,
|
||||
private->data->ext_len))
|
||||
else if (mtk_drm_find_comp_in_ddp(dev, private->data->ext_path,
|
||||
private->data->ext_len, private->ddp_comp))
|
||||
ret = BIT(1);
|
||||
else if (mtk_drm_find_comp_in_ddp(ddp_comp, private->data->third_path,
|
||||
private->data->third_len))
|
||||
else if (mtk_drm_find_comp_in_ddp(dev, private->data->third_path,
|
||||
private->data->third_len, private->ddp_comp))
|
||||
ret = BIT(2);
|
||||
else
|
||||
DRM_INFO("Failed to find comp in ddp table\n");
|
||||
@ -465,59 +449,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
|
||||
struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id,
|
||||
const struct mtk_ddp_comp_funcs *funcs)
|
||||
static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp *comp,
|
||||
struct device *dev)
|
||||
{
|
||||
enum mtk_ddp_comp_type type;
|
||||
struct device_node *larb_node;
|
||||
struct platform_device *larb_pdev;
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
struct resource res;
|
||||
struct cmdq_client_reg cmdq_reg;
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
type = mtk_ddp_matches[comp_id].type;
|
||||
|
||||
comp->id = comp_id;
|
||||
comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
|
||||
|
||||
if (comp_id == DDP_COMPONENT_BLS ||
|
||||
comp_id == DDP_COMPONENT_DPI0 ||
|
||||
comp_id == DDP_COMPONENT_DPI1 ||
|
||||
comp_id == DDP_COMPONENT_DSI0 ||
|
||||
comp_id == DDP_COMPONENT_DSI1 ||
|
||||
comp_id == DDP_COMPONENT_DSI2 ||
|
||||
comp_id == DDP_COMPONENT_DSI3 ||
|
||||
comp_id == DDP_COMPONENT_PWM0) {
|
||||
comp->regs = NULL;
|
||||
comp->clk = NULL;
|
||||
comp->irq = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
comp->regs = of_iomap(node, 0);
|
||||
comp->irq = of_irq_get(node, 0);
|
||||
comp->clk = of_clk_get(node, 0);
|
||||
if (IS_ERR(comp->clk))
|
||||
return PTR_ERR(comp->clk);
|
||||
|
||||
/* Only DMA capable components need the LARB property */
|
||||
comp->larb_dev = NULL;
|
||||
if (type != MTK_DISP_OVL &&
|
||||
type != MTK_DISP_OVL_2L &&
|
||||
type != MTK_DISP_RDMA &&
|
||||
type != MTK_DISP_WDMA)
|
||||
return 0;
|
||||
|
||||
larb_node = of_parse_phandle(node, "mediatek,larb", 0);
|
||||
if (!larb_node) {
|
||||
dev_err(dev,
|
||||
"Missing mediadek,larb phandle in %pOF node\n", node);
|
||||
dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -528,40 +468,71 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
of_node_put(larb_node);
|
||||
|
||||
comp->larb_dev = &larb_pdev->dev;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
if (of_address_to_resource(node, 0, &res) != 0) {
|
||||
dev_err(dev, "Missing reg in %s node\n", node->full_name);
|
||||
put_device(&larb_pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
|
||||
enum mtk_ddp_comp_id comp_id)
|
||||
{
|
||||
struct platform_device *comp_pdev;
|
||||
enum mtk_ddp_comp_type type;
|
||||
struct mtk_ddp_comp_dev *priv;
|
||||
int ret;
|
||||
|
||||
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
type = mtk_ddp_matches[comp_id].type;
|
||||
|
||||
comp->id = comp_id;
|
||||
comp->funcs = mtk_ddp_matches[comp_id].funcs;
|
||||
comp_pdev = of_find_device_by_node(node);
|
||||
if (!comp_pdev) {
|
||||
DRM_INFO("Waiting for device %s\n", node->full_name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
comp->regs_pa = res.start;
|
||||
comp->dev = &comp_pdev->dev;
|
||||
|
||||
ret = cmdq_dev_get_client_reg(dev, &cmdq_reg, 0);
|
||||
/* Only DMA capable components need the LARB property */
|
||||
if (type == MTK_DISP_OVL ||
|
||||
type == MTK_DISP_OVL_2L ||
|
||||
type == MTK_DISP_RDMA ||
|
||||
type == MTK_DISP_WDMA) {
|
||||
ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type == MTK_DISP_BLS ||
|
||||
type == MTK_DISP_CCORR ||
|
||||
type == MTK_DISP_COLOR ||
|
||||
type == MTK_DISP_GAMMA ||
|
||||
type == MTK_DPI ||
|
||||
type == MTK_DSI ||
|
||||
type == MTK_DISP_OVL ||
|
||||
type == MTK_DISP_OVL_2L ||
|
||||
type == MTK_DISP_PWM ||
|
||||
type == MTK_DISP_RDMA)
|
||||
return 0;
|
||||
|
||||
priv = devm_kzalloc(comp->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->regs = of_iomap(node, 0);
|
||||
priv->clk = of_clk_get(node, 0);
|
||||
if (IS_ERR(priv->clk))
|
||||
return PTR_ERR(priv->clk);
|
||||
|
||||
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
|
||||
ret = cmdq_dev_get_client_reg(comp->dev, &priv->cmdq_reg, 0);
|
||||
if (ret)
|
||||
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
|
||||
else
|
||||
comp->subsys = cmdq_reg.subsys;
|
||||
dev_dbg(comp->dev, "get mediatek,gce-client-reg fail!\n");
|
||||
#endif
|
||||
|
||||
platform_set_drvdata(comp_pdev, priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp)
|
||||
{
|
||||
struct mtk_drm_private *private = drm->dev_private;
|
||||
|
||||
if (private->ddp_comp[comp->id])
|
||||
return -EBUSY;
|
||||
|
||||
private->ddp_comp[comp->id] = comp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp)
|
||||
{
|
||||
struct mtk_drm_private *private = drm->dev_private;
|
||||
|
||||
private->ddp_comp[comp->id] = NULL;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define MTK_DRM_DDP_COMP_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/soc/mediatek/mtk-cmdq.h>
|
||||
#include <linux/soc/mediatek/mtk-mmsys.h>
|
||||
|
||||
struct device;
|
||||
@ -39,79 +40,95 @@ enum mtk_ddp_comp_type {
|
||||
struct mtk_ddp_comp;
|
||||
struct cmdq_pkt;
|
||||
struct mtk_ddp_comp_funcs {
|
||||
void (*config)(struct mtk_ddp_comp *comp, unsigned int w,
|
||||
int (*clk_enable)(struct device *dev);
|
||||
void (*clk_disable)(struct device *dev);
|
||||
void (*config)(struct device *dev, unsigned int w,
|
||||
unsigned int h, unsigned int vrefresh,
|
||||
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
|
||||
void (*start)(struct mtk_ddp_comp *comp);
|
||||
void (*stop)(struct mtk_ddp_comp *comp);
|
||||
void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc);
|
||||
void (*disable_vblank)(struct mtk_ddp_comp *comp);
|
||||
unsigned int (*supported_rotations)(struct mtk_ddp_comp *comp);
|
||||
unsigned int (*layer_nr)(struct mtk_ddp_comp *comp);
|
||||
int (*layer_check)(struct mtk_ddp_comp *comp,
|
||||
void (*start)(struct device *dev);
|
||||
void (*stop)(struct device *dev);
|
||||
void (*enable_vblank)(struct device *dev,
|
||||
void (*vblank_cb)(void *),
|
||||
void *vblank_cb_data);
|
||||
void (*disable_vblank)(struct device *dev);
|
||||
unsigned int (*supported_rotations)(struct device *dev);
|
||||
unsigned int (*layer_nr)(struct device *dev);
|
||||
int (*layer_check)(struct device *dev,
|
||||
unsigned int idx,
|
||||
struct mtk_plane_state *state);
|
||||
void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx,
|
||||
void (*layer_config)(struct device *dev, unsigned int idx,
|
||||
struct mtk_plane_state *state,
|
||||
struct cmdq_pkt *cmdq_pkt);
|
||||
void (*gamma_set)(struct mtk_ddp_comp *comp,
|
||||
void (*gamma_set)(struct device *dev,
|
||||
struct drm_crtc_state *state);
|
||||
void (*bgclr_in_on)(struct mtk_ddp_comp *comp);
|
||||
void (*bgclr_in_off)(struct mtk_ddp_comp *comp);
|
||||
void (*ctm_set)(struct mtk_ddp_comp *comp,
|
||||
void (*bgclr_in_on)(struct device *dev);
|
||||
void (*bgclr_in_off)(struct device *dev);
|
||||
void (*ctm_set)(struct device *dev,
|
||||
struct drm_crtc_state *state);
|
||||
};
|
||||
|
||||
struct mtk_ddp_comp {
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct device *dev;
|
||||
int irq;
|
||||
struct device *larb_dev;
|
||||
enum mtk_ddp_comp_id id;
|
||||
const struct mtk_ddp_comp_funcs *funcs;
|
||||
resource_size_t regs_pa;
|
||||
u8 subsys;
|
||||
};
|
||||
|
||||
static inline int mtk_ddp_comp_clk_enable(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->clk_enable)
|
||||
return comp->funcs->clk_enable(comp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_clk_disable(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->clk_disable)
|
||||
comp->funcs->clk_disable(comp->dev);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
|
||||
unsigned int w, unsigned int h,
|
||||
unsigned int vrefresh, unsigned int bpc,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->config)
|
||||
comp->funcs->config(comp, w, h, vrefresh, bpc, cmdq_pkt);
|
||||
comp->funcs->config(comp->dev, w, h, vrefresh, bpc, cmdq_pkt);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->start)
|
||||
comp->funcs->start(comp);
|
||||
comp->funcs->start(comp->dev);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_stop(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->stop)
|
||||
comp->funcs->stop(comp);
|
||||
comp->funcs->stop(comp->dev);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_enable_vblank(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc *crtc)
|
||||
void (*vblank_cb)(void *),
|
||||
void *vblank_cb_data)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->enable_vblank)
|
||||
comp->funcs->enable_vblank(comp, crtc);
|
||||
comp->funcs->enable_vblank(comp->dev, vblank_cb, vblank_cb_data);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_disable_vblank(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->disable_vblank)
|
||||
comp->funcs->disable_vblank(comp);
|
||||
comp->funcs->disable_vblank(comp->dev);
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned int mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->supported_rotations)
|
||||
return comp->funcs->supported_rotations(comp);
|
||||
return comp->funcs->supported_rotations(comp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -119,7 +136,7 @@ unsigned int mtk_ddp_comp_supported_rotations(struct mtk_ddp_comp *comp)
|
||||
static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->layer_nr)
|
||||
return comp->funcs->layer_nr(comp);
|
||||
return comp->funcs->layer_nr(comp->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -129,7 +146,7 @@ static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp,
|
||||
struct mtk_plane_state *state)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->layer_check)
|
||||
return comp->funcs->layer_check(comp, idx, state);
|
||||
return comp->funcs->layer_check(comp->dev, idx, state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -139,52 +156,49 @@ static inline void mtk_ddp_comp_layer_config(struct mtk_ddp_comp *comp,
|
||||
struct cmdq_pkt *cmdq_pkt)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->layer_config)
|
||||
comp->funcs->layer_config(comp, idx, state, cmdq_pkt);
|
||||
comp->funcs->layer_config(comp->dev, idx, state, cmdq_pkt);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_gamma_set(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->gamma_set)
|
||||
comp->funcs->gamma_set(comp, state);
|
||||
comp->funcs->gamma_set(comp->dev, state);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_bgclr_in_on(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->bgclr_in_on)
|
||||
comp->funcs->bgclr_in_on(comp);
|
||||
comp->funcs->bgclr_in_on(comp->dev);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_comp_bgclr_in_off(struct mtk_ddp_comp *comp)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->bgclr_in_off)
|
||||
comp->funcs->bgclr_in_off(comp);
|
||||
comp->funcs->bgclr_in_off(comp->dev);
|
||||
}
|
||||
|
||||
static inline void mtk_ddp_ctm_set(struct mtk_ddp_comp *comp,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
if (comp->funcs && comp->funcs->ctm_set)
|
||||
comp->funcs->ctm_set(comp, state);
|
||||
comp->funcs->ctm_set(comp->dev, state);
|
||||
}
|
||||
|
||||
int mtk_ddp_comp_get_id(struct device_node *node,
|
||||
enum mtk_ddp_comp_type comp_type);
|
||||
unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
|
||||
struct mtk_ddp_comp ddp_comp);
|
||||
int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node,
|
||||
struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id,
|
||||
const struct mtk_ddp_comp_funcs *funcs);
|
||||
int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp);
|
||||
void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp);
|
||||
void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
|
||||
unsigned int CFG, struct cmdq_pkt *cmdq_pkt);
|
||||
struct device *dev);
|
||||
int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp,
|
||||
enum mtk_ddp_comp_id comp_id);
|
||||
enum mtk_ddp_comp_type mtk_ddp_comp_get_type(enum mtk_ddp_comp_id comp_id);
|
||||
void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
|
||||
struct mtk_ddp_comp *comp, unsigned int offset);
|
||||
struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
|
||||
unsigned int offset);
|
||||
void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
|
||||
struct mtk_ddp_comp *comp, unsigned int offset);
|
||||
struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
|
||||
unsigned int offset);
|
||||
void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
|
||||
struct mtk_ddp_comp *comp, unsigned int offset,
|
||||
unsigned int mask);
|
||||
struct cmdq_client_reg *cmdq_reg, void __iomem *regs,
|
||||
unsigned int offset, unsigned int mask);
|
||||
#endif /* MTK_DRM_DDP_COMP_H */
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/soc/mediatek/mtk-mmsys.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
@ -26,7 +25,6 @@
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "mtk_drm_crtc.h"
|
||||
#include "mtk_drm_ddp.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
#include "mtk_drm_drv.h"
|
||||
#include "mtk_drm_gem.h"
|
||||
@ -131,6 +129,24 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
|
||||
DDP_COMPONENT_DPI0,
|
||||
};
|
||||
|
||||
static const enum mtk_ddp_comp_id mt8183_mtk_ddp_main[] = {
|
||||
DDP_COMPONENT_OVL0,
|
||||
DDP_COMPONENT_OVL_2L0,
|
||||
DDP_COMPONENT_RDMA0,
|
||||
DDP_COMPONENT_COLOR0,
|
||||
DDP_COMPONENT_CCORR,
|
||||
DDP_COMPONENT_AAL0,
|
||||
DDP_COMPONENT_GAMMA,
|
||||
DDP_COMPONENT_DITHER,
|
||||
DDP_COMPONENT_DSI0,
|
||||
};
|
||||
|
||||
static const enum mtk_ddp_comp_id mt8183_mtk_ddp_ext[] = {
|
||||
DDP_COMPONENT_OVL_2L1,
|
||||
DDP_COMPONENT_RDMA1,
|
||||
DDP_COMPONENT_DPI0,
|
||||
};
|
||||
|
||||
static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
|
||||
.main_path = mt2701_mtk_ddp_main,
|
||||
.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
|
||||
@ -163,6 +179,13 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
|
||||
.ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
|
||||
};
|
||||
|
||||
static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
|
||||
.main_path = mt8183_mtk_ddp_main,
|
||||
.main_len = ARRAY_SIZE(mt8183_mtk_ddp_main),
|
||||
.ext_path = mt8183_mtk_ddp_ext,
|
||||
.ext_len = ARRAY_SIZE(mt8183_mtk_ddp_ext),
|
||||
};
|
||||
|
||||
static int mtk_drm_kms_init(struct drm_device *drm)
|
||||
{
|
||||
struct mtk_drm_private *private = drm->dev_private;
|
||||
@ -377,12 +400,20 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
|
||||
.data = (void *)MTK_DISP_OVL },
|
||||
{ .compatible = "mediatek,mt8173-disp-ovl",
|
||||
.data = (void *)MTK_DISP_OVL },
|
||||
{ .compatible = "mediatek,mt8183-disp-ovl",
|
||||
.data = (void *)MTK_DISP_OVL },
|
||||
{ .compatible = "mediatek,mt8183-disp-ovl-2l",
|
||||
.data = (void *)MTK_DISP_OVL_2L },
|
||||
{ .compatible = "mediatek,mt2701-disp-rdma",
|
||||
.data = (void *)MTK_DISP_RDMA },
|
||||
{ .compatible = "mediatek,mt8173-disp-rdma",
|
||||
.data = (void *)MTK_DISP_RDMA },
|
||||
{ .compatible = "mediatek,mt8183-disp-rdma",
|
||||
.data = (void *)MTK_DISP_RDMA },
|
||||
{ .compatible = "mediatek,mt8173-disp-wdma",
|
||||
.data = (void *)MTK_DISP_WDMA },
|
||||
{ .compatible = "mediatek,mt8183-disp-ccorr",
|
||||
.data = (void *)MTK_DISP_CCORR },
|
||||
{ .compatible = "mediatek,mt2701-disp-color",
|
||||
.data = (void *)MTK_DISP_COLOR },
|
||||
{ .compatible = "mediatek,mt8173-disp-color",
|
||||
@ -391,22 +422,32 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
|
||||
.data = (void *)MTK_DISP_AAL},
|
||||
{ .compatible = "mediatek,mt8173-disp-gamma",
|
||||
.data = (void *)MTK_DISP_GAMMA, },
|
||||
{ .compatible = "mediatek,mt8183-disp-gamma",
|
||||
.data = (void *)MTK_DISP_GAMMA, },
|
||||
{ .compatible = "mediatek,mt8183-disp-dither",
|
||||
.data = (void *)MTK_DISP_DITHER },
|
||||
{ .compatible = "mediatek,mt8173-disp-ufoe",
|
||||
.data = (void *)MTK_DISP_UFOE },
|
||||
{ .compatible = "mediatek,mt2701-dsi",
|
||||
.data = (void *)MTK_DSI },
|
||||
{ .compatible = "mediatek,mt8173-dsi",
|
||||
.data = (void *)MTK_DSI },
|
||||
{ .compatible = "mediatek,mt8183-dsi",
|
||||
.data = (void *)MTK_DSI },
|
||||
{ .compatible = "mediatek,mt2701-dpi",
|
||||
.data = (void *)MTK_DPI },
|
||||
{ .compatible = "mediatek,mt8173-dpi",
|
||||
.data = (void *)MTK_DPI },
|
||||
{ .compatible = "mediatek,mt8183-dpi",
|
||||
.data = (void *)MTK_DPI },
|
||||
{ .compatible = "mediatek,mt2701-disp-mutex",
|
||||
.data = (void *)MTK_DISP_MUTEX },
|
||||
{ .compatible = "mediatek,mt2712-disp-mutex",
|
||||
.data = (void *)MTK_DISP_MUTEX },
|
||||
{ .compatible = "mediatek,mt8173-disp-mutex",
|
||||
.data = (void *)MTK_DISP_MUTEX },
|
||||
{ .compatible = "mediatek,mt8183-disp-mutex",
|
||||
.data = (void *)MTK_DISP_MUTEX },
|
||||
{ .compatible = "mediatek,mt2701-disp-pwm",
|
||||
.data = (void *)MTK_DISP_BLS },
|
||||
{ .compatible = "mediatek,mt8173-disp-pwm",
|
||||
@ -425,6 +466,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
|
||||
.data = &mt2712_mmsys_driver_data},
|
||||
{ .compatible = "mediatek,mt8173-mmsys",
|
||||
.data = &mt8173_mmsys_driver_data},
|
||||
{ .compatible = "mediatek,mt8183-mmsys",
|
||||
.data = &mt8183_mmsys_driver_data},
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -488,11 +531,13 @@ static int mtk_drm_probe(struct platform_device *pdev)
|
||||
private->comp_node[comp_id] = of_node_get(node);
|
||||
|
||||
/*
|
||||
* Currently only the COLOR, OVL, RDMA, DSI, and DPI blocks have
|
||||
* separate component platform drivers and initialize their own
|
||||
* Currently only the CCORR, COLOR, GAMMA, OVL, RDMA, DSI, and DPI
|
||||
* blocks have separate component platform drivers and initialize their own
|
||||
* DDP component structure. The others are initialized here.
|
||||
*/
|
||||
if (comp_type == MTK_DISP_COLOR ||
|
||||
if (comp_type == MTK_DISP_CCORR ||
|
||||
comp_type == MTK_DISP_COLOR ||
|
||||
comp_type == MTK_DISP_GAMMA ||
|
||||
comp_type == MTK_DISP_OVL ||
|
||||
comp_type == MTK_DISP_OVL_2L ||
|
||||
comp_type == MTK_DISP_RDMA ||
|
||||
@ -502,24 +547,12 @@ static int mtk_drm_probe(struct platform_device *pdev)
|
||||
node);
|
||||
drm_of_component_match_add(dev, &match, compare_of,
|
||||
node);
|
||||
} else {
|
||||
struct mtk_ddp_comp *comp;
|
||||
}
|
||||
|
||||
comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
|
||||
if (!comp) {
|
||||
ret = -ENOMEM;
|
||||
of_node_put(node);
|
||||
goto err_node;
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev->parent, node, comp,
|
||||
comp_id, NULL);
|
||||
if (ret) {
|
||||
of_node_put(node);
|
||||
goto err_node;
|
||||
}
|
||||
|
||||
private->ddp_comp[comp_id] = comp;
|
||||
ret = mtk_ddp_comp_init(node, &private->ddp_comp[comp_id], comp_id);
|
||||
if (ret) {
|
||||
of_node_put(node);
|
||||
goto err_node;
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,10 +578,8 @@ err_node:
|
||||
of_node_put(private->mutex_node);
|
||||
for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) {
|
||||
of_node_put(private->comp_node[i]);
|
||||
if (private->ddp_comp[i]) {
|
||||
put_device(private->ddp_comp[i]->larb_dev);
|
||||
private->ddp_comp[i] = NULL;
|
||||
}
|
||||
if (private->ddp_comp[i].larb_dev)
|
||||
put_device(private->ddp_comp[i].larb_dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -604,8 +635,9 @@ static struct platform_driver mtk_drm_platform_driver = {
|
||||
};
|
||||
|
||||
static struct platform_driver * const mtk_drm_drivers[] = {
|
||||
&mtk_ddp_driver,
|
||||
&mtk_disp_ccorr_driver,
|
||||
&mtk_disp_color_driver,
|
||||
&mtk_disp_gamma_driver,
|
||||
&mtk_disp_ovl_driver,
|
||||
&mtk_disp_rdma_driver,
|
||||
&mtk_dpi_driver,
|
||||
|
@ -41,13 +41,14 @@ struct mtk_drm_private {
|
||||
struct device *mutex_dev;
|
||||
struct device *mmsys_dev;
|
||||
struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
|
||||
struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
|
||||
struct mtk_ddp_comp ddp_comp[DDP_COMPONENT_ID_MAX];
|
||||
const struct mtk_mmsys_driver_data *data;
|
||||
struct drm_atomic_state *suspend_state;
|
||||
};
|
||||
|
||||
extern struct platform_driver mtk_ddp_driver;
|
||||
extern struct platform_driver mtk_disp_ccorr_driver;
|
||||
extern struct platform_driver mtk_disp_color_driver;
|
||||
extern struct platform_driver mtk_disp_gamma_driver;
|
||||
extern struct platform_driver mtk_disp_ovl_driver;
|
||||
extern struct platform_driver mtk_disp_rdma_driver;
|
||||
extern struct platform_driver mtk_dpi_driver;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
#include "mtk_disp_drv.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
#define DSI_START 0x00
|
||||
@ -178,7 +179,6 @@ struct mtk_dsi_driver_data {
|
||||
};
|
||||
|
||||
struct mtk_dsi {
|
||||
struct mtk_ddp_comp ddp_comp;
|
||||
struct device *dev;
|
||||
struct mipi_dsi_host host;
|
||||
struct drm_encoder encoder;
|
||||
@ -767,25 +767,20 @@ static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = {
|
||||
.mode_set = mtk_dsi_bridge_mode_set,
|
||||
};
|
||||
|
||||
static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
|
||||
void mtk_dsi_ddp_start(struct device *dev)
|
||||
{
|
||||
struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
|
||||
struct mtk_dsi *dsi = dev_get_drvdata(dev);
|
||||
|
||||
mtk_dsi_poweron(dsi);
|
||||
}
|
||||
|
||||
static void mtk_dsi_ddp_stop(struct mtk_ddp_comp *comp)
|
||||
void mtk_dsi_ddp_stop(struct device *dev)
|
||||
{
|
||||
struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
|
||||
struct mtk_dsi *dsi = dev_get_drvdata(dev);
|
||||
|
||||
mtk_dsi_poweroff(dsi);
|
||||
}
|
||||
|
||||
static const struct mtk_ddp_comp_funcs mtk_dsi_funcs = {
|
||||
.start = mtk_dsi_ddp_start,
|
||||
.stop = mtk_dsi_ddp_stop,
|
||||
};
|
||||
|
||||
static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
|
||||
struct mipi_dsi_device *device)
|
||||
{
|
||||
@ -952,7 +947,7 @@ static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->ddp_comp);
|
||||
dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev);
|
||||
|
||||
ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL,
|
||||
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||
@ -980,32 +975,17 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
struct drm_device *drm = data;
|
||||
struct mtk_dsi *dsi = dev_get_drvdata(dev);
|
||||
|
||||
ret = mtk_ddp_comp_register(drm, &dsi->ddp_comp);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register component %pOF: %d\n",
|
||||
dev->of_node, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mtk_dsi_encoder_init(drm, dsi);
|
||||
if (ret)
|
||||
goto err_unregister;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister:
|
||||
mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mtk_dsi_unbind(struct device *dev, struct device *master,
|
||||
void *data)
|
||||
{
|
||||
struct drm_device *drm = data;
|
||||
struct mtk_dsi *dsi = dev_get_drvdata(dev);
|
||||
|
||||
drm_encoder_cleanup(&dsi->encoder);
|
||||
mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
|
||||
}
|
||||
|
||||
static const struct component_ops mtk_dsi_component_ops = {
|
||||
@ -1020,7 +1000,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
|
||||
struct drm_panel *panel;
|
||||
struct resource *regs;
|
||||
int irq_num;
|
||||
int comp_id;
|
||||
int ret;
|
||||
|
||||
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
|
||||
@ -1090,20 +1069,6 @@ static int mtk_dsi_probe(struct platform_device *pdev)
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DSI);
|
||||
if (comp_id < 0) {
|
||||
dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
|
||||
ret = comp_id;
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
ret = mtk_ddp_comp_init(dev, dev->of_node, &dsi->ddp_comp, comp_id,
|
||||
&mtk_dsi_funcs);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize component: %d\n", ret);
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
irq_num = platform_get_irq(pdev, 0);
|
||||
if (irq_num < 0) {
|
||||
dev_err(&pdev->dev, "failed to get dsi irq_num: %d\n", irq_num);
|
||||
@ -1111,9 +1076,8 @@ static int mtk_dsi_probe(struct platform_device *pdev)
|
||||
goto err_unregister_host;
|
||||
}
|
||||
|
||||
irq_set_status_flags(irq_num, IRQ_TYPE_LEVEL_LOW);
|
||||
ret = devm_request_irq(&pdev->dev, irq_num, mtk_dsi_irq,
|
||||
IRQF_TRIGGER_LOW, dev_name(&pdev->dev), dsi);
|
||||
IRQF_TRIGGER_NONE, dev_name(&pdev->dev), dsi);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request mediatek dsi irq\n");
|
||||
goto err_unregister_host;
|
||||
|
@ -6,3 +6,4 @@ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
|
||||
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
|
||||
obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
|
||||
obj-$(CONFIG_MTK_MMSYS) += mtk-mmsys.o
|
||||
obj-$(CONFIG_MTK_MMSYS) += mtk-mutex.o
|
||||
|
@ -9,12 +9,11 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/soc/mediatek/mtk-mmsys.h>
|
||||
#include <linux/soc/mediatek/mtk-mutex.h>
|
||||
|
||||
#include "mtk_drm_ddp.h"
|
||||
#include "mtk_drm_ddp_comp.h"
|
||||
|
||||
#define MT2701_DISP_MUTEX0_MOD0 0x2c
|
||||
#define MT2701_DISP_MUTEX0_SOF0 0x30
|
||||
#define MT2701_MUTEX0_MOD0 0x2c
|
||||
#define MT2701_MUTEX0_SOF0 0x30
|
||||
|
||||
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
|
||||
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
|
||||
@ -79,33 +78,32 @@
|
||||
#define MT2701_MUTEX_MOD_DISP_RDMA0 10
|
||||
#define MT2701_MUTEX_MOD_DISP_RDMA1 12
|
||||
|
||||
#define MUTEX_SOF_SINGLE_MODE 0
|
||||
#define MUTEX_SOF_DSI0 1
|
||||
#define MUTEX_SOF_DSI1 2
|
||||
#define MUTEX_SOF_DPI0 3
|
||||
#define MUTEX_SOF_DPI1 4
|
||||
#define MUTEX_SOF_DSI2 5
|
||||
#define MUTEX_SOF_DSI3 6
|
||||
#define MT8167_MUTEX_SOF_DPI0 2
|
||||
#define MT8167_MUTEX_SOF_DPI1 3
|
||||
#define MT2712_MUTEX_SOF_SINGLE_MODE 0
|
||||
#define MT2712_MUTEX_SOF_DSI0 1
|
||||
#define MT2712_MUTEX_SOF_DSI1 2
|
||||
#define MT2712_MUTEX_SOF_DPI0 3
|
||||
#define MT2712_MUTEX_SOF_DPI1 4
|
||||
#define MT2712_MUTEX_SOF_DSI2 5
|
||||
#define MT2712_MUTEX_SOF_DSI3 6
|
||||
#define MT8167_MUTEX_SOF_DPI0 2
|
||||
#define MT8167_MUTEX_SOF_DPI1 3
|
||||
|
||||
|
||||
struct mtk_disp_mutex {
|
||||
struct mtk_mutex {
|
||||
int id;
|
||||
bool claimed;
|
||||
};
|
||||
|
||||
enum mtk_ddp_mutex_sof_id {
|
||||
DDP_MUTEX_SOF_SINGLE_MODE,
|
||||
DDP_MUTEX_SOF_DSI0,
|
||||
DDP_MUTEX_SOF_DSI1,
|
||||
DDP_MUTEX_SOF_DPI0,
|
||||
DDP_MUTEX_SOF_DPI1,
|
||||
DDP_MUTEX_SOF_DSI2,
|
||||
DDP_MUTEX_SOF_DSI3,
|
||||
enum mtk_mutex_sof_id {
|
||||
MUTEX_SOF_SINGLE_MODE,
|
||||
MUTEX_SOF_DSI0,
|
||||
MUTEX_SOF_DSI1,
|
||||
MUTEX_SOF_DPI0,
|
||||
MUTEX_SOF_DPI1,
|
||||
MUTEX_SOF_DSI2,
|
||||
MUTEX_SOF_DSI3,
|
||||
};
|
||||
|
||||
struct mtk_ddp_data {
|
||||
struct mtk_mutex_data {
|
||||
const unsigned int *mutex_mod;
|
||||
const unsigned int *mutex_sof;
|
||||
const unsigned int mutex_mod_reg;
|
||||
@ -113,12 +111,12 @@ struct mtk_ddp_data {
|
||||
const bool no_clk;
|
||||
};
|
||||
|
||||
struct mtk_ddp {
|
||||
struct mtk_mutex_ctx {
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
void __iomem *regs;
|
||||
struct mtk_disp_mutex mutex[10];
|
||||
const struct mtk_ddp_data *data;
|
||||
struct mtk_mutex mutex[10];
|
||||
const struct mtk_mutex_data *data;
|
||||
};
|
||||
|
||||
static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
||||
@ -183,150 +181,155 @@ static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
||||
[DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
|
||||
};
|
||||
|
||||
static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_DSI3 + 1] = {
|
||||
[DDP_MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||
[DDP_MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||
[DDP_MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
|
||||
[DDP_MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
|
||||
[DDP_MUTEX_SOF_DPI1] = MUTEX_SOF_DPI1,
|
||||
[DDP_MUTEX_SOF_DSI2] = MUTEX_SOF_DSI2,
|
||||
[DDP_MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
|
||||
static const unsigned int mt2712_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
|
||||
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||
[MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
|
||||
[MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
|
||||
[MUTEX_SOF_DPI1] = MUTEX_SOF_DPI1,
|
||||
[MUTEX_SOF_DSI2] = MUTEX_SOF_DSI2,
|
||||
[MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
|
||||
};
|
||||
|
||||
static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_DSI3 + 1] = {
|
||||
[DDP_MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||
[DDP_MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||
[DDP_MUTEX_SOF_DPI0] = MT8167_MUTEX_SOF_DPI0,
|
||||
[DDP_MUTEX_SOF_DPI1] = MT8167_MUTEX_SOF_DPI1,
|
||||
static const unsigned int mt8167_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
|
||||
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||
[MUTEX_SOF_DPI0] = MT8167_MUTEX_SOF_DPI0,
|
||||
[MUTEX_SOF_DPI1] = MT8167_MUTEX_SOF_DPI1,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt2701_ddp_driver_data = {
|
||||
static const struct mtk_mutex_data mt2701_mutex_driver_data = {
|
||||
.mutex_mod = mt2701_mutex_mod,
|
||||
.mutex_sof = mt2712_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt2712_ddp_driver_data = {
|
||||
static const struct mtk_mutex_data mt2712_mutex_driver_data = {
|
||||
.mutex_mod = mt2712_mutex_mod,
|
||||
.mutex_sof = mt2712_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt8167_ddp_driver_data = {
|
||||
static const struct mtk_mutex_data mt8167_mutex_driver_data = {
|
||||
.mutex_mod = mt8167_mutex_mod,
|
||||
.mutex_sof = mt8167_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
||||
.no_clk = true,
|
||||
};
|
||||
|
||||
static const struct mtk_ddp_data mt8173_ddp_driver_data = {
|
||||
static const struct mtk_mutex_data mt8173_mutex_driver_data = {
|
||||
.mutex_mod = mt8173_mutex_mod,
|
||||
.mutex_sof = mt2712_mutex_sof,
|
||||
.mutex_mod_reg = MT2701_DISP_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_DISP_MUTEX0_SOF0,
|
||||
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
|
||||
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
||||
};
|
||||
|
||||
struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id)
|
||||
struct mtk_mutex *mtk_mutex_get(struct device *dev)
|
||||
{
|
||||
struct mtk_ddp *ddp = dev_get_drvdata(dev);
|
||||
struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
if (id >= 10)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (ddp->mutex[id].claimed)
|
||||
return ERR_PTR(-EBUSY);
|
||||
for (i = 0; i < 10; i++)
|
||||
if (!mtx->mutex[i].claimed) {
|
||||
mtx->mutex[i].claimed = true;
|
||||
return &mtx->mutex[i];
|
||||
}
|
||||
|
||||
ddp->mutex[id].claimed = true;
|
||||
|
||||
return &ddp->mutex[id];
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_get);
|
||||
|
||||
void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex)
|
||||
void mtk_mutex_put(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
|
||||
WARN_ON(&ddp->mutex[mutex->id] != mutex);
|
||||
WARN_ON(&mtx->mutex[mutex->id] != mutex);
|
||||
|
||||
mutex->claimed = false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_put);
|
||||
|
||||
int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex)
|
||||
int mtk_mutex_prepare(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
return clk_prepare_enable(ddp->clk);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
return clk_prepare_enable(mtx->clk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_prepare);
|
||||
|
||||
void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex)
|
||||
void mtk_mutex_unprepare(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
clk_disable_unprepare(ddp->clk);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
clk_disable_unprepare(mtx->clk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
|
||||
|
||||
void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id)
|
||||
void mtk_mutex_add_comp(struct mtk_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
unsigned int reg;
|
||||
unsigned int sof_id;
|
||||
unsigned int offset;
|
||||
|
||||
WARN_ON(&ddp->mutex[mutex->id] != mutex);
|
||||
WARN_ON(&mtx->mutex[mutex->id] != mutex);
|
||||
|
||||
switch (id) {
|
||||
case DDP_COMPONENT_DSI0:
|
||||
sof_id = DDP_MUTEX_SOF_DSI0;
|
||||
sof_id = MUTEX_SOF_DSI0;
|
||||
break;
|
||||
case DDP_COMPONENT_DSI1:
|
||||
sof_id = DDP_MUTEX_SOF_DSI0;
|
||||
sof_id = MUTEX_SOF_DSI0;
|
||||
break;
|
||||
case DDP_COMPONENT_DSI2:
|
||||
sof_id = DDP_MUTEX_SOF_DSI2;
|
||||
sof_id = MUTEX_SOF_DSI2;
|
||||
break;
|
||||
case DDP_COMPONENT_DSI3:
|
||||
sof_id = DDP_MUTEX_SOF_DSI3;
|
||||
sof_id = MUTEX_SOF_DSI3;
|
||||
break;
|
||||
case DDP_COMPONENT_DPI0:
|
||||
sof_id = DDP_MUTEX_SOF_DPI0;
|
||||
sof_id = MUTEX_SOF_DPI0;
|
||||
break;
|
||||
case DDP_COMPONENT_DPI1:
|
||||
sof_id = DDP_MUTEX_SOF_DPI1;
|
||||
sof_id = MUTEX_SOF_DPI1;
|
||||
break;
|
||||
default:
|
||||
if (ddp->data->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(ddp->data->mutex_mod_reg,
|
||||
if (mtx->data->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
|
||||
mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg |= 1 << ddp->data->mutex_mod[id];
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
reg = readl_relaxed(mtx->regs + offset);
|
||||
reg |= 1 << mtx->data->mutex_mod[id];
|
||||
writel_relaxed(reg, mtx->regs + offset);
|
||||
} else {
|
||||
offset = DISP_REG_MUTEX_MOD2(mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg |= 1 << (ddp->data->mutex_mod[id] - 32);
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
reg = readl_relaxed(mtx->regs + offset);
|
||||
reg |= 1 << (mtx->data->mutex_mod[id] - 32);
|
||||
writel_relaxed(reg, mtx->regs + offset);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
writel_relaxed(ddp->data->mutex_sof[sof_id],
|
||||
ddp->regs +
|
||||
DISP_REG_MUTEX_SOF(ddp->data->mutex_sof_reg, mutex->id));
|
||||
writel_relaxed(mtx->data->mutex_sof[sof_id],
|
||||
mtx->regs +
|
||||
DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
|
||||
|
||||
void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id)
|
||||
void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
unsigned int reg;
|
||||
unsigned int offset;
|
||||
|
||||
WARN_ON(&ddp->mutex[mutex->id] != mutex);
|
||||
WARN_ON(&mtx->mutex[mutex->id] != mutex);
|
||||
|
||||
switch (id) {
|
||||
case DDP_COMPONENT_DSI0:
|
||||
@ -336,129 +339,136 @@ void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
|
||||
case DDP_COMPONENT_DPI0:
|
||||
case DDP_COMPONENT_DPI1:
|
||||
writel_relaxed(MUTEX_SOF_SINGLE_MODE,
|
||||
ddp->regs +
|
||||
DISP_REG_MUTEX_SOF(ddp->data->mutex_sof_reg,
|
||||
mtx->regs +
|
||||
DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
|
||||
mutex->id));
|
||||
break;
|
||||
default:
|
||||
if (ddp->data->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(ddp->data->mutex_mod_reg,
|
||||
if (mtx->data->mutex_mod[id] < 32) {
|
||||
offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
|
||||
mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg &= ~(1 << ddp->data->mutex_mod[id]);
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
reg = readl_relaxed(mtx->regs + offset);
|
||||
reg &= ~(1 << mtx->data->mutex_mod[id]);
|
||||
writel_relaxed(reg, mtx->regs + offset);
|
||||
} else {
|
||||
offset = DISP_REG_MUTEX_MOD2(mutex->id);
|
||||
reg = readl_relaxed(ddp->regs + offset);
|
||||
reg &= ~(1 << (ddp->data->mutex_mod[id] - 32));
|
||||
writel_relaxed(reg, ddp->regs + offset);
|
||||
reg = readl_relaxed(mtx->regs + offset);
|
||||
reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
|
||||
writel_relaxed(reg, mtx->regs + offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
|
||||
|
||||
void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex)
|
||||
void mtk_mutex_enable(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
|
||||
WARN_ON(&ddp->mutex[mutex->id] != mutex);
|
||||
WARN_ON(&mtx->mutex[mutex->id] != mutex);
|
||||
|
||||
writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
|
||||
writel(1, mtx->regs + DISP_REG_MUTEX_EN(mutex->id));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_enable);
|
||||
|
||||
void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
|
||||
void mtk_mutex_disable(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
|
||||
WARN_ON(&ddp->mutex[mutex->id] != mutex);
|
||||
WARN_ON(&mtx->mutex[mutex->id] != mutex);
|
||||
|
||||
writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
|
||||
writel(0, mtx->regs + DISP_REG_MUTEX_EN(mutex->id));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_disable);
|
||||
|
||||
void mtk_disp_mutex_acquire(struct mtk_disp_mutex *mutex)
|
||||
void mtk_mutex_acquire(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
u32 tmp;
|
||||
|
||||
writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
|
||||
writel(1, ddp->regs + DISP_REG_MUTEX(mutex->id));
|
||||
if (readl_poll_timeout_atomic(ddp->regs + DISP_REG_MUTEX(mutex->id),
|
||||
writel(1, mtx->regs + DISP_REG_MUTEX_EN(mutex->id));
|
||||
writel(1, mtx->regs + DISP_REG_MUTEX(mutex->id));
|
||||
if (readl_poll_timeout_atomic(mtx->regs + DISP_REG_MUTEX(mutex->id),
|
||||
tmp, tmp & INT_MUTEX, 1, 10000))
|
||||
pr_err("could not acquire mutex %d\n", mutex->id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_acquire);
|
||||
|
||||
void mtk_disp_mutex_release(struct mtk_disp_mutex *mutex)
|
||||
void mtk_mutex_release(struct mtk_mutex *mutex)
|
||||
{
|
||||
struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
|
||||
mutex[mutex->id]);
|
||||
struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
|
||||
mutex[mutex->id]);
|
||||
|
||||
writel(0, ddp->regs + DISP_REG_MUTEX(mutex->id));
|
||||
writel(0, mtx->regs + DISP_REG_MUTEX(mutex->id));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_mutex_release);
|
||||
|
||||
static int mtk_ddp_probe(struct platform_device *pdev)
|
||||
static int mtk_mutex_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtk_ddp *ddp;
|
||||
struct mtk_mutex_ctx *mtx;
|
||||
struct resource *regs;
|
||||
int i;
|
||||
|
||||
ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL);
|
||||
if (!ddp)
|
||||
mtx = devm_kzalloc(dev, sizeof(*mtx), GFP_KERNEL);
|
||||
if (!mtx)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
ddp->mutex[i].id = i;
|
||||
mtx->mutex[i].id = i;
|
||||
|
||||
ddp->data = of_device_get_match_data(dev);
|
||||
mtx->data = of_device_get_match_data(dev);
|
||||
|
||||
if (!ddp->data->no_clk) {
|
||||
ddp->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(ddp->clk)) {
|
||||
if (PTR_ERR(ddp->clk) != -EPROBE_DEFER)
|
||||
if (!mtx->data->no_clk) {
|
||||
mtx->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(mtx->clk)) {
|
||||
if (PTR_ERR(mtx->clk) != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to get clock\n");
|
||||
return PTR_ERR(ddp->clk);
|
||||
return PTR_ERR(mtx->clk);
|
||||
}
|
||||
}
|
||||
|
||||
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
ddp->regs = devm_ioremap_resource(dev, regs);
|
||||
if (IS_ERR(ddp->regs)) {
|
||||
mtx->regs = devm_ioremap_resource(dev, regs);
|
||||
if (IS_ERR(mtx->regs)) {
|
||||
dev_err(dev, "Failed to map mutex registers\n");
|
||||
return PTR_ERR(ddp->regs);
|
||||
return PTR_ERR(mtx->regs);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ddp);
|
||||
platform_set_drvdata(pdev, mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_ddp_remove(struct platform_device *pdev)
|
||||
static int mtk_mutex_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ddp_driver_dt_match[] = {
|
||||
static const struct of_device_id mutex_driver_dt_match[] = {
|
||||
{ .compatible = "mediatek,mt2701-disp-mutex",
|
||||
.data = &mt2701_ddp_driver_data},
|
||||
.data = &mt2701_mutex_driver_data},
|
||||
{ .compatible = "mediatek,mt2712-disp-mutex",
|
||||
.data = &mt2712_ddp_driver_data},
|
||||
.data = &mt2712_mutex_driver_data},
|
||||
{ .compatible = "mediatek,mt8167-disp-mutex",
|
||||
.data = &mt8167_ddp_driver_data},
|
||||
.data = &mt8167_mutex_driver_data},
|
||||
{ .compatible = "mediatek,mt8173-disp-mutex",
|
||||
.data = &mt8173_ddp_driver_data},
|
||||
.data = &mt8173_mutex_driver_data},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
|
||||
MODULE_DEVICE_TABLE(of, mutex_driver_dt_match);
|
||||
|
||||
struct platform_driver mtk_ddp_driver = {
|
||||
.probe = mtk_ddp_probe,
|
||||
.remove = mtk_ddp_remove,
|
||||
struct platform_driver mtk_mutex_driver = {
|
||||
.probe = mtk_mutex_probe,
|
||||
.remove = mtk_mutex_remove,
|
||||
.driver = {
|
||||
.name = "mediatek-ddp",
|
||||
.name = "mediatek-mutex",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = ddp_driver_dt_match,
|
||||
.of_match_table = mutex_driver_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(mtk_mutex_driver);
|
26
include/linux/soc/mediatek/mtk-mutex.h
Normal file
26
include/linux/soc/mediatek/mtk-mutex.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015 MediaTek Inc.
|
||||
*/
|
||||
|
||||
#ifndef MTK_MUTEX_H
|
||||
#define MTK_MUTEX_H
|
||||
|
||||
struct regmap;
|
||||
struct device;
|
||||
struct mtk_mutex;
|
||||
|
||||
struct mtk_mutex *mtk_mutex_get(struct device *dev);
|
||||
int mtk_mutex_prepare(struct mtk_mutex *mutex);
|
||||
void mtk_mutex_add_comp(struct mtk_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id);
|
||||
void mtk_mutex_enable(struct mtk_mutex *mutex);
|
||||
void mtk_mutex_disable(struct mtk_mutex *mutex);
|
||||
void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
|
||||
enum mtk_ddp_comp_id id);
|
||||
void mtk_mutex_unprepare(struct mtk_mutex *mutex);
|
||||
void mtk_mutex_put(struct mtk_mutex *mutex);
|
||||
void mtk_mutex_acquire(struct mtk_mutex *mutex);
|
||||
void mtk_mutex_release(struct mtk_mutex *mutex);
|
||||
|
||||
#endif /* MTK_MUTEX_H */
|
Loading…
x
Reference in New Issue
Block a user