forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/tegra/hub.c
....@@ -1,12 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
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.
74 */
85
96 #include <linux/clk.h>
7
+#include <linux/delay.h>
108 #include <linux/host1x.h>
119 #include <linux/module.h>
1210 #include <linux/of.h>
....@@ -16,10 +14,10 @@
1614 #include <linux/pm_runtime.h>
1715 #include <linux/reset.h>
1816
19
-#include <drm/drmP.h>
2017 #include <drm/drm_atomic.h>
2118 #include <drm/drm_atomic_helper.h>
22
-#include <drm/drm_crtc_helper.h>
19
+#include <drm/drm_fourcc.h>
20
+#include <drm/drm_probe_helper.h>
2321
2422 #include "drm.h"
2523 #include "dc.h"
....@@ -97,17 +95,25 @@
9795
9896 static int tegra_windowgroup_enable(struct tegra_windowgroup *wgrp)
9997 {
98
+ int err = 0;
99
+
100100 mutex_lock(&wgrp->lock);
101101
102102 if (wgrp->usecount == 0) {
103
- pm_runtime_get_sync(wgrp->parent);
103
+ err = host1x_client_resume(wgrp->parent);
104
+ if (err < 0) {
105
+ dev_err(wgrp->parent->dev, "failed to resume: %d\n", err);
106
+ goto unlock;
107
+ }
108
+
104109 reset_control_deassert(wgrp->rst);
105110 }
106111
107112 wgrp->usecount++;
108
- mutex_unlock(&wgrp->lock);
109113
110
- return 0;
114
+unlock:
115
+ mutex_unlock(&wgrp->lock);
116
+ return err;
111117 }
112118
113119 static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp)
....@@ -123,7 +129,7 @@
123129 wgrp->index);
124130 }
125131
126
- pm_runtime_put(wgrp->parent);
132
+ host1x_client_suspend(wgrp->parent);
127133 }
128134
129135 wgrp->usecount--;
....@@ -385,12 +391,19 @@
385391 struct tegra_plane *p = to_tegra_plane(plane);
386392 struct tegra_dc *dc;
387393 u32 value;
394
+ int err;
388395
389396 /* rien ne va plus */
390397 if (!old_state || !old_state->crtc)
391398 return;
392399
393400 dc = to_tegra_dc(old_state->crtc);
401
+
402
+ err = host1x_client_resume(&dc->client);
403
+ if (err < 0) {
404
+ dev_err(dc->dev, "failed to resume: %d\n", err);
405
+ return;
406
+ }
394407
395408 /*
396409 * XXX Legacy helpers seem to sometimes call ->atomic_disable() even
....@@ -400,15 +413,13 @@
400413 if (WARN_ON(p->dc == NULL))
401414 p->dc = dc;
402415
403
- pm_runtime_get_sync(dc->dev);
404
-
405416 value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);
406417 value &= ~WIN_ENABLE;
407418 tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);
408419
409420 tegra_dc_remove_shared_plane(dc, p);
410421
411
- pm_runtime_put(dc->dev);
422
+ host1x_client_suspend(&dc->client);
412423 }
413424
414425 static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
....@@ -419,9 +430,9 @@
419430 unsigned int zpos = plane->state->normalized_zpos;
420431 struct drm_framebuffer *fb = plane->state->fb;
421432 struct tegra_plane *p = to_tegra_plane(plane);
422
- struct tegra_bo *bo;
423433 dma_addr_t base;
424434 u32 value;
435
+ int err;
425436
426437 /* rien ne va plus */
427438 if (!plane->state->crtc || !plane->state->fb)
....@@ -432,7 +443,11 @@
432443 return;
433444 }
434445
435
- pm_runtime_get_sync(dc->dev);
446
+ err = host1x_client_resume(&dc->client);
447
+ if (err < 0) {
448
+ dev_err(dc->dev, "failed to resume: %d\n", err);
449
+ return;
450
+ }
436451
437452 tegra_dc_assign_shared_plane(dc, p);
438453
....@@ -462,8 +477,7 @@
462477 /* disable compression */
463478 tegra_plane_writel(p, 0, DC_WINBUF_CDE_CONTROL);
464479
465
- bo = tegra_fb_get_plane(fb, 0);
466
- base = bo->paddr;
480
+ base = state->iova[0] + fb->offsets[0];
467481
468482 tegra_plane_writel(p, state->format, DC_WIN_COLOR_DEPTH);
469483 tegra_plane_writel(p, 0, DC_WIN_PRECOMP_WGRP_PARAMS);
....@@ -523,10 +537,12 @@
523537 value &= ~CONTROL_CSC_ENABLE;
524538 tegra_plane_writel(p, value, DC_WIN_WINDOW_SET_CONTROL);
525539
526
- pm_runtime_put(dc->dev);
540
+ host1x_client_suspend(&dc->client);
527541 }
528542
529543 static const struct drm_plane_helper_funcs tegra_shared_plane_helper_funcs = {
544
+ .prepare_fb = tegra_plane_prepare_fb,
545
+ .cleanup_fb = tegra_plane_cleanup_fb,
530546 .atomic_check = tegra_shared_plane_atomic_check,
531547 .atomic_update = tegra_shared_plane_atomic_update,
532548 .atomic_disable = tegra_shared_plane_atomic_disable,
....@@ -557,7 +573,7 @@
557573 plane->base.index = index;
558574
559575 plane->wgrp = &hub->wgrps[wgrp];
560
- plane->wgrp->parent = dc->dev;
576
+ plane->wgrp->parent = &dc->client;
561577
562578 p = &plane->base.base;
563579
....@@ -611,10 +627,7 @@
611627 tegra_display_hub_get_state(struct tegra_display_hub *hub,
612628 struct drm_atomic_state *state)
613629 {
614
- struct drm_device *drm = dev_get_drvdata(hub->client.parent);
615630 struct drm_private_state *priv;
616
-
617
- WARN_ON(!drm_modeset_is_locked(&drm->mode_config.connection_mutex));
618631
619632 priv = drm_atomic_get_private_obj_state(state, &hub->base);
620633 if (IS_ERR(priv))
....@@ -665,8 +678,13 @@
665678 static void tegra_display_hub_update(struct tegra_dc *dc)
666679 {
667680 u32 value;
681
+ int err;
668682
669
- pm_runtime_get_sync(dc->dev);
683
+ err = host1x_client_resume(&dc->client);
684
+ if (err < 0) {
685
+ dev_err(dc->dev, "failed to resume: %d\n", err);
686
+ return;
687
+ }
670688
671689 value = tegra_dc_readl(dc, DC_CMD_IHUB_COMMON_MISC_CTL);
672690 value &= ~LATENCY_EVENT;
....@@ -681,7 +699,7 @@
681699 tegra_dc_writel(dc, COMMON_ACTREQ, DC_CMD_STATE_CONTROL);
682700 tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
683701
684
- pm_runtime_put(dc->dev);
702
+ host1x_client_suspend(&dc->client);
685703 }
686704
687705 void tegra_display_hub_atomic_commit(struct drm_device *drm,
....@@ -714,7 +732,7 @@
714732 static int tegra_display_hub_init(struct host1x_client *client)
715733 {
716734 struct tegra_display_hub *hub = to_tegra_display_hub(client);
717
- struct drm_device *drm = dev_get_drvdata(client->parent);
735
+ struct drm_device *drm = dev_get_drvdata(client->host);
718736 struct tegra_drm *tegra = drm->dev_private;
719737 struct tegra_display_hub_state *state;
720738
....@@ -722,7 +740,7 @@
722740 if (!state)
723741 return -ENOMEM;
724742
725
- drm_atomic_private_obj_init(&hub->base, &state->base,
743
+ drm_atomic_private_obj_init(drm, &hub->base, &state->base,
726744 &tegra_display_hub_state_funcs);
727745
728746 tegra->hub = hub;
....@@ -732,7 +750,7 @@
732750
733751 static int tegra_display_hub_exit(struct host1x_client *client)
734752 {
735
- struct drm_device *drm = dev_get_drvdata(client->parent);
753
+ struct drm_device *drm = dev_get_drvdata(client->host);
736754 struct tegra_drm *tegra = drm->dev_private;
737755
738756 drm_atomic_private_obj_fini(&tegra->hub->base);
....@@ -741,14 +759,92 @@
741759 return 0;
742760 }
743761
762
+static int tegra_display_hub_runtime_suspend(struct host1x_client *client)
763
+{
764
+ struct tegra_display_hub *hub = to_tegra_display_hub(client);
765
+ struct device *dev = client->dev;
766
+ unsigned int i = hub->num_heads;
767
+ int err;
768
+
769
+ err = reset_control_assert(hub->rst);
770
+ if (err < 0)
771
+ return err;
772
+
773
+ while (i--)
774
+ clk_disable_unprepare(hub->clk_heads[i]);
775
+
776
+ clk_disable_unprepare(hub->clk_hub);
777
+ clk_disable_unprepare(hub->clk_dsc);
778
+ clk_disable_unprepare(hub->clk_disp);
779
+
780
+ pm_runtime_put_sync(dev);
781
+
782
+ return 0;
783
+}
784
+
785
+static int tegra_display_hub_runtime_resume(struct host1x_client *client)
786
+{
787
+ struct tegra_display_hub *hub = to_tegra_display_hub(client);
788
+ struct device *dev = client->dev;
789
+ unsigned int i;
790
+ int err;
791
+
792
+ err = pm_runtime_resume_and_get(dev);
793
+ if (err < 0) {
794
+ dev_err(dev, "failed to get runtime PM: %d\n", err);
795
+ return err;
796
+ }
797
+
798
+ err = clk_prepare_enable(hub->clk_disp);
799
+ if (err < 0)
800
+ goto put_rpm;
801
+
802
+ err = clk_prepare_enable(hub->clk_dsc);
803
+ if (err < 0)
804
+ goto disable_disp;
805
+
806
+ err = clk_prepare_enable(hub->clk_hub);
807
+ if (err < 0)
808
+ goto disable_dsc;
809
+
810
+ for (i = 0; i < hub->num_heads; i++) {
811
+ err = clk_prepare_enable(hub->clk_heads[i]);
812
+ if (err < 0)
813
+ goto disable_heads;
814
+ }
815
+
816
+ err = reset_control_deassert(hub->rst);
817
+ if (err < 0)
818
+ goto disable_heads;
819
+
820
+ return 0;
821
+
822
+disable_heads:
823
+ while (i--)
824
+ clk_disable_unprepare(hub->clk_heads[i]);
825
+
826
+ clk_disable_unprepare(hub->clk_hub);
827
+disable_dsc:
828
+ clk_disable_unprepare(hub->clk_dsc);
829
+disable_disp:
830
+ clk_disable_unprepare(hub->clk_disp);
831
+put_rpm:
832
+ pm_runtime_put_sync(dev);
833
+ return err;
834
+}
835
+
744836 static const struct host1x_client_ops tegra_display_hub_ops = {
745837 .init = tegra_display_hub_init,
746838 .exit = tegra_display_hub_exit,
839
+ .suspend = tegra_display_hub_runtime_suspend,
840
+ .resume = tegra_display_hub_runtime_resume,
747841 };
748842
749843 static int tegra_display_hub_probe(struct platform_device *pdev)
750844 {
845
+ struct device_node *child = NULL;
751846 struct tegra_display_hub *hub;
847
+ struct clk *clk;
752848 unsigned int i;
753849 int err;
754850
....@@ -764,10 +860,12 @@
764860 return err;
765861 }
766862
767
- hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
768
- if (IS_ERR(hub->clk_dsc)) {
769
- err = PTR_ERR(hub->clk_dsc);
770
- return err;
863
+ if (hub->soc->supports_dsc) {
864
+ hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc");
865
+ if (IS_ERR(hub->clk_dsc)) {
866
+ err = PTR_ERR(hub->clk_dsc);
867
+ return err;
868
+ }
771869 }
772870
773871 hub->clk_hub = devm_clk_get(&pdev->dev, "hub");
....@@ -805,6 +903,34 @@
805903 return err;
806904 }
807905
906
+ hub->num_heads = of_get_child_count(pdev->dev.of_node);
907
+
908
+ hub->clk_heads = devm_kcalloc(&pdev->dev, hub->num_heads, sizeof(clk),
909
+ GFP_KERNEL);
910
+ if (!hub->clk_heads)
911
+ return -ENOMEM;
912
+
913
+ for (i = 0; i < hub->num_heads; i++) {
914
+ child = of_get_next_child(pdev->dev.of_node, child);
915
+ if (!child) {
916
+ dev_err(&pdev->dev, "failed to find node for head %u\n",
917
+ i);
918
+ return -ENODEV;
919
+ }
920
+
921
+ clk = devm_get_clk_from_child(&pdev->dev, child, "dc");
922
+ if (IS_ERR(clk)) {
923
+ dev_err(&pdev->dev, "failed to get clock for head %u\n",
924
+ i);
925
+ of_node_put(child);
926
+ return PTR_ERR(clk);
927
+ }
928
+
929
+ hub->clk_heads[i] = clk;
930
+ }
931
+
932
+ of_node_put(child);
933
+
808934 /* XXX: enable clock across reset? */
809935 err = reset_control_assert(hub->rst);
810936 if (err < 0)
....@@ -822,12 +948,22 @@
822948 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
823949 err);
824950
951
+ err = devm_of_platform_populate(&pdev->dev);
952
+ if (err < 0)
953
+ goto unregister;
954
+
955
+ return err;
956
+
957
+unregister:
958
+ host1x_client_unregister(&hub->client);
959
+ pm_runtime_disable(&pdev->dev);
825960 return err;
826961 }
827962
828963 static int tegra_display_hub_remove(struct platform_device *pdev)
829964 {
830965 struct tegra_display_hub *hub = platform_get_drvdata(pdev);
966
+ unsigned int i;
831967 int err;
832968
833969 err = host1x_client_unregister(&hub->client);
....@@ -836,70 +972,32 @@
836972 err);
837973 }
838974
975
+ for (i = 0; i < hub->soc->num_wgrps; i++) {
976
+ struct tegra_windowgroup *wgrp = &hub->wgrps[i];
977
+
978
+ mutex_destroy(&wgrp->lock);
979
+ }
980
+
839981 pm_runtime_disable(&pdev->dev);
840982
841983 return err;
842984 }
843985
844
-static int __maybe_unused tegra_display_hub_suspend(struct device *dev)
845
-{
846
- struct tegra_display_hub *hub = dev_get_drvdata(dev);
847
- int err;
848
-
849
- err = reset_control_assert(hub->rst);
850
- if (err < 0)
851
- return err;
852
-
853
- clk_disable_unprepare(hub->clk_hub);
854
- clk_disable_unprepare(hub->clk_dsc);
855
- clk_disable_unprepare(hub->clk_disp);
856
-
857
- return 0;
858
-}
859
-
860
-static int __maybe_unused tegra_display_hub_resume(struct device *dev)
861
-{
862
- struct tegra_display_hub *hub = dev_get_drvdata(dev);
863
- int err;
864
-
865
- err = clk_prepare_enable(hub->clk_disp);
866
- if (err < 0)
867
- return err;
868
-
869
- err = clk_prepare_enable(hub->clk_dsc);
870
- if (err < 0)
871
- goto disable_disp;
872
-
873
- err = clk_prepare_enable(hub->clk_hub);
874
- if (err < 0)
875
- goto disable_dsc;
876
-
877
- err = reset_control_deassert(hub->rst);
878
- if (err < 0)
879
- goto disable_hub;
880
-
881
- return 0;
882
-
883
-disable_hub:
884
- clk_disable_unprepare(hub->clk_hub);
885
-disable_dsc:
886
- clk_disable_unprepare(hub->clk_dsc);
887
-disable_disp:
888
- clk_disable_unprepare(hub->clk_disp);
889
- return err;
890
-}
891
-
892
-static const struct dev_pm_ops tegra_display_hub_pm_ops = {
893
- SET_RUNTIME_PM_OPS(tegra_display_hub_suspend,
894
- tegra_display_hub_resume, NULL)
895
-};
896
-
897986 static const struct tegra_display_hub_soc tegra186_display_hub = {
898987 .num_wgrps = 6,
988
+ .supports_dsc = true,
989
+};
990
+
991
+static const struct tegra_display_hub_soc tegra194_display_hub = {
992
+ .num_wgrps = 6,
993
+ .supports_dsc = false,
899994 };
900995
901996 static const struct of_device_id tegra_display_hub_of_match[] = {
902997 {
998
+ .compatible = "nvidia,tegra194-display",
999
+ .data = &tegra194_display_hub
1000
+ }, {
9031001 .compatible = "nvidia,tegra186-display",
9041002 .data = &tegra186_display_hub
9051003 }, {
....@@ -912,7 +1010,6 @@
9121010 .driver = {
9131011 .name = "tegra-display-hub",
9141012 .of_match_table = tegra_display_hub_of_match,
915
- .pm = &tegra_display_hub_pm_ops,
9161013 },
9171014 .probe = tegra_display_hub_probe,
9181015 .remove = tegra_display_hub_remove,