2 * Copyright (c) 2015 MediaTek Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include <linux/clk.h>
16 #include <linux/component.h>
17 #include <linux/of_device.h>
18 #include <linux/of_irq.h>
19 #include <linux/platform_device.h>
21 #include "mtk_drm_crtc.h"
22 #include "mtk_drm_ddp_comp.h"
24 #define DISP_REG_RDMA_INT_ENABLE 0x0000
25 #define DISP_REG_RDMA_INT_STATUS 0x0004
26 #define RDMA_TARGET_LINE_INT BIT(5)
27 #define RDMA_FIFO_UNDERFLOW_INT BIT(4)
28 #define RDMA_EOF_ABNORMAL_INT BIT(3)
29 #define RDMA_FRAME_END_INT BIT(2)
30 #define RDMA_FRAME_START_INT BIT(1)
31 #define RDMA_REG_UPDATE_INT BIT(0)
32 #define DISP_REG_RDMA_GLOBAL_CON 0x0010
33 #define RDMA_ENGINE_EN BIT(0)
34 #define RDMA_MODE_MEMORY BIT(1)
35 #define DISP_REG_RDMA_SIZE_CON_0 0x0014
36 #define RDMA_MATRIX_ENABLE BIT(17)
37 #define RDMA_MATRIX_INT_MTX_SEL GENMASK(23, 20)
38 #define RDMA_MATRIX_INT_MTX_BT601_to_RGB (6 << 20)
39 #define DISP_REG_RDMA_SIZE_CON_1 0x0018
40 #define DISP_REG_RDMA_TARGET_LINE 0x001c
41 #define DISP_RDMA_MEM_CON 0x0024
42 #define MEM_MODE_INPUT_FORMAT_RGB565 (0x000 << 4)
43 #define MEM_MODE_INPUT_FORMAT_RGB888 (0x001 << 4)
44 #define MEM_MODE_INPUT_FORMAT_RGBA8888 (0x002 << 4)
45 #define MEM_MODE_INPUT_FORMAT_ARGB8888 (0x003 << 4)
46 #define MEM_MODE_INPUT_FORMAT_UYVY (0x004 << 4)
47 #define MEM_MODE_INPUT_FORMAT_YUYV (0x005 << 4)
48 #define MEM_MODE_INPUT_SWAP BIT(8)
49 #define DISP_RDMA_MEM_SRC_PITCH 0x002c
50 #define DISP_RDMA_MEM_GMC_SETTING_0 0x0030
51 #define DISP_REG_RDMA_FIFO_CON 0x0040
52 #define RDMA_FIFO_UNDERFLOW_EN BIT(31)
53 #define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16)
54 #define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16)
55 #define RDMA_FIFO_SIZE(rdma) ((rdma)->data->fifo_size)
56 #define DISP_RDMA_MEM_START_ADDR 0x0f00
58 #define RDMA_MEM_GMC 0x40402020
60 struct mtk_disp_rdma_data
{
61 unsigned int fifo_size
;
65 * struct mtk_disp_rdma - DISP_RDMA driver structure
66 * @ddp_comp - structure containing type enum and hardware resources
67 * @crtc - associated crtc to report irq events to
69 struct mtk_disp_rdma
{
70 struct mtk_ddp_comp ddp_comp
;
71 struct drm_crtc
*crtc
;
72 const struct mtk_disp_rdma_data
*data
;
75 static inline struct mtk_disp_rdma
*comp_to_rdma(struct mtk_ddp_comp
*comp
)
77 return container_of(comp
, struct mtk_disp_rdma
, ddp_comp
);
80 static irqreturn_t
mtk_disp_rdma_irq_handler(int irq
, void *dev_id
)
82 struct mtk_disp_rdma
*priv
= dev_id
;
83 struct mtk_ddp_comp
*rdma
= &priv
->ddp_comp
;
85 /* Clear frame completion interrupt */
86 writel(0x0, rdma
->regs
+ DISP_REG_RDMA_INT_STATUS
);
91 mtk_crtc_ddp_irq(priv
->crtc
, rdma
);
96 static void rdma_update_bits(struct mtk_ddp_comp
*comp
, unsigned int reg
,
97 unsigned int mask
, unsigned int val
)
99 unsigned int tmp
= readl(comp
->regs
+ reg
);
101 tmp
= (tmp
& ~mask
) | (val
& mask
);
102 writel(tmp
, comp
->regs
+ reg
);
105 static void mtk_rdma_enable_vblank(struct mtk_ddp_comp
*comp
,
106 struct drm_crtc
*crtc
)
108 struct mtk_disp_rdma
*rdma
= comp_to_rdma(comp
);
111 rdma_update_bits(comp
, DISP_REG_RDMA_INT_ENABLE
, RDMA_FRAME_END_INT
,
115 static void mtk_rdma_disable_vblank(struct mtk_ddp_comp
*comp
)
117 struct mtk_disp_rdma
*rdma
= comp_to_rdma(comp
);
120 rdma_update_bits(comp
, DISP_REG_RDMA_INT_ENABLE
, RDMA_FRAME_END_INT
, 0);
123 static void mtk_rdma_start(struct mtk_ddp_comp
*comp
)
125 rdma_update_bits(comp
, DISP_REG_RDMA_GLOBAL_CON
, RDMA_ENGINE_EN
,
129 static void mtk_rdma_stop(struct mtk_ddp_comp
*comp
)
131 rdma_update_bits(comp
, DISP_REG_RDMA_GLOBAL_CON
, RDMA_ENGINE_EN
, 0);
134 static void mtk_rdma_config(struct mtk_ddp_comp
*comp
, unsigned int width
,
135 unsigned int height
, unsigned int vrefresh
,
138 unsigned int threshold
;
140 struct mtk_disp_rdma
*rdma
= comp_to_rdma(comp
);
142 rdma_update_bits(comp
, DISP_REG_RDMA_SIZE_CON_0
, 0xfff, width
);
143 rdma_update_bits(comp
, DISP_REG_RDMA_SIZE_CON_1
, 0xfffff, height
);
146 * Enable FIFO underflow since DSI and DPI can't be blocked.
147 * Keep the FIFO pseudo size reset default of 8 KiB. Set the
148 * output threshold to 6 microseconds with 7/6 overhead to
149 * account for blanking, and with a pixel depth of 4 bytes:
151 threshold
= width
* height
* vrefresh
* 4 * 7 / 1000000;
152 reg
= RDMA_FIFO_UNDERFLOW_EN
|
153 RDMA_FIFO_PSEUDO_SIZE(RDMA_FIFO_SIZE(rdma
)) |
154 RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold
);
155 writel(reg
, comp
->regs
+ DISP_REG_RDMA_FIFO_CON
);
158 static unsigned int rdma_fmt_convert(struct mtk_disp_rdma
*rdma
,
161 /* The return value in switch "MEM_MODE_INPUT_FORMAT_XXX"
162 * is defined in mediatek HW data sheet.
163 * The alphabet order in XXX is no relation to data
164 * arrangement in memory.
168 case DRM_FORMAT_RGB565
:
169 return MEM_MODE_INPUT_FORMAT_RGB565
;
170 case DRM_FORMAT_BGR565
:
171 return MEM_MODE_INPUT_FORMAT_RGB565
| MEM_MODE_INPUT_SWAP
;
172 case DRM_FORMAT_RGB888
:
173 return MEM_MODE_INPUT_FORMAT_RGB888
;
174 case DRM_FORMAT_BGR888
:
175 return MEM_MODE_INPUT_FORMAT_RGB888
| MEM_MODE_INPUT_SWAP
;
176 case DRM_FORMAT_RGBX8888
:
177 case DRM_FORMAT_RGBA8888
:
178 return MEM_MODE_INPUT_FORMAT_ARGB8888
;
179 case DRM_FORMAT_BGRX8888
:
180 case DRM_FORMAT_BGRA8888
:
181 return MEM_MODE_INPUT_FORMAT_ARGB8888
| MEM_MODE_INPUT_SWAP
;
182 case DRM_FORMAT_XRGB8888
:
183 case DRM_FORMAT_ARGB8888
:
184 return MEM_MODE_INPUT_FORMAT_RGBA8888
;
185 case DRM_FORMAT_XBGR8888
:
186 case DRM_FORMAT_ABGR8888
:
187 return MEM_MODE_INPUT_FORMAT_RGBA8888
| MEM_MODE_INPUT_SWAP
;
188 case DRM_FORMAT_UYVY
:
189 return MEM_MODE_INPUT_FORMAT_UYVY
;
190 case DRM_FORMAT_YUYV
:
191 return MEM_MODE_INPUT_FORMAT_YUYV
;
195 static unsigned int mtk_rdma_layer_nr(struct mtk_ddp_comp
*comp
)
200 static void mtk_rdma_layer_config(struct mtk_ddp_comp
*comp
, unsigned int idx
,
201 struct mtk_plane_state
*state
)
203 struct mtk_disp_rdma
*rdma
= comp_to_rdma(comp
);
204 struct mtk_plane_pending_state
*pending
= &state
->pending
;
205 unsigned int addr
= pending
->addr
;
206 unsigned int pitch
= pending
->pitch
& 0xffff;
207 unsigned int fmt
= pending
->format
;
210 con
= rdma_fmt_convert(rdma
, fmt
);
211 writel_relaxed(con
, comp
->regs
+ DISP_RDMA_MEM_CON
);
213 if (fmt
== DRM_FORMAT_UYVY
|| fmt
== DRM_FORMAT_YUYV
) {
214 rdma_update_bits(comp
, DISP_REG_RDMA_SIZE_CON_0
,
215 RDMA_MATRIX_ENABLE
, RDMA_MATRIX_ENABLE
);
216 rdma_update_bits(comp
, DISP_REG_RDMA_SIZE_CON_0
,
217 RDMA_MATRIX_INT_MTX_SEL
,
218 RDMA_MATRIX_INT_MTX_BT601_to_RGB
);
220 rdma_update_bits(comp
, DISP_REG_RDMA_SIZE_CON_0
,
221 RDMA_MATRIX_ENABLE
, 0);
224 writel_relaxed(addr
, comp
->regs
+ DISP_RDMA_MEM_START_ADDR
);
225 writel_relaxed(pitch
, comp
->regs
+ DISP_RDMA_MEM_SRC_PITCH
);
226 writel(RDMA_MEM_GMC
, comp
->regs
+ DISP_RDMA_MEM_GMC_SETTING_0
);
227 rdma_update_bits(comp
, DISP_REG_RDMA_GLOBAL_CON
,
228 RDMA_MODE_MEMORY
, RDMA_MODE_MEMORY
);
231 static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs
= {
232 .config
= mtk_rdma_config
,
233 .start
= mtk_rdma_start
,
234 .stop
= mtk_rdma_stop
,
235 .enable_vblank
= mtk_rdma_enable_vblank
,
236 .disable_vblank
= mtk_rdma_disable_vblank
,
237 .layer_nr
= mtk_rdma_layer_nr
,
238 .layer_config
= mtk_rdma_layer_config
,
241 static int mtk_disp_rdma_bind(struct device
*dev
, struct device
*master
,
244 struct mtk_disp_rdma
*priv
= dev_get_drvdata(dev
);
245 struct drm_device
*drm_dev
= data
;
248 ret
= mtk_ddp_comp_register(drm_dev
, &priv
->ddp_comp
);
250 dev_err(dev
, "Failed to register component %pOF: %d\n",
259 static void mtk_disp_rdma_unbind(struct device
*dev
, struct device
*master
,
262 struct mtk_disp_rdma
*priv
= dev_get_drvdata(dev
);
263 struct drm_device
*drm_dev
= data
;
265 mtk_ddp_comp_unregister(drm_dev
, &priv
->ddp_comp
);
268 static const struct component_ops mtk_disp_rdma_component_ops
= {
269 .bind
= mtk_disp_rdma_bind
,
270 .unbind
= mtk_disp_rdma_unbind
,
273 static int mtk_disp_rdma_probe(struct platform_device
*pdev
)
275 struct device
*dev
= &pdev
->dev
;
276 struct mtk_disp_rdma
*priv
;
281 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
285 irq
= platform_get_irq(pdev
, 0);
289 comp_id
= mtk_ddp_comp_get_id(dev
->of_node
, MTK_DISP_RDMA
);
291 dev_err(dev
, "Failed to identify by alias: %d\n", comp_id
);
295 ret
= mtk_ddp_comp_init(dev
, dev
->of_node
, &priv
->ddp_comp
, comp_id
,
296 &mtk_disp_rdma_funcs
);
298 dev_err(dev
, "Failed to initialize component: %d\n", ret
);
302 /* Disable and clear pending interrupts */
303 writel(0x0, priv
->ddp_comp
.regs
+ DISP_REG_RDMA_INT_ENABLE
);
304 writel(0x0, priv
->ddp_comp
.regs
+ DISP_REG_RDMA_INT_STATUS
);
306 ret
= devm_request_irq(dev
, irq
, mtk_disp_rdma_irq_handler
,
307 IRQF_TRIGGER_NONE
, dev_name(dev
), priv
);
309 dev_err(dev
, "Failed to request irq %d: %d\n", irq
, ret
);
313 priv
->data
= of_device_get_match_data(dev
);
315 platform_set_drvdata(pdev
, priv
);
317 ret
= component_add(dev
, &mtk_disp_rdma_component_ops
);
319 dev_err(dev
, "Failed to add component: %d\n", ret
);
324 static int mtk_disp_rdma_remove(struct platform_device
*pdev
)
326 component_del(&pdev
->dev
, &mtk_disp_rdma_component_ops
);
331 static const struct mtk_disp_rdma_data mt2701_rdma_driver_data
= {
335 static const struct mtk_disp_rdma_data mt8173_rdma_driver_data
= {
339 static const struct of_device_id mtk_disp_rdma_driver_dt_match
[] = {
340 { .compatible
= "mediatek,mt2701-disp-rdma",
341 .data
= &mt2701_rdma_driver_data
},
342 { .compatible
= "mediatek,mt8173-disp-rdma",
343 .data
= &mt8173_rdma_driver_data
},
346 MODULE_DEVICE_TABLE(of
, mtk_disp_rdma_driver_dt_match
);
348 struct platform_driver mtk_disp_rdma_driver
= {
349 .probe
= mtk_disp_rdma_probe
,
350 .remove
= mtk_disp_rdma_remove
,
352 .name
= "mediatek-disp-rdma",
353 .owner
= THIS_MODULE
,
354 .of_match_table
= mtk_disp_rdma_driver_dt_match
,