forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* Hisilicon Hibmc SoC drm driver
23 *
34 * Based on the bochs drm driver.
....@@ -8,18 +9,15 @@
89 * Rongrong Zou <zourongrong@huawei.com>
910 * Rongrong Zou <zourongrong@gmail.com>
1011 * Jianhua Li <lijianhua@huawei.com>
11
- *
12
- * This program is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2 of the License, or
15
- * (at your option) any later version.
16
- *
1712 */
13
+
14
+#include <linux/delay.h>
1815
1916 #include <drm/drm_atomic.h>
2017 #include <drm/drm_atomic_helper.h>
21
-#include <drm/drm_crtc_helper.h>
22
-#include <drm/drm_plane_helper.h>
18
+#include <drm/drm_fourcc.h>
19
+#include <drm/drm_gem_vram_helper.h>
20
+#include <drm/drm_vblank.h>
2321
2422 #include "hibmc_drm_drv.h"
2523 #include "hibmc_drm_regs.h"
....@@ -39,6 +37,7 @@
3937 };
4038
4139 static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
40
+ {640, 480, CRT_PLL1_HS_25MHZ, CRT_PLL2_HS_25MHZ},
4241 {800, 600, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
4342 {1024, 768, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
4443 {1152, 864, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
....@@ -46,6 +45,8 @@
4645 {1280, 720, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
4746 {1280, 960, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
4847 {1280, 1024, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
48
+ {1440, 900, CRT_PLL1_HS_106MHZ, CRT_PLL2_HS_106MHZ},
49
+ {1600, 900, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
4950 {1600, 1200, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
5051 {1920, 1080, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
5152 {1920, 1200, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
....@@ -70,23 +71,30 @@
7071 return PTR_ERR(crtc_state);
7172
7273 if (src_w != state->crtc_w || src_h != state->crtc_h) {
73
- DRM_DEBUG_ATOMIC("scale not support\n");
74
+ drm_dbg_atomic(plane->dev, "scale not support\n");
7475 return -EINVAL;
7576 }
7677
7778 if (state->crtc_x < 0 || state->crtc_y < 0) {
78
- DRM_DEBUG_ATOMIC("crtc_x/y of drm_plane state is invalid\n");
79
+ drm_dbg_atomic(plane->dev, "crtc_x/y of drm_plane state is invalid\n");
7980 return -EINVAL;
8081 }
82
+
83
+ if (!crtc_state->enable)
84
+ return 0;
8185
8286 if (state->crtc_x + state->crtc_w >
8387 crtc_state->adjusted_mode.hdisplay ||
8488 state->crtc_y + state->crtc_h >
8589 crtc_state->adjusted_mode.vdisplay) {
86
- DRM_DEBUG_ATOMIC("visible portion of plane is invalid\n");
90
+ drm_dbg_atomic(plane->dev, "visible portion of plane is invalid\n");
8791 return -EINVAL;
8892 }
8993
94
+ if (state->fb->pitches[0] % 128 != 0) {
95
+ drm_dbg_atomic(plane->dev, "wrong stride with 128-byte aligned\n");
96
+ return -EINVAL;
97
+ }
9098 return 0;
9199 }
92100
....@@ -95,39 +103,25 @@
95103 {
96104 struct drm_plane_state *state = plane->state;
97105 u32 reg;
98
- int ret;
99
- u64 gpu_addr = 0;
106
+ s64 gpu_addr = 0;
100107 unsigned int line_l;
101108 struct hibmc_drm_private *priv = plane->dev->dev_private;
102
- struct hibmc_framebuffer *hibmc_fb;
103
- struct hibmc_bo *bo;
109
+ struct drm_gem_vram_object *gbo;
104110
105111 if (!state->fb)
106112 return;
107113
108
- hibmc_fb = to_hibmc_framebuffer(state->fb);
109
- bo = gem_to_hibmc_bo(hibmc_fb->obj);
110
- ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
111
- if (ret) {
112
- DRM_ERROR("failed to reserve ttm_bo: %d", ret);
113
- return;
114
- }
114
+ gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
115115
116
- ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
117
- ttm_bo_unreserve(&bo->bo);
118
- if (ret) {
119
- DRM_ERROR("failed to pin hibmc_bo: %d", ret);
120
- return;
121
- }
116
+ gpu_addr = drm_gem_vram_offset(gbo);
117
+ if (WARN_ON_ONCE(gpu_addr < 0))
118
+ return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
122119
123120 writel(gpu_addr, priv->mmio + HIBMC_CRT_FB_ADDRESS);
124121
125122 reg = state->fb->width * (state->fb->format->cpp[0]);
126
- /* now line_pad is 16 */
127
- reg = PADDING(16, reg);
128123
129
- line_l = state->fb->width * state->fb->format->cpp[0];
130
- line_l = PADDING(16, line_l);
124
+ line_l = state->fb->pitches[0];
131125 writel(HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_WIDTH, reg) |
132126 HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_OFFS, line_l),
133127 priv->mmio + HIBMC_CRT_FB_WIDTH);
....@@ -157,39 +151,24 @@
157151 };
158152
159153 static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
154
+ .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
155
+ .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
160156 .atomic_check = hibmc_plane_atomic_check,
161157 .atomic_update = hibmc_plane_atomic_update,
162158 };
163159
164
-static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
160
+static void hibmc_crtc_dpms(struct drm_crtc *crtc, int dpms)
165161 {
166
- struct drm_device *dev = priv->dev;
167
- struct drm_plane *plane;
168
- int ret = 0;
162
+ struct hibmc_drm_private *priv = crtc->dev->dev_private;
163
+ unsigned int reg;
169164
170
- plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL);
171
- if (!plane) {
172
- DRM_ERROR("failed to alloc memory when init plane\n");
173
- return ERR_PTR(-ENOMEM);
174
- }
175
- /*
176
- * plane init
177
- * TODO: Now only support primary plane, overlay planes
178
- * need to do.
179
- */
180
- ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
181
- channel_formats1,
182
- ARRAY_SIZE(channel_formats1),
183
- NULL,
184
- DRM_PLANE_TYPE_PRIMARY,
185
- NULL);
186
- if (ret) {
187
- DRM_ERROR("failed to init plane: %d\n", ret);
188
- return ERR_PTR(ret);
189
- }
190
-
191
- drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
192
- return plane;
165
+ reg = readl(priv->mmio + HIBMC_CRT_DISP_CTL);
166
+ reg &= ~HIBMC_CRT_DISP_CTL_DPMS_MASK;
167
+ reg |= HIBMC_FIELD(HIBMC_CRT_DISP_CTL_DPMS, dpms);
168
+ reg &= ~HIBMC_CRT_DISP_CTL_TIMING_MASK;
169
+ if (dpms == HIBMC_CRT_DPMS_ON)
170
+ reg |= HIBMC_CRT_DISP_CTL_TIMING(1);
171
+ writel(reg, priv->mmio + HIBMC_CRT_DISP_CTL);
193172 }
194173
195174 static void hibmc_crtc_atomic_enable(struct drm_crtc *crtc,
....@@ -208,6 +187,7 @@
208187 reg |= HIBMC_CURR_GATE_DISPLAY(1);
209188 hibmc_set_current_gate(priv, reg);
210189 drm_crtc_vblank_on(crtc);
190
+ hibmc_crtc_dpms(crtc, HIBMC_CRT_DPMS_ON);
211191 }
212192
213193 static void hibmc_crtc_atomic_disable(struct drm_crtc *crtc,
....@@ -216,6 +196,7 @@
216196 unsigned int reg;
217197 struct hibmc_drm_private *priv = crtc->dev->dev_private;
218198
199
+ hibmc_crtc_dpms(crtc, HIBMC_CRT_DPMS_OFF);
219200 drm_crtc_vblank_off(crtc);
220201
221202 hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_SLEEP);
....@@ -227,6 +208,25 @@
227208 reg |= HIBMC_CURR_GATE_LOCALMEM(0);
228209 reg |= HIBMC_CURR_GATE_DISPLAY(0);
229210 hibmc_set_current_gate(priv, reg);
211
+}
212
+
213
+static enum drm_mode_status
214
+hibmc_crtc_mode_valid(struct drm_crtc *crtc,
215
+ const struct drm_display_mode *mode)
216
+{
217
+ int i = 0;
218
+ int vrefresh = drm_mode_vrefresh(mode);
219
+
220
+ if (vrefresh < 59 || vrefresh > 61)
221
+ return MODE_NOCLOCK;
222
+
223
+ for (i = 0; i < ARRAY_SIZE(hibmc_pll_table); i++) {
224
+ if (hibmc_pll_table[i].hdisplay == mode->hdisplay &&
225
+ hibmc_pll_table[i].vdisplay == mode->vdisplay)
226
+ return MODE_OK;
227
+ }
228
+
229
+ return MODE_BAD;
230230 }
231231
232232 static unsigned int format_pll_reg(void)
....@@ -443,6 +443,42 @@
443443 priv->mmio + HIBMC_RAW_INTERRUPT_EN);
444444 }
445445
446
+static void hibmc_crtc_load_lut(struct drm_crtc *crtc)
447
+{
448
+ struct hibmc_drm_private *priv = crtc->dev->dev_private;
449
+ void __iomem *mmio = priv->mmio;
450
+ u16 *r, *g, *b;
451
+ unsigned int reg;
452
+ int i;
453
+
454
+ r = crtc->gamma_store;
455
+ g = r + crtc->gamma_size;
456
+ b = g + crtc->gamma_size;
457
+
458
+ for (i = 0; i < crtc->gamma_size; i++) {
459
+ unsigned int offset = i << 2;
460
+ u8 red = *r++ >> 8;
461
+ u8 green = *g++ >> 8;
462
+ u8 blue = *b++ >> 8;
463
+ u32 rgb = (red << 16) | (green << 8) | blue;
464
+
465
+ writel(rgb, mmio + HIBMC_CRT_PALETTE + offset);
466
+ }
467
+
468
+ reg = readl(priv->mmio + HIBMC_CRT_DISP_CTL);
469
+ reg |= HIBMC_FIELD(HIBMC_CTL_DISP_CTL_GAMMA, 1);
470
+ writel(reg, priv->mmio + HIBMC_CRT_DISP_CTL);
471
+}
472
+
473
+static int hibmc_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
474
+ u16 *blue, uint32_t size,
475
+ struct drm_modeset_acquire_ctx *ctx)
476
+{
477
+ hibmc_crtc_load_lut(crtc);
478
+
479
+ return 0;
480
+}
481
+
446482 static const struct drm_crtc_funcs hibmc_crtc_funcs = {
447483 .page_flip = drm_atomic_helper_page_flip,
448484 .set_config = drm_atomic_helper_set_config,
....@@ -452,6 +488,7 @@
452488 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
453489 .enable_vblank = hibmc_crtc_enable_vblank,
454490 .disable_vblank = hibmc_crtc_disable_vblank,
491
+ .gamma_set = hibmc_crtc_gamma_set,
455492 };
456493
457494 static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
....@@ -460,37 +497,40 @@
460497 .atomic_flush = hibmc_crtc_atomic_flush,
461498 .atomic_enable = hibmc_crtc_atomic_enable,
462499 .atomic_disable = hibmc_crtc_atomic_disable,
500
+ .mode_valid = hibmc_crtc_mode_valid,
463501 };
464502
465503 int hibmc_de_init(struct hibmc_drm_private *priv)
466504 {
467505 struct drm_device *dev = priv->dev;
468
- struct drm_crtc *crtc;
469
- struct drm_plane *plane;
506
+ struct drm_crtc *crtc = &priv->crtc;
507
+ struct drm_plane *plane = &priv->primary_plane;
470508 int ret;
471509
472
- plane = hibmc_plane_init(priv);
473
- if (IS_ERR(plane)) {
474
- DRM_ERROR("failed to create plane: %ld\n", PTR_ERR(plane));
475
- return PTR_ERR(plane);
510
+ ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
511
+ channel_formats1,
512
+ ARRAY_SIZE(channel_formats1),
513
+ NULL,
514
+ DRM_PLANE_TYPE_PRIMARY,
515
+ NULL);
516
+
517
+ if (ret) {
518
+ drm_err(dev, "failed to init plane: %d\n", ret);
519
+ return ret;
476520 }
477521
478
- crtc = devm_kzalloc(dev->dev, sizeof(*crtc), GFP_KERNEL);
479
- if (!crtc) {
480
- DRM_ERROR("failed to alloc memory when init crtc\n");
481
- return -ENOMEM;
482
- }
522
+ drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
483523
484524 ret = drm_crtc_init_with_planes(dev, crtc, plane,
485525 NULL, &hibmc_crtc_funcs, NULL);
486526 if (ret) {
487
- DRM_ERROR("failed to init crtc: %d\n", ret);
527
+ drm_err(dev, "failed to init crtc: %d\n", ret);
488528 return ret;
489529 }
490530
491531 ret = drm_mode_crtc_set_gamma_size(crtc, 256);
492532 if (ret) {
493
- DRM_ERROR("failed to set gamma size: %d\n", ret);
533
+ drm_err(dev, "failed to set gamma size: %d\n", ret);
494534 return ret;
495535 }
496536 drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs);