Skip to content

Commit bd448b8

Browse files
jason-jh.linChun-Kuang Hu
authored andcommitted
drm/mediatek: Add MERGE support for mediatek-drm
Add MERGE engine file: MERGE module is used to merge two slice-per-line inputs into one side-by-side output. Link: https://patchwork.kernel.org/project/linux-mediatek/patch/[email protected]/ Signed-off-by: jason-jh.lin <[email protected]> Acked-by: AngeloGioacchino Del Regno <[email protected]> Signed-off-by: Chun-Kuang Hu <[email protected]>
1 parent b7fb767 commit bd448b8

File tree

7 files changed

+276
-1
lines changed

7 files changed

+276
-1
lines changed

drivers/gpu/drm/mediatek/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mediatek-drm-y := mtk_disp_aal.o \
44
mtk_disp_ccorr.o \
55
mtk_disp_color.o \
66
mtk_disp_gamma.o \
7+
mtk_disp_merge.o \
78
mtk_disp_ovl.o \
89
mtk_disp_rdma.o \
910
mtk_drm_crtc.o \

drivers/gpu/drm/mediatek/mtk_disp_drv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ void mtk_gamma_set_common(void __iomem *regs, struct drm_crtc_state *state, bool
5555
void mtk_gamma_start(struct device *dev);
5656
void mtk_gamma_stop(struct device *dev);
5757

58+
int mtk_merge_clk_enable(struct device *dev);
59+
void mtk_merge_clk_disable(struct device *dev);
60+
void mtk_merge_config(struct device *dev, unsigned int width,
61+
unsigned int height, unsigned int vrefresh,
62+
unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
63+
void mtk_merge_start(struct device *dev);
64+
void mtk_merge_stop(struct device *dev);
65+
5866
void mtk_ovl_bgclr_in_on(struct device *dev);
5967
void mtk_ovl_bgclr_in_off(struct device *dev);
6068
void mtk_ovl_bypass_shadow(struct device *dev);
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2021 MediaTek Inc.
4+
*/
5+
6+
#include <linux/clk.h>
7+
#include <linux/component.h>
8+
#include <linux/of_device.h>
9+
#include <linux/of_irq.h>
10+
#include <linux/platform_device.h>
11+
#include <linux/soc/mediatek/mtk-cmdq.h>
12+
13+
#include "mtk_drm_ddp_comp.h"
14+
#include "mtk_drm_drv.h"
15+
#include "mtk_disp_drv.h"
16+
17+
#define DISP_REG_MERGE_CTRL 0x000
18+
#define MERGE_EN 1
19+
#define DISP_REG_MERGE_CFG_0 0x010
20+
#define DISP_REG_MERGE_CFG_4 0x020
21+
#define DISP_REG_MERGE_CFG_10 0x038
22+
/* no swap */
23+
#define SWAP_MODE 0
24+
#define FLD_SWAP_MODE GENMASK(4, 0)
25+
#define DISP_REG_MERGE_CFG_12 0x040
26+
#define CFG_10_10_1PI_2PO_BUF_MODE 6
27+
#define CFG_10_10_2PI_2PO_BUF_MODE 8
28+
#define FLD_CFG_MERGE_MODE GENMASK(4, 0)
29+
#define DISP_REG_MERGE_CFG_24 0x070
30+
#define DISP_REG_MERGE_CFG_25 0x074
31+
#define DISP_REG_MERGE_CFG_36 0x0a0
32+
#define ULTRA_EN BIT(0)
33+
#define PREULTRA_EN BIT(4)
34+
#define DISP_REG_MERGE_CFG_37 0x0a4
35+
/* 0: Off, 1: SRAM0, 2: SRAM1, 3: SRAM0 + SRAM1 */
36+
#define BUFFER_MODE 3
37+
#define FLD_BUFFER_MODE GENMASK(1, 0)
38+
/*
39+
* For the ultra and preultra settings, 6us ~ 9us is experience value
40+
* and the maximum frequency of mmsys clock is 594MHz.
41+
*/
42+
#define DISP_REG_MERGE_CFG_40 0x0b0
43+
/* 6 us, 594M pixel/sec */
44+
#define ULTRA_TH_LOW (6 * 594)
45+
/* 8 us, 594M pixel/sec */
46+
#define ULTRA_TH_HIGH (8 * 594)
47+
#define FLD_ULTRA_TH_LOW GENMASK(15, 0)
48+
#define FLD_ULTRA_TH_HIGH GENMASK(31, 16)
49+
#define DISP_REG_MERGE_CFG_41 0x0b4
50+
/* 8 us, 594M pixel/sec */
51+
#define PREULTRA_TH_LOW (8 * 594)
52+
/* 9 us, 594M pixel/sec */
53+
#define PREULTRA_TH_HIGH (9 * 594)
54+
#define FLD_PREULTRA_TH_LOW GENMASK(15, 0)
55+
#define FLD_PREULTRA_TH_HIGH GENMASK(31, 16)
56+
57+
struct mtk_disp_merge {
58+
void __iomem *regs;
59+
struct clk *clk;
60+
struct clk *async_clk;
61+
struct cmdq_client_reg cmdq_reg;
62+
bool fifo_en;
63+
};
64+
65+
void mtk_merge_start(struct device *dev)
66+
{
67+
struct mtk_disp_merge *priv = dev_get_drvdata(dev);
68+
69+
writel(MERGE_EN, priv->regs + DISP_REG_MERGE_CTRL);
70+
}
71+
72+
void mtk_merge_stop(struct device *dev)
73+
{
74+
struct mtk_disp_merge *priv = dev_get_drvdata(dev);
75+
76+
writel(0x0, priv->regs + DISP_REG_MERGE_CTRL);
77+
}
78+
79+
static void mtk_merge_fifo_setting(struct mtk_disp_merge *priv,
80+
struct cmdq_pkt *cmdq_pkt)
81+
{
82+
mtk_ddp_write(cmdq_pkt, ULTRA_EN | PREULTRA_EN,
83+
&priv->cmdq_reg, priv->regs, DISP_REG_MERGE_CFG_36);
84+
85+
mtk_ddp_write_mask(cmdq_pkt, BUFFER_MODE,
86+
&priv->cmdq_reg, priv->regs, DISP_REG_MERGE_CFG_37,
87+
FLD_BUFFER_MODE);
88+
89+
mtk_ddp_write_mask(cmdq_pkt, ULTRA_TH_LOW | ULTRA_TH_HIGH << 16,
90+
&priv->cmdq_reg, priv->regs, DISP_REG_MERGE_CFG_40,
91+
FLD_ULTRA_TH_LOW | FLD_ULTRA_TH_HIGH);
92+
93+
mtk_ddp_write_mask(cmdq_pkt, PREULTRA_TH_LOW | PREULTRA_TH_HIGH << 16,
94+
&priv->cmdq_reg, priv->regs, DISP_REG_MERGE_CFG_41,
95+
FLD_PREULTRA_TH_LOW | FLD_PREULTRA_TH_HIGH);
96+
}
97+
98+
void mtk_merge_config(struct device *dev, unsigned int w,
99+
unsigned int h, unsigned int vrefresh,
100+
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
101+
{
102+
struct mtk_disp_merge *priv = dev_get_drvdata(dev);
103+
unsigned int mode = CFG_10_10_1PI_2PO_BUF_MODE;
104+
105+
if (!h || !w) {
106+
dev_err(dev, "%s: input width(%d) or height(%d) is invalid\n", __func__, w, h);
107+
return;
108+
}
109+
110+
if (priv->fifo_en) {
111+
mtk_merge_fifo_setting(priv, cmdq_pkt);
112+
mode = CFG_10_10_2PI_2PO_BUF_MODE;
113+
}
114+
115+
mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
116+
DISP_REG_MERGE_CFG_0);
117+
mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
118+
DISP_REG_MERGE_CFG_4);
119+
mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
120+
DISP_REG_MERGE_CFG_24);
121+
mtk_ddp_write(cmdq_pkt, h << 16 | w, &priv->cmdq_reg, priv->regs,
122+
DISP_REG_MERGE_CFG_25);
123+
mtk_ddp_write_mask(cmdq_pkt, SWAP_MODE, &priv->cmdq_reg, priv->regs,
124+
DISP_REG_MERGE_CFG_10, FLD_SWAP_MODE);
125+
mtk_ddp_write_mask(cmdq_pkt, mode, &priv->cmdq_reg, priv->regs,
126+
DISP_REG_MERGE_CFG_12, FLD_CFG_MERGE_MODE);
127+
}
128+
129+
int mtk_merge_clk_enable(struct device *dev)
130+
{
131+
int ret = 0;
132+
struct mtk_disp_merge *priv = dev_get_drvdata(dev);
133+
134+
ret = clk_prepare_enable(priv->clk);
135+
if (ret) {
136+
dev_err(dev, "merge clk prepare enable failed\n");
137+
return ret;
138+
}
139+
140+
ret = clk_prepare_enable(priv->async_clk);
141+
if (ret) {
142+
/* should clean up the state of priv->clk */
143+
clk_disable_unprepare(priv->clk);
144+
145+
dev_err(dev, "async clk prepare enable failed\n");
146+
return ret;
147+
}
148+
149+
return ret;
150+
}
151+
152+
void mtk_merge_clk_disable(struct device *dev)
153+
{
154+
struct mtk_disp_merge *priv = dev_get_drvdata(dev);
155+
156+
clk_disable_unprepare(priv->async_clk);
157+
clk_disable_unprepare(priv->clk);
158+
}
159+
160+
static int mtk_disp_merge_bind(struct device *dev, struct device *master,
161+
void *data)
162+
{
163+
return 0;
164+
}
165+
166+
static void mtk_disp_merge_unbind(struct device *dev, struct device *master,
167+
void *data)
168+
{
169+
}
170+
171+
static const struct component_ops mtk_disp_merge_component_ops = {
172+
.bind = mtk_disp_merge_bind,
173+
.unbind = mtk_disp_merge_unbind,
174+
};
175+
176+
static int mtk_disp_merge_probe(struct platform_device *pdev)
177+
{
178+
struct device *dev = &pdev->dev;
179+
struct resource *res;
180+
struct mtk_disp_merge *priv;
181+
int ret;
182+
183+
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
184+
if (!priv)
185+
return -ENOMEM;
186+
187+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
188+
priv->regs = devm_ioremap_resource(dev, res);
189+
if (IS_ERR(priv->regs)) {
190+
dev_err(dev, "failed to ioremap merge\n");
191+
return PTR_ERR(priv->regs);
192+
}
193+
194+
priv->clk = devm_clk_get(dev, NULL);
195+
if (IS_ERR(priv->clk)) {
196+
dev_err(dev, "failed to get merge clk\n");
197+
return PTR_ERR(priv->clk);
198+
}
199+
200+
priv->async_clk = devm_clk_get_optional(dev, "merge_async");
201+
if (IS_ERR(priv->async_clk)) {
202+
dev_err(dev, "failed to get merge async clock\n");
203+
return PTR_ERR(priv->async_clk);
204+
}
205+
206+
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
207+
ret = cmdq_dev_get_client_reg(dev, &priv->cmdq_reg, 0);
208+
if (ret)
209+
dev_dbg(dev, "get mediatek,gce-client-reg fail!\n");
210+
#endif
211+
212+
priv->fifo_en = of_property_read_bool(dev->of_node,
213+
"mediatek,merge-fifo-en");
214+
215+
platform_set_drvdata(pdev, priv);
216+
217+
ret = component_add(dev, &mtk_disp_merge_component_ops);
218+
if (ret != 0)
219+
dev_err(dev, "Failed to add component: %d\n", ret);
220+
221+
return ret;
222+
}
223+
224+
static int mtk_disp_merge_remove(struct platform_device *pdev)
225+
{
226+
component_del(&pdev->dev, &mtk_disp_merge_component_ops);
227+
228+
return 0;
229+
}
230+
231+
static const struct of_device_id mtk_disp_merge_driver_dt_match[] = {
232+
{ .compatible = "mediatek,mt8195-disp-merge", },
233+
{},
234+
};
235+
236+
MODULE_DEVICE_TABLE(of, mtk_disp_merge_driver_dt_match);
237+
238+
struct platform_driver mtk_disp_merge_driver = {
239+
.probe = mtk_disp_merge_probe,
240+
.remove = mtk_disp_merge_remove,
241+
.driver = {
242+
.name = "mediatek-disp-merge",
243+
.owner = THIS_MODULE,
244+
.of_match_table = mtk_disp_merge_driver_dt_match,
245+
},
246+
};

drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ static const struct mtk_ddp_comp_funcs ddp_gamma = {
328328
.stop = mtk_gamma_stop,
329329
};
330330

331+
static const struct mtk_ddp_comp_funcs ddp_merge = {
332+
.clk_enable = mtk_merge_clk_enable,
333+
.clk_disable = mtk_merge_clk_disable,
334+
.start = mtk_merge_start,
335+
.stop = mtk_merge_stop,
336+
.config = mtk_merge_config,
337+
};
338+
331339
static const struct mtk_ddp_comp_funcs ddp_od = {
332340
.clk_enable = mtk_ddp_clk_enable,
333341
.clk_disable = mtk_ddp_clk_disable,
@@ -389,6 +397,7 @@ static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
389397
[MTK_DISP_DITHER] = "dither",
390398
[MTK_DISP_DSC] = "dsc",
391399
[MTK_DISP_GAMMA] = "gamma",
400+
[MTK_DISP_MERGE] = "merge",
392401
[MTK_DISP_MUTEX] = "mutex",
393402
[MTK_DISP_OD] = "od",
394403
[MTK_DISP_OVL] = "ovl",
@@ -425,6 +434,12 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
425434
[DDP_COMPONENT_DSI2] = { MTK_DSI, 2, &ddp_dsi },
426435
[DDP_COMPONENT_DSI3] = { MTK_DSI, 3, &ddp_dsi },
427436
[DDP_COMPONENT_GAMMA] = { MTK_DISP_GAMMA, 0, &ddp_gamma },
437+
[DDP_COMPONENT_MERGE0] = { MTK_DISP_MERGE, 0, &ddp_merge },
438+
[DDP_COMPONENT_MERGE1] = { MTK_DISP_MERGE, 1, &ddp_merge },
439+
[DDP_COMPONENT_MERGE2] = { MTK_DISP_MERGE, 2, &ddp_merge },
440+
[DDP_COMPONENT_MERGE3] = { MTK_DISP_MERGE, 3, &ddp_merge },
441+
[DDP_COMPONENT_MERGE4] = { MTK_DISP_MERGE, 4, &ddp_merge },
442+
[DDP_COMPONENT_MERGE5] = { MTK_DISP_MERGE, 5, &ddp_merge },
428443
[DDP_COMPONENT_OD0] = { MTK_DISP_OD, 0, &ddp_od },
429444
[DDP_COMPONENT_OD1] = { MTK_DISP_OD, 1, &ddp_od },
430445
[DDP_COMPONENT_OVL0] = { MTK_DISP_OVL, 0, &ddp_ovl },
@@ -527,6 +542,7 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
527542
type == MTK_DISP_CCORR ||
528543
type == MTK_DISP_COLOR ||
529544
type == MTK_DISP_GAMMA ||
545+
type == MTK_DISP_MERGE ||
530546
type == MTK_DISP_OVL ||
531547
type == MTK_DISP_OVL_2L ||
532548
type == MTK_DISP_PWM ||

drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum mtk_ddp_comp_type {
2525
MTK_DISP_DITHER,
2626
MTK_DISP_DSC,
2727
MTK_DISP_GAMMA,
28+
MTK_DISP_MERGE,
2829
MTK_DISP_MUTEX,
2930
MTK_DISP_OD,
3031
MTK_DISP_OVL,

drivers/gpu/drm/mediatek/mtk_drm_drv.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,14 +628,15 @@ static int mtk_drm_probe(struct platform_device *pdev)
628628
private->comp_node[comp_id] = of_node_get(node);
629629

630630
/*
631-
* Currently only the AAL, CCORR, COLOR, GAMMA, OVL, RDMA, DSI, and DPI
631+
* Currently only the AAL, CCORR, COLOR, GAMMA, MERGE, OVL, RDMA, DSI, and DPI
632632
* blocks have separate component platform drivers and initialize their own
633633
* DDP component structure. The others are initialized here.
634634
*/
635635
if (comp_type == MTK_DISP_AAL ||
636636
comp_type == MTK_DISP_CCORR ||
637637
comp_type == MTK_DISP_COLOR ||
638638
comp_type == MTK_DISP_GAMMA ||
639+
comp_type == MTK_DISP_MERGE ||
639640
comp_type == MTK_DISP_OVL ||
640641
comp_type == MTK_DISP_OVL_2L ||
641642
comp_type == MTK_DISP_RDMA ||
@@ -734,6 +735,7 @@ static struct platform_driver * const mtk_drm_drivers[] = {
734735
&mtk_disp_ccorr_driver,
735736
&mtk_disp_color_driver,
736737
&mtk_disp_gamma_driver,
738+
&mtk_disp_merge_driver,
737739
&mtk_disp_ovl_driver,
738740
&mtk_disp_rdma_driver,
739741
&mtk_dpi_driver,

drivers/gpu/drm/mediatek/mtk_drm_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern struct platform_driver mtk_disp_aal_driver;
5050
extern struct platform_driver mtk_disp_ccorr_driver;
5151
extern struct platform_driver mtk_disp_color_driver;
5252
extern struct platform_driver mtk_disp_gamma_driver;
53+
extern struct platform_driver mtk_disp_merge_driver;
5354
extern struct platform_driver mtk_disp_ovl_driver;
5455
extern struct platform_driver mtk_disp_rdma_driver;
5556
extern struct platform_driver mtk_dpi_driver;

0 commit comments

Comments
 (0)