hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
....@@ -1,22 +1,17 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2015 MediaTek Inc.
3
- *
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.
7
- *
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.
124 */
135
14
-#include <drm/drmP.h>
6
+#include <drm/drm_fourcc.h>
7
+
158 #include <linux/clk.h>
169 #include <linux/component.h>
10
+#include <linux/module.h>
1711 #include <linux/of_device.h>
1812 #include <linux/of_irq.h>
1913 #include <linux/platform_device.h>
14
+#include <linux/soc/mediatek/mtk-cmdq.h>
2015
2116 #include "mtk_drm_crtc.h"
2217 #include "mtk_drm_ddp_comp.h"
....@@ -27,6 +22,8 @@
2722 #define DISP_REG_OVL_EN 0x000c
2823 #define DISP_REG_OVL_RST 0x0014
2924 #define DISP_REG_OVL_ROI_SIZE 0x0020
25
+#define DISP_REG_OVL_DATAPATH_CON 0x0024
26
+#define OVL_BGCLR_SEL_IN BIT(2)
3027 #define DISP_REG_OVL_ROI_BGCLR 0x0028
3128 #define DISP_REG_OVL_SRC_CON 0x002c
3229 #define DISP_REG_OVL_CON(n) (0x0030 + 0x20 * (n))
....@@ -39,7 +36,9 @@
3936 #define DISP_REG_OVL_ADDR_MT8173 0x0f40
4037 #define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))
4138
42
-#define OVL_RDMA_MEM_GMC 0x40402020
39
+#define GMC_THRESHOLD_BITS 16
40
+#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
41
+#define GMC_THRESHOLD_LOW ((1 << GMC_THRESHOLD_BITS) / 8)
4342
4443 #define OVL_CON_BYTE_SWAP BIT(24)
4544 #define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
....@@ -54,9 +53,13 @@
5453 OVL_CON_CLRFMT_RGB : 0)
5554 #define OVL_CON_AEN BIT(8)
5655 #define OVL_CON_ALPHA 0xff
56
+#define OVL_CON_VIRT_FLIP BIT(9)
57
+#define OVL_CON_HORZ_FLIP BIT(10)
5758
5859 struct mtk_disp_ovl_data {
5960 unsigned int addr;
61
+ unsigned int gmc_bits;
62
+ unsigned int layer_nr;
6063 bool fmt_rgb565_is_0;
6164 };
6265
....@@ -122,42 +125,90 @@
122125
123126 static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w,
124127 unsigned int h, unsigned int vrefresh,
125
- unsigned int bpc)
128
+ unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
126129 {
127130 if (w != 0 && h != 0)
128
- writel_relaxed(h << 16 | w, comp->regs + DISP_REG_OVL_ROI_SIZE);
129
- writel_relaxed(0x0, comp->regs + DISP_REG_OVL_ROI_BGCLR);
131
+ mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, comp,
132
+ DISP_REG_OVL_ROI_SIZE);
133
+ mtk_ddp_write_relaxed(cmdq_pkt, 0x0, comp, DISP_REG_OVL_ROI_BGCLR);
130134
131
- writel(0x1, comp->regs + DISP_REG_OVL_RST);
132
- writel(0x0, comp->regs + DISP_REG_OVL_RST);
135
+ mtk_ddp_write(cmdq_pkt, 0x1, comp, DISP_REG_OVL_RST);
136
+ mtk_ddp_write(cmdq_pkt, 0x0, comp, DISP_REG_OVL_RST);
133137 }
134138
135139 static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp)
136140 {
137
- return 4;
141
+ struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
142
+
143
+ return ovl->data->layer_nr;
138144 }
139145
140
-static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx)
146
+static unsigned int mtk_ovl_supported_rotations(struct mtk_ddp_comp *comp)
141147 {
142
- unsigned int reg;
143
-
144
- writel(0x1, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
145
- writel(OVL_RDMA_MEM_GMC, comp->regs + DISP_REG_OVL_RDMA_GMC(idx));
146
-
147
- reg = readl(comp->regs + DISP_REG_OVL_SRC_CON);
148
- reg = reg | BIT(idx);
149
- writel(reg, comp->regs + DISP_REG_OVL_SRC_CON);
148
+ return DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
149
+ DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
150150 }
151151
152
-static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
152
+static int mtk_ovl_layer_check(struct mtk_ddp_comp *comp, unsigned int idx,
153
+ struct mtk_plane_state *mtk_state)
153154 {
154
- unsigned int reg;
155
+ struct drm_plane_state *state = &mtk_state->base;
156
+ unsigned int rotation = 0;
155157
156
- reg = readl(comp->regs + DISP_REG_OVL_SRC_CON);
157
- reg = reg & ~BIT(idx);
158
- writel(reg, comp->regs + DISP_REG_OVL_SRC_CON);
158
+ rotation = drm_rotation_simplify(state->rotation,
159
+ DRM_MODE_ROTATE_0 |
160
+ DRM_MODE_REFLECT_X |
161
+ DRM_MODE_REFLECT_Y);
162
+ rotation &= ~DRM_MODE_ROTATE_0;
159163
160
- writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
164
+ /* We can only do reflection, not rotation */
165
+ if ((rotation & DRM_MODE_ROTATE_MASK) != 0)
166
+ return -EINVAL;
167
+
168
+ /*
169
+ * TODO: Rotating/reflecting YUV buffers is not supported at this time.
170
+ * Only RGB[AX] variants are supported.
171
+ */
172
+ if (state->fb->format->is_yuv && rotation != 0)
173
+ return -EINVAL;
174
+
175
+ state->rotation = rotation;
176
+
177
+ return 0;
178
+}
179
+
180
+static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx,
181
+ struct cmdq_pkt *cmdq_pkt)
182
+{
183
+ unsigned int gmc_thrshd_l;
184
+ unsigned int gmc_thrshd_h;
185
+ unsigned int gmc_value;
186
+ struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
187
+
188
+ mtk_ddp_write(cmdq_pkt, 0x1, comp,
189
+ DISP_REG_OVL_RDMA_CTRL(idx));
190
+ gmc_thrshd_l = GMC_THRESHOLD_LOW >>
191
+ (GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
192
+ gmc_thrshd_h = GMC_THRESHOLD_HIGH >>
193
+ (GMC_THRESHOLD_BITS - ovl->data->gmc_bits);
194
+ if (ovl->data->gmc_bits == 10)
195
+ gmc_value = gmc_thrshd_h | gmc_thrshd_h << 16;
196
+ else
197
+ gmc_value = gmc_thrshd_l | gmc_thrshd_l << 8 |
198
+ gmc_thrshd_h << 16 | gmc_thrshd_h << 24;
199
+ mtk_ddp_write(cmdq_pkt, gmc_value,
200
+ comp, DISP_REG_OVL_RDMA_GMC(idx));
201
+ mtk_ddp_write_mask(cmdq_pkt, BIT(idx), comp,
202
+ DISP_REG_OVL_SRC_CON, BIT(idx));
203
+}
204
+
205
+static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx,
206
+ struct cmdq_pkt *cmdq_pkt)
207
+{
208
+ mtk_ddp_write_mask(cmdq_pkt, 0, comp,
209
+ DISP_REG_OVL_SRC_CON, BIT(idx));
210
+ mtk_ddp_write(cmdq_pkt, 0, comp,
211
+ DISP_REG_OVL_RDMA_CTRL(idx));
161212 }
162213
163214 static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt)
....@@ -197,7 +248,8 @@
197248 }
198249
199250 static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
200
- struct mtk_plane_state *state)
251
+ struct mtk_plane_state *state,
252
+ struct cmdq_pkt *cmdq_pkt)
201253 {
202254 struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
203255 struct mtk_plane_pending_state *pending = &state->pending;
....@@ -208,21 +260,55 @@
208260 unsigned int src_size = (pending->height << 16) | pending->width;
209261 unsigned int con;
210262
211
- if (!pending->enable)
212
- mtk_ovl_layer_off(comp, idx);
263
+ if (!pending->enable) {
264
+ mtk_ovl_layer_off(comp, idx, cmdq_pkt);
265
+ return;
266
+ }
213267
214268 con = ovl_fmt_convert(ovl, fmt);
215
- if (idx != 0)
269
+ if (state->base.fb && state->base.fb->format->has_alpha)
216270 con |= OVL_CON_AEN | OVL_CON_ALPHA;
217271
218
- writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx));
219
- writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
220
- writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
221
- writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
222
- writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(ovl, idx));
272
+ if (pending->rotation & DRM_MODE_REFLECT_Y) {
273
+ con |= OVL_CON_VIRT_FLIP;
274
+ addr += (pending->height - 1) * pending->pitch;
275
+ }
223276
224
- if (pending->enable)
225
- mtk_ovl_layer_on(comp, idx);
277
+ if (pending->rotation & DRM_MODE_REFLECT_X) {
278
+ con |= OVL_CON_HORZ_FLIP;
279
+ addr += pending->pitch - 1;
280
+ }
281
+
282
+ mtk_ddp_write_relaxed(cmdq_pkt, con, comp,
283
+ DISP_REG_OVL_CON(idx));
284
+ mtk_ddp_write_relaxed(cmdq_pkt, pitch, comp,
285
+ DISP_REG_OVL_PITCH(idx));
286
+ mtk_ddp_write_relaxed(cmdq_pkt, src_size, comp,
287
+ DISP_REG_OVL_SRC_SIZE(idx));
288
+ mtk_ddp_write_relaxed(cmdq_pkt, offset, comp,
289
+ DISP_REG_OVL_OFFSET(idx));
290
+ mtk_ddp_write_relaxed(cmdq_pkt, addr, comp,
291
+ DISP_REG_OVL_ADDR(ovl, idx));
292
+
293
+ mtk_ovl_layer_on(comp, idx, cmdq_pkt);
294
+}
295
+
296
+static void mtk_ovl_bgclr_in_on(struct mtk_ddp_comp *comp)
297
+{
298
+ unsigned int reg;
299
+
300
+ reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
301
+ reg = reg | OVL_BGCLR_SEL_IN;
302
+ writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
303
+}
304
+
305
+static void mtk_ovl_bgclr_in_off(struct mtk_ddp_comp *comp)
306
+{
307
+ unsigned int reg;
308
+
309
+ reg = readl(comp->regs + DISP_REG_OVL_DATAPATH_CON);
310
+ reg = reg & ~OVL_BGCLR_SEL_IN;
311
+ writel(reg, comp->regs + DISP_REG_OVL_DATAPATH_CON);
226312 }
227313
228314 static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
....@@ -231,10 +317,12 @@
231317 .stop = mtk_ovl_stop,
232318 .enable_vblank = mtk_ovl_enable_vblank,
233319 .disable_vblank = mtk_ovl_disable_vblank,
320
+ .supported_rotations = mtk_ovl_supported_rotations,
234321 .layer_nr = mtk_ovl_layer_nr,
235
- .layer_on = mtk_ovl_layer_on,
236
- .layer_off = mtk_ovl_layer_off,
322
+ .layer_check = mtk_ovl_layer_check,
237323 .layer_config = mtk_ovl_layer_config,
324
+ .bgclr_in_on = mtk_ovl_bgclr_in_on,
325
+ .bgclr_in_off = mtk_ovl_bgclr_in_off,
238326 };
239327
240328 static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
....@@ -284,7 +372,12 @@
284372 if (irq < 0)
285373 return irq;
286374
287
- comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_OVL);
375
+ priv->data = of_device_get_match_data(dev);
376
+
377
+ comp_id = mtk_ddp_comp_get_id(dev->of_node,
378
+ priv->data->layer_nr == 4 ?
379
+ MTK_DISP_OVL :
380
+ MTK_DISP_OVL_2L);
288381 if (comp_id < 0) {
289382 dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
290383 return comp_id;
....@@ -293,11 +386,12 @@
293386 ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
294387 &mtk_disp_ovl_funcs);
295388 if (ret) {
296
- dev_err(dev, "Failed to initialize component: %d\n", ret);
389
+ if (ret != -EPROBE_DEFER)
390
+ dev_err(dev, "Failed to initialize component: %d\n",
391
+ ret);
392
+
297393 return ret;
298394 }
299
-
300
- priv->data = of_device_get_match_data(dev);
301395
302396 platform_set_drvdata(pdev, priv);
303397
....@@ -324,11 +418,15 @@
324418
325419 static const struct mtk_disp_ovl_data mt2701_ovl_driver_data = {
326420 .addr = DISP_REG_OVL_ADDR_MT2701,
421
+ .gmc_bits = 8,
422
+ .layer_nr = 4,
327423 .fmt_rgb565_is_0 = false,
328424 };
329425
330426 static const struct mtk_disp_ovl_data mt8173_ovl_driver_data = {
331427 .addr = DISP_REG_OVL_ADDR_MT8173,
428
+ .gmc_bits = 8,
429
+ .layer_nr = 4,
332430 .fmt_rgb565_is_0 = true,
333431 };
334432