forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/tegra/dc.c
....@@ -1,20 +1,26 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2012 Avionic Design GmbH
34 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
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 */
96
107 #include <linux/clk.h>
118 #include <linux/debugfs.h>
9
+#include <linux/delay.h>
1210 #include <linux/iommu.h>
11
+#include <linux/module.h>
1312 #include <linux/of_device.h>
1413 #include <linux/pm_runtime.h>
1514 #include <linux/reset.h>
1615
1716 #include <soc/tegra/pmc.h>
17
+
18
+#include <drm/drm_atomic.h>
19
+#include <drm/drm_atomic_helper.h>
20
+#include <drm/drm_debugfs.h>
21
+#include <drm/drm_fourcc.h>
22
+#include <drm/drm_plane_helper.h>
23
+#include <drm/drm_vblank.h>
1824
1925 #include "dc.h"
2026 #include "drm.h"
....@@ -22,9 +28,8 @@
2228 #include "hub.h"
2329 #include "plane.h"
2430
25
-#include <drm/drm_atomic.h>
26
-#include <drm/drm_atomic_helper.h>
27
-#include <drm/drm_plane_helper.h>
31
+static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
32
+ struct drm_crtc_state *state);
2833
2934 static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
3035 {
....@@ -130,7 +135,7 @@
130135
131136 default:
132137 WARN_ON_ONCE(1);
133
- /* fallthrough */
138
+ fallthrough;
134139 case 4:
135140 max = 4;
136141 break;
....@@ -363,6 +368,12 @@
363368 h_size = window->src.w * bpp;
364369 v_size = window->src.h;
365370
371
+ if (window->reflect_x)
372
+ h_offset += (window->src.w - 1) * bpp;
373
+
374
+ if (window->reflect_y)
375
+ v_offset += window->src.h - 1;
376
+
366377 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
367378 tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE);
368379
....@@ -398,9 +409,6 @@
398409 } else {
399410 tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);
400411 }
401
-
402
- if (window->bottom_up)
403
- v_offset += window->src.h - 1;
404412
405413 tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET);
406414 tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET);
....@@ -465,7 +473,10 @@
465473 value |= COLOR_EXPAND;
466474 }
467475
468
- if (window->bottom_up)
476
+ if (window->reflect_x)
477
+ value |= H_DIRECTION;
478
+
479
+ if (window->reflect_y)
469480 value |= V_DIRECTION;
470481
471482 if (tegra_plane_use_horizontal_filtering(plane, window)) {
....@@ -596,7 +607,10 @@
596607 struct drm_plane_state *state)
597608 {
598609 struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
599
- unsigned int rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y;
610
+ unsigned int supported_rotation = DRM_MODE_ROTATE_0 |
611
+ DRM_MODE_REFLECT_X |
612
+ DRM_MODE_REFLECT_Y;
613
+ unsigned int rotation = state->rotation;
600614 struct tegra_bo_tiling *tiling = &plane_state->tiling;
601615 struct tegra_plane *tegra = to_tegra_plane(plane);
602616 struct tegra_dc *dc = to_tegra_dc(state->crtc);
....@@ -634,12 +648,26 @@
634648 return -EINVAL;
635649 }
636650
637
- rotation = drm_rotation_simplify(state->rotation, rotation);
651
+ /*
652
+ * Older userspace used custom BO flag in order to specify the Y
653
+ * reflection, while modern userspace uses the generic DRM rotation
654
+ * property in order to achieve the same result. The legacy BO flag
655
+ * duplicates the DRM rotation property when both are set.
656
+ */
657
+ if (tegra_fb_is_bottom_up(state->fb))
658
+ rotation |= DRM_MODE_REFLECT_Y;
659
+
660
+ rotation = drm_rotation_simplify(rotation, supported_rotation);
661
+
662
+ if (rotation & DRM_MODE_REFLECT_X)
663
+ plane_state->reflect_x = true;
664
+ else
665
+ plane_state->reflect_x = false;
638666
639667 if (rotation & DRM_MODE_REFLECT_Y)
640
- plane_state->bottom_up = true;
668
+ plane_state->reflect_y = true;
641669 else
642
- plane_state->bottom_up = false;
670
+ plane_state->reflect_y = false;
643671
644672 /*
645673 * Tegra doesn't support different strides for U and V planes so we
....@@ -701,7 +729,8 @@
701729 window.dst.w = drm_rect_width(&plane->state->dst);
702730 window.dst.h = drm_rect_height(&plane->state->dst);
703731 window.bits_per_pixel = fb->format->cpp[0] * 8;
704
- window.bottom_up = tegra_fb_is_bottom_up(fb) || state->bottom_up;
732
+ window.reflect_x = state->reflect_x;
733
+ window.reflect_y = state->reflect_y;
705734
706735 /* copy from state */
707736 window.zpos = plane->state->normalized_zpos;
....@@ -710,9 +739,7 @@
710739 window.swap = state->swap;
711740
712741 for (i = 0; i < fb->format->num_planes; i++) {
713
- struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
714
-
715
- window.base[i] = bo->paddr + fb->offsets[i];
742
+ window.base[i] = state->iova[i] + fb->offsets[i];
716743
717744 /*
718745 * Tegra uses a shared stride for UV planes. Framebuffers are
....@@ -727,6 +754,8 @@
727754 }
728755
729756 static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = {
757
+ .prepare_fb = tegra_plane_prepare_fb,
758
+ .cleanup_fb = tegra_plane_cleanup_fb,
730759 .atomic_check = tegra_plane_atomic_check,
731760 .atomic_disable = tegra_plane_atomic_disable,
732761 .atomic_update = tegra_plane_atomic_update,
....@@ -787,6 +816,8 @@
787816 err = drm_plane_create_rotation_property(&plane->base,
788817 DRM_MODE_ROTATE_0,
789818 DRM_MODE_ROTATE_0 |
819
+ DRM_MODE_ROTATE_180 |
820
+ DRM_MODE_REFLECT_X |
790821 DRM_MODE_REFLECT_Y);
791822 if (err < 0)
792823 dev_err(dc->dev, "failed to create rotation property: %d\n",
....@@ -832,16 +863,15 @@
832863 static void tegra_cursor_atomic_update(struct drm_plane *plane,
833864 struct drm_plane_state *old_state)
834865 {
835
- struct tegra_bo *bo = tegra_fb_get_plane(plane->state->fb, 0);
866
+ struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
836867 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc);
837
- struct drm_plane_state *state = plane->state;
838868 u32 value = CURSOR_CLIP_DISPLAY;
839869
840870 /* rien ne va plus */
841871 if (!plane->state->crtc || !plane->state->fb)
842872 return;
843873
844
- switch (state->crtc_w) {
874
+ switch (plane->state->crtc_w) {
845875 case 32:
846876 value |= CURSOR_SIZE_32x32;
847877 break;
....@@ -859,16 +889,16 @@
859889 break;
860890
861891 default:
862
- WARN(1, "cursor size %ux%u not supported\n", state->crtc_w,
863
- state->crtc_h);
892
+ WARN(1, "cursor size %ux%u not supported\n",
893
+ plane->state->crtc_w, plane->state->crtc_h);
864894 return;
865895 }
866896
867
- value |= (bo->paddr >> 10) & 0x3fffff;
897
+ value |= (state->iova[0] >> 10) & 0x3fffff;
868898 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
869899
870900 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
871
- value = (bo->paddr >> 32) & 0x3;
901
+ value = (state->iova[0] >> 32) & 0x3;
872902 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
873903 #endif
874904
....@@ -887,7 +917,8 @@
887917 tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
888918
889919 /* position the cursor */
890
- value = (state->crtc_y & 0x3fff) << 16 | (state->crtc_x & 0x3fff);
920
+ value = (plane->state->crtc_y & 0x3fff) << 16 |
921
+ (plane->state->crtc_x & 0x3fff);
891922 tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
892923 }
893924
....@@ -909,9 +940,16 @@
909940 }
910941
911942 static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
943
+ .prepare_fb = tegra_plane_prepare_fb,
944
+ .cleanup_fb = tegra_plane_cleanup_fb,
912945 .atomic_check = tegra_cursor_atomic_check,
913946 .atomic_update = tegra_cursor_atomic_update,
914947 .atomic_disable = tegra_cursor_atomic_disable,
948
+};
949
+
950
+static const uint64_t linear_modifiers[] = {
951
+ DRM_FORMAT_MOD_LINEAR,
952
+ DRM_FORMAT_MOD_INVALID
915953 };
916954
917955 static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
....@@ -942,7 +980,7 @@
942980
943981 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
944982 &tegra_plane_funcs, formats,
945
- num_formats, NULL,
983
+ num_formats, linear_modifiers,
946984 DRM_PLANE_TYPE_CURSOR, NULL);
947985 if (err < 0) {
948986 kfree(plane);
....@@ -950,6 +988,7 @@
950988 }
951989
952990 drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
991
+ drm_plane_create_zpos_immutable_property(&plane->base, 255);
953992
954993 return &plane->base;
955994 }
....@@ -1060,7 +1099,8 @@
10601099
10611100 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
10621101 &tegra_plane_funcs, formats,
1063
- num_formats, NULL, type, NULL);
1102
+ num_formats, linear_modifiers,
1103
+ type, NULL);
10641104 if (err < 0) {
10651105 kfree(plane);
10661106 return ERR_PTR(err);
....@@ -1072,6 +1112,8 @@
10721112 err = drm_plane_create_rotation_property(&plane->base,
10731113 DRM_MODE_ROTATE_0,
10741114 DRM_MODE_ROTATE_0 |
1115
+ DRM_MODE_ROTATE_180 |
1116
+ DRM_MODE_REFLECT_X |
10751117 DRM_MODE_REFLECT_Y);
10761118 if (err < 0)
10771119 dev_err(dc->dev, "failed to create rotation property: %d\n",
....@@ -1155,21 +1197,12 @@
11551197
11561198 static void tegra_crtc_reset(struct drm_crtc *crtc)
11571199 {
1158
- struct tegra_dc_state *state;
1200
+ struct tegra_dc_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
11591201
11601202 if (crtc->state)
1161
- __drm_atomic_helper_crtc_destroy_state(crtc->state);
1203
+ tegra_crtc_atomic_destroy_state(crtc, crtc->state);
11621204
1163
- kfree(crtc->state);
1164
- crtc->state = NULL;
1165
-
1166
- state = kzalloc(sizeof(*state), GFP_KERNEL);
1167
- if (state) {
1168
- crtc->state = &state->base;
1169
- crtc->state->crtc = crtc;
1170
- }
1171
-
1172
- drm_crtc_vblank_reset(crtc);
1205
+ __drm_atomic_helper_crtc_reset(crtc, &state->base);
11731206 }
11741207
11751208 static struct drm_crtc_state *
....@@ -1497,7 +1530,6 @@
14971530 struct drm_minor *minor = crtc->dev->primary;
14981531 struct dentry *root;
14991532 struct tegra_dc *dc = to_tegra_dc(crtc);
1500
- int err;
15011533
15021534 #ifdef CONFIG_DEBUG_FS
15031535 root = crtc->debugfs_entry;
....@@ -1513,17 +1545,9 @@
15131545 for (i = 0; i < count; i++)
15141546 dc->debugfs_files[i].data = dc;
15151547
1516
- err = drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
1517
- if (err < 0)
1518
- goto free;
1548
+ drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
15191549
15201550 return 0;
1521
-
1522
-free:
1523
- kfree(dc->debugfs_files);
1524
- dc->debugfs_files = NULL;
1525
-
1526
- return err;
15271551 }
15281552
15291553 static void tegra_dc_early_unregister(struct drm_crtc *crtc)
....@@ -1728,6 +1752,7 @@
17281752 {
17291753 struct tegra_dc *dc = to_tegra_dc(crtc);
17301754 u32 value;
1755
+ int err;
17311756
17321757 if (!tegra_dc_idle(dc)) {
17331758 tegra_dc_stop(dc);
....@@ -1774,7 +1799,9 @@
17741799
17751800 spin_unlock_irq(&crtc->dev->event_lock);
17761801
1777
- pm_runtime_put_sync(dc->dev);
1802
+ err = host1x_client_suspend(&dc->client);
1803
+ if (err < 0)
1804
+ dev_err(dc->dev, "failed to suspend: %d\n", err);
17781805 }
17791806
17801807 static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
....@@ -1784,8 +1811,13 @@
17841811 struct tegra_dc_state *state = to_dc_state(crtc->state);
17851812 struct tegra_dc *dc = to_tegra_dc(crtc);
17861813 u32 value;
1814
+ int err;
17871815
1788
- pm_runtime_get_sync(dc->dev);
1816
+ err = host1x_client_resume(&dc->client);
1817
+ if (err < 0) {
1818
+ dev_err(dc->dev, "failed to resume: %d\n", err);
1819
+ return;
1820
+ }
17891821
17901822 /* initialize display controller */
17911823 if (dc->syncpt) {
....@@ -1978,9 +2010,26 @@
19782010 return IRQ_HANDLED;
19792011 }
19802012
2013
+static bool tegra_dc_has_window_groups(struct tegra_dc *dc)
2014
+{
2015
+ unsigned int i;
2016
+
2017
+ if (!dc->soc->wgrps)
2018
+ return true;
2019
+
2020
+ for (i = 0; i < dc->soc->num_wgrps; i++) {
2021
+ const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
2022
+
2023
+ if (wgrp->dc == dc->pipe && wgrp->num_windows > 0)
2024
+ return true;
2025
+ }
2026
+
2027
+ return false;
2028
+}
2029
+
19812030 static int tegra_dc_init(struct host1x_client *client)
19822031 {
1983
- struct drm_device *drm = dev_get_drvdata(client->parent);
2032
+ struct drm_device *drm = dev_get_drvdata(client->host);
19842033 unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
19852034 struct tegra_dc *dc = host1x_client_to_dc(client);
19862035 struct tegra_drm *tegra = drm->dev_private;
....@@ -1988,13 +2037,29 @@
19882037 struct drm_plane *cursor = NULL;
19892038 int err;
19902039
2040
+ /*
2041
+ * XXX do not register DCs with no window groups because we cannot
2042
+ * assign a primary plane to them, which in turn will cause KMS to
2043
+ * crash.
2044
+ */
2045
+ if (!tegra_dc_has_window_groups(dc))
2046
+ return 0;
2047
+
2048
+ /*
2049
+ * Set the display hub as the host1x client parent for the display
2050
+ * controller. This is needed for the runtime reference counting that
2051
+ * ensures the display hub is always powered when any of the display
2052
+ * controllers are.
2053
+ */
2054
+ if (dc->soc->has_nvdisplay)
2055
+ client->parent = &tegra->hub->client;
2056
+
19912057 dc->syncpt = host1x_syncpt_request(client, flags);
19922058 if (!dc->syncpt)
19932059 dev_warn(dc->dev, "failed to allocate syncpoint\n");
19942060
1995
- dc->group = host1x_client_iommu_attach(client, true);
1996
- if (IS_ERR(dc->group)) {
1997
- err = PTR_ERR(dc->group);
2061
+ err = host1x_client_iommu_attach(client);
2062
+ if (err < 0 && err != -ENODEV) {
19982063 dev_err(client->dev, "failed to attach to domain: %d\n", err);
19992064 return err;
20002065 }
....@@ -2052,6 +2117,12 @@
20522117 goto cleanup;
20532118 }
20542119
2120
+ /*
2121
+ * Inherit the DMA parameters (such as maximum segment size) from the
2122
+ * parent host1x device.
2123
+ */
2124
+ client->dev->dma_parms = client->host->dma_parms;
2125
+
20552126 return 0;
20562127
20572128 cleanup:
....@@ -2061,7 +2132,7 @@
20612132 if (!IS_ERR(primary))
20622133 drm_plane_cleanup(primary);
20632134
2064
- host1x_client_iommu_detach(client, dc->group);
2135
+ host1x_client_iommu_detach(client);
20652136 host1x_syncpt_free(dc->syncpt);
20662137
20672138 return err;
....@@ -2072,6 +2143,12 @@
20722143 struct tegra_dc *dc = host1x_client_to_dc(client);
20732144 int err;
20742145
2146
+ if (!tegra_dc_has_window_groups(dc))
2147
+ return 0;
2148
+
2149
+ /* avoid a dangling pointer just in case this disappears */
2150
+ client->dev->dma_parms = NULL;
2151
+
20752152 devm_free_irq(dc->dev, dc->irq, dc);
20762153
20772154 err = tegra_dc_rgb_exit(dc);
....@@ -2080,15 +2157,80 @@
20802157 return err;
20812158 }
20822159
2083
- host1x_client_iommu_detach(client, dc->group);
2160
+ host1x_client_iommu_detach(client);
20842161 host1x_syncpt_free(dc->syncpt);
20852162
20862163 return 0;
20872164 }
20882165
2166
+static int tegra_dc_runtime_suspend(struct host1x_client *client)
2167
+{
2168
+ struct tegra_dc *dc = host1x_client_to_dc(client);
2169
+ struct device *dev = client->dev;
2170
+ int err;
2171
+
2172
+ err = reset_control_assert(dc->rst);
2173
+ if (err < 0) {
2174
+ dev_err(dev, "failed to assert reset: %d\n", err);
2175
+ return err;
2176
+ }
2177
+
2178
+ if (dc->soc->has_powergate)
2179
+ tegra_powergate_power_off(dc->powergate);
2180
+
2181
+ clk_disable_unprepare(dc->clk);
2182
+ pm_runtime_put_sync(dev);
2183
+
2184
+ return 0;
2185
+}
2186
+
2187
+static int tegra_dc_runtime_resume(struct host1x_client *client)
2188
+{
2189
+ struct tegra_dc *dc = host1x_client_to_dc(client);
2190
+ struct device *dev = client->dev;
2191
+ int err;
2192
+
2193
+ err = pm_runtime_resume_and_get(dev);
2194
+ if (err < 0) {
2195
+ dev_err(dev, "failed to get runtime PM: %d\n", err);
2196
+ return err;
2197
+ }
2198
+
2199
+ if (dc->soc->has_powergate) {
2200
+ err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2201
+ dc->rst);
2202
+ if (err < 0) {
2203
+ dev_err(dev, "failed to power partition: %d\n", err);
2204
+ goto put_rpm;
2205
+ }
2206
+ } else {
2207
+ err = clk_prepare_enable(dc->clk);
2208
+ if (err < 0) {
2209
+ dev_err(dev, "failed to enable clock: %d\n", err);
2210
+ goto put_rpm;
2211
+ }
2212
+
2213
+ err = reset_control_deassert(dc->rst);
2214
+ if (err < 0) {
2215
+ dev_err(dev, "failed to deassert reset: %d\n", err);
2216
+ goto disable_clk;
2217
+ }
2218
+ }
2219
+
2220
+ return 0;
2221
+
2222
+disable_clk:
2223
+ clk_disable_unprepare(dc->clk);
2224
+put_rpm:
2225
+ pm_runtime_put_sync(dev);
2226
+ return err;
2227
+}
2228
+
20892229 static const struct host1x_client_ops dc_client_ops = {
20902230 .init = tegra_dc_init,
20912231 .exit = tegra_dc_exit,
2232
+ .suspend = tegra_dc_runtime_suspend,
2233
+ .resume = tegra_dc_runtime_resume,
20922234 };
20932235
20942236 static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
....@@ -2234,8 +2376,59 @@
22342376 .num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps),
22352377 };
22362378
2379
+static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = {
2380
+ {
2381
+ .index = 0,
2382
+ .dc = 0,
2383
+ .windows = (const unsigned int[]) { 0 },
2384
+ .num_windows = 1,
2385
+ }, {
2386
+ .index = 1,
2387
+ .dc = 1,
2388
+ .windows = (const unsigned int[]) { 1 },
2389
+ .num_windows = 1,
2390
+ }, {
2391
+ .index = 2,
2392
+ .dc = 1,
2393
+ .windows = (const unsigned int[]) { 2 },
2394
+ .num_windows = 1,
2395
+ }, {
2396
+ .index = 3,
2397
+ .dc = 2,
2398
+ .windows = (const unsigned int[]) { 3 },
2399
+ .num_windows = 1,
2400
+ }, {
2401
+ .index = 4,
2402
+ .dc = 2,
2403
+ .windows = (const unsigned int[]) { 4 },
2404
+ .num_windows = 1,
2405
+ }, {
2406
+ .index = 5,
2407
+ .dc = 2,
2408
+ .windows = (const unsigned int[]) { 5 },
2409
+ .num_windows = 1,
2410
+ },
2411
+};
2412
+
2413
+static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
2414
+ .supports_background_color = true,
2415
+ .supports_interlacing = true,
2416
+ .supports_cursor = true,
2417
+ .supports_block_linear = true,
2418
+ .has_legacy_blending = false,
2419
+ .pitch_align = 64,
2420
+ .has_powergate = false,
2421
+ .coupled_pm = false,
2422
+ .has_nvdisplay = true,
2423
+ .wgrps = tegra194_dc_wgrps,
2424
+ .num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps),
2425
+};
2426
+
22372427 static const struct of_device_id tegra_dc_of_match[] = {
22382428 {
2429
+ .compatible = "nvidia,tegra194-dc",
2430
+ .data = &tegra194_dc_soc_info,
2431
+ }, {
22392432 .compatible = "nvidia,tegra186-dc",
22402433 .data = &tegra186_dc_soc_info,
22412434 }, {
....@@ -2296,10 +2489,10 @@
22962489 return 0;
22972490 }
22982491
2299
-static int tegra_dc_match_by_pipe(struct device *dev, void *data)
2492
+static int tegra_dc_match_by_pipe(struct device *dev, const void *data)
23002493 {
23012494 struct tegra_dc *dc = dev_get_drvdata(dev);
2302
- unsigned int pipe = (unsigned long)data;
2495
+ unsigned int pipe = (unsigned long)(void *)data;
23032496
23042497 return dc->pipe == pipe;
23052498 }
....@@ -2312,22 +2505,18 @@
23122505 * POWER_CONTROL registers during CRTC enabling.
23132506 */
23142507 if (dc->soc->coupled_pm && dc->pipe == 1) {
2315
- u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER;
2316
- struct device_link *link;
2317
- struct device *partner;
2508
+ struct device *companion;
2509
+ struct tegra_dc *parent;
23182510
2319
- partner = driver_find_device(dc->dev->driver, NULL, NULL,
2320
- tegra_dc_match_by_pipe);
2321
- if (!partner)
2511
+ companion = driver_find_device(dc->dev->driver, NULL, (const void *)0,
2512
+ tegra_dc_match_by_pipe);
2513
+ if (!companion)
23222514 return -EPROBE_DEFER;
23232515
2324
- link = device_link_add(dc->dev, partner, flags);
2325
- if (!link) {
2326
- dev_err(dc->dev, "failed to link controllers\n");
2327
- return -EINVAL;
2328
- }
2516
+ parent = dev_get_drvdata(companion);
2517
+ dc->client.parent = &parent->client;
23292518
2330
- dev_dbg(dc->dev, "coupled to %s\n", dev_name(partner));
2519
+ dev_dbg(dc->dev, "coupled to %s\n", dev_name(companion));
23312520 }
23322521
23332522 return 0;
....@@ -2335,7 +2524,6 @@
23352524
23362525 static int tegra_dc_probe(struct platform_device *pdev)
23372526 {
2338
- struct resource *regs;
23392527 struct tegra_dc *dc;
23402528 int err;
23412529
....@@ -2376,8 +2564,10 @@
23762564 usleep_range(2000, 4000);
23772565
23782566 err = reset_control_assert(dc->rst);
2379
- if (err < 0)
2567
+ if (err < 0) {
2568
+ clk_disable_unprepare(dc->clk);
23802569 return err;
2570
+ }
23812571
23822572 usleep_range(2000, 4000);
23832573
....@@ -2392,20 +2582,23 @@
23922582 tegra_powergate_power_off(dc->powergate);
23932583 }
23942584
2395
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2396
- dc->regs = devm_ioremap_resource(&pdev->dev, regs);
2585
+ dc->regs = devm_platform_ioremap_resource(pdev, 0);
23972586 if (IS_ERR(dc->regs))
23982587 return PTR_ERR(dc->regs);
23992588
24002589 dc->irq = platform_get_irq(pdev, 0);
2401
- if (dc->irq < 0) {
2402
- dev_err(&pdev->dev, "failed to get IRQ\n");
2590
+ if (dc->irq < 0)
24032591 return -ENXIO;
2404
- }
24052592
24062593 err = tegra_dc_rgb_probe(dc);
24072594 if (err < 0 && err != -ENODEV) {
2408
- dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
2595
+ const char *level = KERN_ERR;
2596
+
2597
+ if (err == -EPROBE_DEFER)
2598
+ level = KERN_DEBUG;
2599
+
2600
+ dev_printk(level, dc->dev, "failed to probe RGB output: %d\n",
2601
+ err);
24092602 return err;
24102603 }
24112604
....@@ -2420,10 +2613,16 @@
24202613 if (err < 0) {
24212614 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
24222615 err);
2423
- return err;
2616
+ goto disable_pm;
24242617 }
24252618
24262619 return 0;
2620
+
2621
+disable_pm:
2622
+ pm_runtime_disable(&pdev->dev);
2623
+ tegra_dc_rgb_remove(dc);
2624
+
2625
+ return err;
24272626 }
24282627
24292628 static int tegra_dc_remove(struct platform_device *pdev)
....@@ -2449,65 +2648,10 @@
24492648 return 0;
24502649 }
24512650
2452
-#ifdef CONFIG_PM
2453
-static int tegra_dc_suspend(struct device *dev)
2454
-{
2455
- struct tegra_dc *dc = dev_get_drvdata(dev);
2456
- int err;
2457
-
2458
- err = reset_control_assert(dc->rst);
2459
- if (err < 0) {
2460
- dev_err(dev, "failed to assert reset: %d\n", err);
2461
- return err;
2462
- }
2463
-
2464
- if (dc->soc->has_powergate)
2465
- tegra_powergate_power_off(dc->powergate);
2466
-
2467
- clk_disable_unprepare(dc->clk);
2468
-
2469
- return 0;
2470
-}
2471
-
2472
-static int tegra_dc_resume(struct device *dev)
2473
-{
2474
- struct tegra_dc *dc = dev_get_drvdata(dev);
2475
- int err;
2476
-
2477
- if (dc->soc->has_powergate) {
2478
- err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2479
- dc->rst);
2480
- if (err < 0) {
2481
- dev_err(dev, "failed to power partition: %d\n", err);
2482
- return err;
2483
- }
2484
- } else {
2485
- err = clk_prepare_enable(dc->clk);
2486
- if (err < 0) {
2487
- dev_err(dev, "failed to enable clock: %d\n", err);
2488
- return err;
2489
- }
2490
-
2491
- err = reset_control_deassert(dc->rst);
2492
- if (err < 0) {
2493
- dev_err(dev, "failed to deassert reset: %d\n", err);
2494
- return err;
2495
- }
2496
- }
2497
-
2498
- return 0;
2499
-}
2500
-#endif
2501
-
2502
-static const struct dev_pm_ops tegra_dc_pm_ops = {
2503
- SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
2504
-};
2505
-
25062651 struct platform_driver tegra_dc_driver = {
25072652 .driver = {
25082653 .name = "tegra-dc",
25092654 .of_match_table = tegra_dc_of_match,
2510
- .pm = &tegra_dc_pm_ops,
25112655 },
25122656 .probe = tegra_dc_probe,
25132657 .remove = tegra_dc_remove,