forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/drivers/gpu/drm/armada/armada_crtc.c
....@@ -1,20 +1,21 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2012 Russell King
34 * Rewritten from the dovefb driver, and Armada510 manuals.
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 as
7
- * published by the Free Software Foundation.
85 */
6
+
97 #include <linux/clk.h>
108 #include <linux/component.h>
9
+#include <linux/module.h>
1110 #include <linux/of_device.h>
1211 #include <linux/platform_device.h>
13
-#include <drm/drmP.h>
12
+
1413 #include <drm/drm_atomic.h>
15
-#include <drm/drm_crtc_helper.h>
16
-#include <drm/drm_plane_helper.h>
1714 #include <drm/drm_atomic_helper.h>
15
+#include <drm/drm_plane_helper.h>
16
+#include <drm/drm_probe_helper.h>
17
+#include <drm/drm_vblank.h>
18
+
1819 #include "armada_crtc.h"
1920 #include "armada_drm.h"
2021 #include "armada_fb.h"
....@@ -130,6 +131,70 @@
130131 }
131132 }
132133
134
+static void armada_drm_update_gamma(struct drm_crtc *crtc)
135
+{
136
+ struct drm_property_blob *blob = crtc->state->gamma_lut;
137
+ void __iomem *base = drm_to_armada_crtc(crtc)->base;
138
+ int i;
139
+
140
+ if (blob) {
141
+ struct drm_color_lut *lut = blob->data;
142
+
143
+ armada_updatel(CFG_CSB_256x8, CFG_CSB_256x8 | CFG_PDWN256x8,
144
+ base + LCD_SPU_SRAM_PARA1);
145
+
146
+ for (i = 0; i < 256; i++) {
147
+ writel_relaxed(drm_color_lut_extract(lut[i].red, 8),
148
+ base + LCD_SPU_SRAM_WRDAT);
149
+ writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_YR,
150
+ base + LCD_SPU_SRAM_CTRL);
151
+ readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
152
+ writel_relaxed(drm_color_lut_extract(lut[i].green, 8),
153
+ base + LCD_SPU_SRAM_WRDAT);
154
+ writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_UG,
155
+ base + LCD_SPU_SRAM_CTRL);
156
+ readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
157
+ writel_relaxed(drm_color_lut_extract(lut[i].blue, 8),
158
+ base + LCD_SPU_SRAM_WRDAT);
159
+ writel_relaxed(i | SRAM_WRITE | SRAM_GAMMA_VB,
160
+ base + LCD_SPU_SRAM_CTRL);
161
+ readl_relaxed(base + LCD_SPU_HWC_OVSA_HPXL_VLN);
162
+ }
163
+ armada_updatel(CFG_GAMMA_ENA, CFG_GAMMA_ENA,
164
+ base + LCD_SPU_DMA_CTRL0);
165
+ } else {
166
+ armada_updatel(0, CFG_GAMMA_ENA, base + LCD_SPU_DMA_CTRL0);
167
+ armada_updatel(CFG_PDWN256x8, CFG_CSB_256x8 | CFG_PDWN256x8,
168
+ base + LCD_SPU_SRAM_PARA1);
169
+ }
170
+}
171
+
172
+static enum drm_mode_status armada_drm_crtc_mode_valid(struct drm_crtc *crtc,
173
+ const struct drm_display_mode *mode)
174
+{
175
+ struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
176
+
177
+ if (mode->vscan > 1)
178
+ return MODE_NO_VSCAN;
179
+
180
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
181
+ return MODE_NO_DBLESCAN;
182
+
183
+ if (mode->flags & DRM_MODE_FLAG_HSKEW)
184
+ return MODE_H_ILLEGAL;
185
+
186
+ /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
187
+ if (!dcrtc->variant->has_spu_adv_reg &&
188
+ mode->flags & DRM_MODE_FLAG_INTERLACE)
189
+ return MODE_NO_INTERLACE;
190
+
191
+ if (mode->flags & (DRM_MODE_FLAG_BCAST | DRM_MODE_FLAG_PIXMUX |
192
+ DRM_MODE_FLAG_CLKDIV2))
193
+ return MODE_BAD;
194
+
195
+ return MODE_OK;
196
+}
197
+
133198 /* The mode_config.mutex will be held for this call */
134199 static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
135200 const struct drm_display_mode *mode, struct drm_display_mode *adj)
....@@ -137,9 +202,18 @@
137202 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
138203 int ret;
139204
140
- /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
141
- if (!dcrtc->variant->has_spu_adv_reg &&
142
- adj->flags & DRM_MODE_FLAG_INTERLACE)
205
+ /*
206
+ * Set CRTC modesetting parameters for the adjusted mode. This is
207
+ * applied after the connectors, bridges, and encoders have fixed up
208
+ * this mode, as described above drm_atomic_helper_check_modeset().
209
+ */
210
+ drm_mode_set_crtcinfo(adj, CRTC_INTERLACE_HALVE_V);
211
+
212
+ /*
213
+ * Validate the adjusted mode in case an encoder/bridge has set
214
+ * something we don't support.
215
+ */
216
+ if (armada_drm_crtc_mode_valid(crtc, adj) != MODE_OK)
143217 return false;
144218
145219 /* Check whether the display mode is possible */
....@@ -270,13 +344,7 @@
270344 tm = adj->crtc_vtotal - adj->crtc_vsync_end;
271345
272346 DRM_DEBUG_KMS("[CRTC:%d:%s] mode " DRM_MODE_FMT "\n",
273
- crtc->base.id, crtc->name,
274
- adj->base.id, adj->name, adj->vrefresh, adj->clock,
275
- adj->crtc_hdisplay, adj->crtc_hsync_start,
276
- adj->crtc_hsync_end, adj->crtc_htotal,
277
- adj->crtc_vdisplay, adj->crtc_vsync_start,
278
- adj->crtc_vsync_end, adj->crtc_vtotal,
279
- adj->type, adj->flags);
347
+ crtc->base.id, crtc->name, DRM_MODE_ARG(adj));
280348 DRM_DEBUG_KMS("lm %d rm %d tm %d bm %d\n", lm, rm, tm, bm);
281349
282350 /* Now compute the divider for real */
....@@ -284,16 +352,9 @@
284352
285353 armada_reg_queue_set(regs, i, sclk, LCD_CFG_SCLK_DIV);
286354
287
- if (interlaced ^ dcrtc->interlaced) {
288
- if (adj->flags & DRM_MODE_FLAG_INTERLACE)
289
- drm_crtc_vblank_get(&dcrtc->crtc);
290
- else
291
- drm_crtc_vblank_put(&dcrtc->crtc);
292
- dcrtc->interlaced = interlaced;
293
- }
294
-
295355 spin_lock_irqsave(&dcrtc->irq_lock, flags);
296356
357
+ dcrtc->interlaced = interlaced;
297358 /* Even interlaced/progressive frame */
298359 dcrtc->v[1].spu_v_h_total = adj->crtc_vtotal << 16 |
299360 adj->crtc_htotal;
....@@ -351,12 +412,29 @@
351412 spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
352413 }
353414
415
+static int armada_drm_crtc_atomic_check(struct drm_crtc *crtc,
416
+ struct drm_crtc_state *state)
417
+{
418
+ DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
419
+
420
+ if (state->gamma_lut && drm_color_lut_size(state->gamma_lut) != 256)
421
+ return -EINVAL;
422
+
423
+ if (state->color_mgmt_changed)
424
+ state->planes_changed = true;
425
+
426
+ return 0;
427
+}
428
+
354429 static void armada_drm_crtc_atomic_begin(struct drm_crtc *crtc,
355430 struct drm_crtc_state *old_crtc_state)
356431 {
357432 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
358433
359434 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
435
+
436
+ if (crtc->state->color_mgmt_changed)
437
+ armada_drm_update_gamma(crtc);
360438
361439 dcrtc->regs_idx = 0;
362440 dcrtc->regs = dcrtc->atomic_regs;
....@@ -395,6 +473,9 @@
395473 struct drm_pending_vblank_event *event;
396474
397475 DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
476
+
477
+ if (old_state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
478
+ drm_crtc_vblank_put(crtc);
398479
399480 drm_crtc_vblank_off(crtc);
400481 armada_drm_crtc_update(dcrtc, false);
....@@ -440,12 +521,17 @@
440521 armada_drm_crtc_update(dcrtc, true);
441522 drm_crtc_vblank_on(crtc);
442523
524
+ if (crtc->state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
525
+ WARN_ON(drm_crtc_vblank_get(crtc));
526
+
443527 armada_drm_crtc_queue_state_event(crtc);
444528 }
445529
446530 static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
531
+ .mode_valid = armada_drm_crtc_mode_valid,
447532 .mode_fixup = armada_drm_crtc_mode_fixup,
448533 .mode_set_nofb = armada_drm_crtc_mode_set_nofb,
534
+ .atomic_check = armada_drm_crtc_atomic_check,
449535 .atomic_begin = armada_drm_crtc_atomic_begin,
450536 .atomic_flush = armada_drm_crtc_atomic_flush,
451537 .atomic_disable = armada_drm_crtc_atomic_disable,
....@@ -466,6 +552,13 @@
466552 for (x = 0; x < width; x++, p++) {
467553 uint32_t val = *p;
468554
555
+ /*
556
+ * In "ARGB888" (HWC32) mode, writing to the SRAM
557
+ * requires these bits to contain:
558
+ * 31:24 = alpha 23:16 = blue 15:8 = green 7:0 = red
559
+ * So, it's actually ABGR8888. This is independent
560
+ * of the SWAPRB bits in DMA control register 0.
561
+ */
469562 val = (val & 0xff00ff00) |
470563 (val & 0x000000ff) << 16 |
471564 (val & 0x00ff0000) >> 16;
....@@ -617,13 +710,13 @@
617710
618711 /* Must be a kernel-mapped object */
619712 if (!obj->addr) {
620
- drm_gem_object_put_unlocked(&obj->obj);
713
+ drm_gem_object_put(&obj->obj);
621714 return -EINVAL;
622715 }
623716
624717 if (obj->obj.size < w * h * 4) {
625718 DRM_ERROR("buffer is too small\n");
626
- drm_gem_object_put_unlocked(&obj->obj);
719
+ drm_gem_object_put(&obj->obj);
627720 return -ENOMEM;
628721 }
629722 }
....@@ -631,7 +724,7 @@
631724 if (dcrtc->cursor_obj) {
632725 dcrtc->cursor_obj->update = NULL;
633726 dcrtc->cursor_obj->update_data = NULL;
634
- drm_gem_object_put_unlocked(&dcrtc->cursor_obj->obj);
727
+ drm_gem_object_put(&dcrtc->cursor_obj->obj);
635728 }
636729 dcrtc->cursor_obj = obj;
637730 dcrtc->cursor_w = w;
....@@ -664,10 +757,10 @@
664757 static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
665758 {
666759 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
667
- struct armada_private *priv = crtc->dev->dev_private;
760
+ struct armada_private *priv = drm_to_armada_dev(crtc->dev);
668761
669762 if (dcrtc->cursor_obj)
670
- drm_gem_object_put_unlocked(&dcrtc->cursor_obj->obj);
763
+ drm_gem_object_put(&dcrtc->cursor_obj->obj);
671764
672765 priv->dcrtc[dcrtc->num] = NULL;
673766 drm_crtc_cleanup(&dcrtc->crtc);
....@@ -680,6 +773,14 @@
680773 of_node_put(dcrtc->crtc.port);
681774
682775 kfree(dcrtc);
776
+}
777
+
778
+static int armada_drm_crtc_late_register(struct drm_crtc *crtc)
779
+{
780
+ if (IS_ENABLED(CONFIG_DEBUG_FS))
781
+ armada_drm_crtc_debugfs_init(drm_to_armada_crtc(crtc));
782
+
783
+ return 0;
683784 }
684785
685786 /* These are called under the vbl_lock. */
....@@ -709,19 +810,98 @@
709810 .cursor_set = armada_drm_crtc_cursor_set,
710811 .cursor_move = armada_drm_crtc_cursor_move,
711812 .destroy = armada_drm_crtc_destroy,
813
+ .gamma_set = drm_atomic_helper_legacy_gamma_set,
712814 .set_config = drm_atomic_helper_set_config,
713815 .page_flip = drm_atomic_helper_page_flip,
714816 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
715817 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
818
+ .late_register = armada_drm_crtc_late_register,
716819 .enable_vblank = armada_drm_crtc_enable_vblank,
717820 .disable_vblank = armada_drm_crtc_disable_vblank,
718821 };
822
+
823
+int armada_crtc_select_clock(struct armada_crtc *dcrtc,
824
+ struct armada_clk_result *res,
825
+ const struct armada_clocking_params *params,
826
+ struct clk *clks[], size_t num_clks,
827
+ unsigned long desired_khz)
828
+{
829
+ unsigned long desired_hz = desired_khz * 1000;
830
+ unsigned long desired_clk_hz; // requested clk input
831
+ unsigned long real_clk_hz; // actual clk input
832
+ unsigned long real_hz; // actual pixel clk
833
+ unsigned long permillage;
834
+ struct clk *clk;
835
+ u32 div;
836
+ int i;
837
+
838
+ DRM_DEBUG_KMS("[CRTC:%u:%s] desired clock=%luHz\n",
839
+ dcrtc->crtc.base.id, dcrtc->crtc.name, desired_hz);
840
+
841
+ for (i = 0; i < num_clks; i++) {
842
+ clk = clks[i];
843
+ if (!clk)
844
+ continue;
845
+
846
+ if (params->settable & BIT(i)) {
847
+ real_clk_hz = clk_round_rate(clk, desired_hz);
848
+ desired_clk_hz = desired_hz;
849
+ } else {
850
+ real_clk_hz = clk_get_rate(clk);
851
+ desired_clk_hz = real_clk_hz;
852
+ }
853
+
854
+ /* If the clock can do exactly the desired rate, we're done */
855
+ if (real_clk_hz == desired_hz) {
856
+ real_hz = real_clk_hz;
857
+ div = 1;
858
+ goto found;
859
+ }
860
+
861
+ /* Calculate the divider - if invalid, we can't do this rate */
862
+ div = DIV_ROUND_CLOSEST(real_clk_hz, desired_hz);
863
+ if (div == 0 || div > params->div_max)
864
+ continue;
865
+
866
+ /* Calculate the actual rate - HDMI requires -0.6%..+0.5% */
867
+ real_hz = DIV_ROUND_CLOSEST(real_clk_hz, div);
868
+
869
+ DRM_DEBUG_KMS("[CRTC:%u:%s] clk=%u %luHz div=%u real=%luHz\n",
870
+ dcrtc->crtc.base.id, dcrtc->crtc.name,
871
+ i, real_clk_hz, div, real_hz);
872
+
873
+ /* Avoid repeated division */
874
+ if (real_hz < desired_hz) {
875
+ permillage = real_hz / desired_khz;
876
+ if (permillage < params->permillage_min)
877
+ continue;
878
+ } else {
879
+ permillage = DIV_ROUND_UP(real_hz, desired_khz);
880
+ if (permillage > params->permillage_max)
881
+ continue;
882
+ }
883
+ goto found;
884
+ }
885
+
886
+ return -ERANGE;
887
+
888
+found:
889
+ DRM_DEBUG_KMS("[CRTC:%u:%s] selected clk=%u %luHz div=%u real=%luHz\n",
890
+ dcrtc->crtc.base.id, dcrtc->crtc.name,
891
+ i, real_clk_hz, div, real_hz);
892
+
893
+ res->desired_clk_hz = desired_clk_hz;
894
+ res->clk = clk;
895
+ res->div = div;
896
+
897
+ return i;
898
+}
719899
720900 static int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
721901 struct resource *res, int irq, const struct armada_variant *variant,
722902 struct device_node *port)
723903 {
724
- struct armada_private *priv = drm->dev_private;
904
+ struct armada_private *priv = drm_to_armada_dev(drm);
725905 struct armada_crtc *dcrtc;
726906 struct drm_plane *primary;
727907 void __iomem *base;
....@@ -743,7 +923,6 @@
743923 dcrtc->variant = variant;
744924 dcrtc->base = base;
745925 dcrtc->num = drm->mode_config.num_crtc;
746
- dcrtc->clk = ERR_PTR(-EINVAL);
747926 dcrtc->cfg_dumb_ctrl = DUMB24_RGB888_0;
748927 dcrtc->spu_iopad_ctrl = CFG_VSCALE_LN_EN | CFG_IOPAD_DUMB24;
749928 spin_lock_init(&dcrtc->irq_lock);
....@@ -800,6 +979,12 @@
800979
801980 drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
802981
982
+ ret = drm_mode_crtc_set_gamma_size(&dcrtc->crtc, 256);
983
+ if (ret)
984
+ return ret;
985
+
986
+ drm_crtc_enable_color_mgmt(&dcrtc->crtc, 0, false, 256);
987
+
803988 return armada_overlay_plane_create(drm, 1 << dcrtc->num);
804989
805990 err_crtc_init: