diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-11-07 01:43:00 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-11-28 18:57:45 -0500 |
commit | 6c5a04249d7afeea3e0ed971e7813f84e29a1706 (patch) | |
tree | c96db5880f784974c33b3470a784527cd80d1c66 /drivers/gpu/drm/nouveau | |
parent | fb445b3c23a4ae75190e814d952be6dce6181abe (diff) |
drm/nvd0/disp: move link training helpers into core as display methods
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c | 93 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c | 126 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/core/class.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvd0_display.c | 94 |
9 files changed, 295 insertions, 84 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2ca1d39d5027..0eb4c2d5f92e 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -137,6 +137,8 @@ nouveau-y += core/engine/disp/nva0.o | |||
137 | nouveau-y += core/engine/disp/nva3.o | 137 | nouveau-y += core/engine/disp/nva3.o |
138 | nouveau-y += core/engine/disp/nvd0.o | 138 | nouveau-y += core/engine/disp/nvd0.o |
139 | nouveau-y += core/engine/disp/nve0.o | 139 | nouveau-y += core/engine/disp/nve0.o |
140 | nouveau-y += core/engine/disp/sornv50.o | ||
141 | nouveau-y += core/engine/disp/sornvd0.o | ||
140 | nouveau-y += core/engine/disp/vga.o | 142 | nouveau-y += core/engine/disp/vga.o |
141 | nouveau-y += core/engine/fifo/base.o | 143 | nouveau-y += core/engine/fifo/base.o |
142 | nouveau-y += core/engine/fifo/nv04.o | 144 | nouveau-y += core/engine/fifo/nv04.o |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index f269138ade6b..eada7bc408be 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <engine/dmaobj.h> | 8 | #include <engine/dmaobj.h> |
9 | #include <engine/disp.h> | 9 | #include <engine/disp.h> |
10 | 10 | ||
11 | struct dcb_output; | ||
12 | |||
11 | struct nv50_disp_priv { | 13 | struct nv50_disp_priv { |
12 | struct nouveau_disp base; | 14 | struct nouveau_disp base; |
13 | struct nouveau_oclass *sclass; | 15 | struct nouveau_oclass *sclass; |
@@ -19,9 +21,31 @@ struct nv50_disp_priv { | |||
19 | } dac; | 21 | } dac; |
20 | struct { | 22 | struct { |
21 | int nr; | 23 | int nr; |
24 | int (*dp_train)(struct nv50_disp_priv *, int sor, int link, | ||
25 | u16 type, u16 mask, u32 data, | ||
26 | struct dcb_output *); | ||
27 | int (*dp_lnkctl)(struct nv50_disp_priv *, int sor, int link, | ||
28 | int head, u16 type, u16 mask, u32 data, | ||
29 | struct dcb_output *); | ||
30 | int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link, | ||
31 | int lane, u16 type, u16 mask, u32 data, | ||
32 | struct dcb_output *); | ||
22 | } sor; | 33 | } sor; |
23 | }; | 34 | }; |
24 | 35 | ||
36 | extern struct nouveau_omthds nva3_disp_base_omthds[]; | ||
37 | |||
38 | #define SOR_MTHD(n) (n), (n) + 0x3f | ||
39 | |||
40 | int nv50_sor_mthd(struct nouveau_object *, u32, void *, u32); | ||
41 | |||
42 | int nvd0_sor_dp_train(struct nv50_disp_priv *, int, int, u16, u16, u32, | ||
43 | struct dcb_output *); | ||
44 | int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, | ||
45 | struct dcb_output *); | ||
46 | int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, | ||
47 | struct dcb_output *); | ||
48 | |||
25 | struct nv50_disp_base { | 49 | struct nv50_disp_base { |
26 | struct nouveau_parent base; | 50 | struct nouveau_parent base; |
27 | struct nouveau_ramht *ramht; | 51 | struct nouveau_ramht *ramht; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index 08945cb3ea8e..ec0ac5bc874e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c | |||
@@ -39,6 +39,17 @@ nva3_disp_sclass[] = { | |||
39 | {} | 39 | {} |
40 | }; | 40 | }; |
41 | 41 | ||
42 | struct nouveau_omthds | ||
43 | nva3_disp_base_omthds[] = { | ||
44 | { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, | ||
45 | { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, | ||
46 | { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, | ||
47 | { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd }, | ||
48 | { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd }, | ||
49 | { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd }, | ||
50 | {}, | ||
51 | }; | ||
52 | |||
42 | static struct nouveau_oclass | 53 | static struct nouveau_oclass |
43 | nva3_disp_base_oclass[] = { | 54 | nva3_disp_base_oclass[] = { |
44 | { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs }, | 55 | { NVA3_DISP_CLASS, &nv50_disp_base_ofuncs }, |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 17d452cd6d39..f5ebbac87129 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c | |||
@@ -552,7 +552,7 @@ nvd0_disp_base_ofuncs = { | |||
552 | 552 | ||
553 | static struct nouveau_oclass | 553 | static struct nouveau_oclass |
554 | nvd0_disp_base_oclass[] = { | 554 | nvd0_disp_base_oclass[] = { |
555 | { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs }, | 555 | { NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, |
556 | {} | 556 | {} |
557 | }; | 557 | }; |
558 | 558 | ||
@@ -896,6 +896,9 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
896 | priv->head.nr = nv_rd32(priv, 0x022448); | 896 | priv->head.nr = nv_rd32(priv, 0x022448); |
897 | priv->dac.nr = 3; | 897 | priv->dac.nr = 3; |
898 | priv->sor.nr = 4; | 898 | priv->sor.nr = 4; |
899 | priv->sor.dp_train = nvd0_sor_dp_train; | ||
900 | priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; | ||
901 | priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; | ||
899 | 902 | ||
900 | INIT_LIST_HEAD(&priv->base.vblank.list); | 903 | INIT_LIST_HEAD(&priv->base.vblank.list); |
901 | spin_lock_init(&priv->base.vblank.lock); | 904 | spin_lock_init(&priv->base.vblank.lock); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index 2fbad90f2f35..ed5ab9baa8eb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c | |||
@@ -41,7 +41,7 @@ nve0_disp_sclass[] = { | |||
41 | 41 | ||
42 | static struct nouveau_oclass | 42 | static struct nouveau_oclass |
43 | nve0_disp_base_oclass[] = { | 43 | nve0_disp_base_oclass[] = { |
44 | { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs }, | 44 | { NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, |
45 | {} | 45 | {} |
46 | }; | 46 | }; |
47 | 47 | ||
@@ -66,6 +66,9 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
66 | priv->head.nr = nv_rd32(priv, 0x022448); | 66 | priv->head.nr = nv_rd32(priv, 0x022448); |
67 | priv->dac.nr = 3; | 67 | priv->dac.nr = 3; |
68 | priv->sor.nr = 4; | 68 | priv->sor.nr = 4; |
69 | priv->sor.dp_train = nvd0_sor_dp_train; | ||
70 | priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; | ||
71 | priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; | ||
69 | 72 | ||
70 | INIT_LIST_HEAD(&priv->base.vblank.list); | 73 | INIT_LIST_HEAD(&priv->base.vblank.list); |
71 | spin_lock_init(&priv->base.vblank.lock); | 74 | spin_lock_init(&priv->base.vblank.lock); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c new file mode 100644 index 000000000000..1ebf2bd372f1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include <core/os.h> | ||
26 | #include <core/class.h> | ||
27 | |||
28 | #include <subdev/bios.h> | ||
29 | #include <subdev/bios/dcb.h> | ||
30 | |||
31 | #include "nv50.h" | ||
32 | |||
33 | int | ||
34 | nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) | ||
35 | { | ||
36 | struct nv50_disp_priv *priv = (void *)object->engine; | ||
37 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
38 | const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12; | ||
39 | const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; | ||
40 | const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2; | ||
41 | const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); | ||
42 | const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or); | ||
43 | struct dcb_output outp = { | ||
44 | .type = type, | ||
45 | .or = (1 << or), | ||
46 | .sorconf.link = (1 << link), | ||
47 | }; | ||
48 | u8 ver, hdr, idx = 0; | ||
49 | u32 data; | ||
50 | int ret = -EINVAL; | ||
51 | |||
52 | if (size < sizeof(u32)) | ||
53 | return -EINVAL; | ||
54 | |||
55 | while (type && (data = dcb_outp(bios, idx++, &ver, &hdr))) { | ||
56 | u32 conn = nv_ro32(bios, data + 0); | ||
57 | u32 conf = nv_ro32(bios, data + 4); | ||
58 | if ((conn & 0x00300000) || | ||
59 | (conn & 0x0000000f) != type || | ||
60 | (conn & 0x0f000000) != (0x01000000 << or)) | ||
61 | continue; | ||
62 | |||
63 | if ( (mask & 0x00c0) && (mask & 0x00c0) != | ||
64 | ((mask & 0x00c0) & ((conf & 0x00000030) << 2))) | ||
65 | continue; | ||
66 | |||
67 | outp.connector = (conn & 0x0000f000) >> 12; | ||
68 | } | ||
69 | |||
70 | if (data == 0x0000) | ||
71 | return -ENODEV; | ||
72 | |||
73 | data = *(u32 *)args; | ||
74 | switch (mthd & ~0x3f) { | ||
75 | case NV94_DISP_SOR_DP_TRAIN: | ||
76 | ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); | ||
77 | break; | ||
78 | case NV94_DISP_SOR_DP_LNKCTL: | ||
79 | ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp); | ||
80 | break; | ||
81 | case NV94_DISP_SOR_DP_DRVCTL(0): | ||
82 | case NV94_DISP_SOR_DP_DRVCTL(1): | ||
83 | case NV94_DISP_SOR_DP_DRVCTL(2): | ||
84 | case NV94_DISP_SOR_DP_DRVCTL(3): | ||
85 | ret = priv->sor.dp_drvctl(priv, or, link, (mthd & 0xc0) >> 6, | ||
86 | type, mask, data, &outp); | ||
87 | break; | ||
88 | default: | ||
89 | BUG_ON(1); | ||
90 | } | ||
91 | |||
92 | return ret; | ||
93 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c new file mode 100644 index 000000000000..c37ce7e29f5d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include <core/os.h> | ||
26 | #include <core/class.h> | ||
27 | |||
28 | #include <subdev/bios.h> | ||
29 | #include <subdev/bios/dcb.h> | ||
30 | #include <subdev/bios/dp.h> | ||
31 | #include <subdev/bios/init.h> | ||
32 | |||
33 | #include "nv50.h" | ||
34 | |||
35 | static inline u32 | ||
36 | nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) | ||
37 | { | ||
38 | static const u8 nvd0[] = { 16, 8, 0, 24 }; | ||
39 | return nvd0[lane]; | ||
40 | } | ||
41 | |||
42 | int | ||
43 | nvd0_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, | ||
44 | u16 type, u16 mask, u32 data, struct dcb_output *info) | ||
45 | { | ||
46 | const u32 loff = (or * 0x800) + (link * 0x80); | ||
47 | const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); | ||
48 | nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * patt); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | int | ||
53 | nvd0_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, | ||
54 | u16 type, u16 mask, u32 data, struct dcb_output *dcbo) | ||
55 | { | ||
56 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
57 | const u32 loff = (or * 0x800) + (link * 0x80); | ||
58 | const u32 soff = (or * 0x800); | ||
59 | const u8 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8; | ||
60 | const u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT); | ||
61 | u32 dpctrl = 0x00000000; | ||
62 | u32 clksor = 0x00000000; | ||
63 | u32 outp, lane = 0; | ||
64 | u8 ver, hdr, cnt, len; | ||
65 | struct nvbios_dpout info; | ||
66 | int i; | ||
67 | |||
68 | outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); | ||
69 | if (outp && info.lnkcmp) { | ||
70 | struct nvbios_init init = { | ||
71 | .subdev = nv_subdev(priv), | ||
72 | .bios = bios, | ||
73 | .offset = 0x0000, | ||
74 | .outp = dcbo, | ||
75 | .crtc = head, | ||
76 | .execute = 1, | ||
77 | }; | ||
78 | |||
79 | while (nv_ro08(bios, info.lnkcmp) < link_bw) | ||
80 | info.lnkcmp += 3; | ||
81 | init.offset = nv_ro16(bios, info.lnkcmp + 1); | ||
82 | |||
83 | nvbios_exec(&init); | ||
84 | } | ||
85 | |||
86 | clksor |= link_bw << 18; | ||
87 | dpctrl |= ((1 << link_nr) - 1) << 16; | ||
88 | if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) | ||
89 | dpctrl |= 0x00004000; | ||
90 | |||
91 | for (i = 0; i < link_nr; i++) | ||
92 | lane |= 1 << (nvd0_sor_dp_lane_map(priv, i) >> 3); | ||
93 | |||
94 | nv_mask(priv, 0x612300 + soff, 0x007c0000, clksor); | ||
95 | nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); | ||
96 | nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | int | ||
101 | nvd0_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, | ||
102 | u16 type, u16 mask, u32 data, struct dcb_output *dcbo) | ||
103 | { | ||
104 | struct nouveau_bios *bios = nouveau_bios(priv); | ||
105 | const u32 loff = (or * 0x800) + (link * 0x80); | ||
106 | const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; | ||
107 | const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE); | ||
108 | u32 addr, shift = nvd0_sor_dp_lane_map(priv, lane); | ||
109 | u8 ver, hdr, cnt, len; | ||
110 | struct nvbios_dpout outp; | ||
111 | struct nvbios_dpcfg ocfg; | ||
112 | |||
113 | addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); | ||
114 | if (!addr) | ||
115 | return -ENODEV; | ||
116 | |||
117 | addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); | ||
118 | if (!addr) | ||
119 | return -EINVAL; | ||
120 | |||
121 | nv_mask(priv, 0x61c118 + loff, 0x000000ff << shift, ocfg.drv << shift); | ||
122 | nv_mask(priv, 0x61c120 + loff, 0x000000ff << shift, ocfg.pre << shift); | ||
123 | nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8); | ||
124 | nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000); | ||
125 | return 0; | ||
126 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 784e47aff640..0445b0fdd2f0 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h | |||
@@ -171,6 +171,25 @@ struct nve0_channel_ind_class { | |||
171 | #define NVD0_DISP_CLASS 0x00009070 | 171 | #define NVD0_DISP_CLASS 0x00009070 |
172 | #define NVE0_DISP_CLASS 0x00009170 | 172 | #define NVE0_DISP_CLASS 0x00009170 |
173 | 173 | ||
174 | #define NV50_DISP_SOR_MTHD 0x00010000 | ||
175 | #define NV50_DISP_SOR_MTHD_TYPE 0x0000f000 | ||
176 | #define NV50_DISP_SOR_MTHD_HEAD 0x00000018 | ||
177 | #define NV50_DISP_SOR_MTHD_LINK 0x00000004 | ||
178 | #define NV50_DISP_SOR_MTHD_OR 0x00000003 | ||
179 | |||
180 | #define NV94_DISP_SOR_DP_TRAIN 0x00016000 | ||
181 | #define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003 | ||
182 | #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000 | ||
183 | #define NV94_DISP_SOR_DP_LNKCTL 0x00016040 | ||
184 | #define NV94_DISP_SOR_DP_LNKCTL_FRAME 0x80000000 | ||
185 | #define NV94_DISP_SOR_DP_LNKCTL_FRAME_STD 0x00000000 | ||
186 | #define NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH 0x80000000 | ||
187 | #define NV94_DISP_SOR_DP_LNKCTL_WIDTH 0x00001f00 | ||
188 | #define NV94_DISP_SOR_DP_LNKCTL_COUNT 0x00000007 | ||
189 | #define NV94_DISP_SOR_DP_DRVCTL(l) ((l) * 0x40 + 0x00016100) | ||
190 | #define NV94_DISP_SOR_DP_DRVCTL_VS 0x00000300 | ||
191 | #define NV94_DISP_SOR_DP_DRVCTL_PE 0x00000003 | ||
192 | |||
174 | struct nv50_display_class { | 193 | struct nv50_display_class { |
175 | }; | 194 | }; |
176 | 195 | ||
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index fa0ca63e333d..39ceff274db8 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c | |||
@@ -1350,107 +1350,37 @@ nvd0_hdmi_disconnect(struct drm_encoder *encoder) | |||
1350 | /****************************************************************************** | 1350 | /****************************************************************************** |
1351 | * SOR | 1351 | * SOR |
1352 | *****************************************************************************/ | 1352 | *****************************************************************************/ |
1353 | static inline u32 | ||
1354 | nvd0_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) | ||
1355 | { | ||
1356 | static const u8 nvd0[] = { 16, 8, 0, 24 }; | ||
1357 | return nvd0[lane]; | ||
1358 | } | ||
1359 | |||
1360 | static void | 1353 | static void |
1361 | nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) | 1354 | nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) |
1362 | { | 1355 | { |
1363 | struct nouveau_device *device = nouveau_dev(dev); | 1356 | struct nvd0_disp *disp = nvd0_disp(dev); |
1364 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 1357 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); |
1365 | const u32 loff = (or * 0x800) + (link * 0x80); | 1358 | const u32 moff = (link << 2) | or; |
1366 | nv_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); | 1359 | nv_call(disp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern); |
1367 | } | 1360 | } |
1368 | 1361 | ||
1369 | static void | 1362 | static void |
1370 | nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | 1363 | nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, |
1371 | u8 lane, u8 swing, u8 preem) | 1364 | u8 lane, u8 swing, u8 preem) |
1372 | { | 1365 | { |
1373 | struct nouveau_device *device = nouveau_dev(dev); | 1366 | struct nvd0_disp *disp = nvd0_disp(dev); |
1374 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
1375 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 1367 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); |
1376 | const u32 loff = (or * 0x800) + (link * 0x80); | 1368 | const u32 moff = (link << 2) | or; |
1377 | u32 shift = nvd0_sor_dp_lane_map(dev, dcb, lane); | 1369 | const u32 data = (swing << 8) | preem; |
1378 | u32 mask = 0x000000ff << shift; | 1370 | nv_call(disp->core, NV94_DISP_SOR_DP_DRVCTL(lane) + moff, data); |
1379 | u8 *table, *entry, *config = NULL; | ||
1380 | |||
1381 | switch (swing) { | ||
1382 | case 0: preem += 0; break; | ||
1383 | case 1: preem += 4; break; | ||
1384 | case 2: preem += 7; break; | ||
1385 | case 3: preem += 9; break; | ||
1386 | } | ||
1387 | |||
1388 | table = nouveau_dp_bios_data(dev, dcb, &entry); | ||
1389 | if (table) { | ||
1390 | if (table[0] == 0x30) { | ||
1391 | config = entry + table[4]; | ||
1392 | config += table[5] * preem; | ||
1393 | } else | ||
1394 | if (table[0] == 0x40) { | ||
1395 | config = table + table[1]; | ||
1396 | config += table[2] * table[3]; | ||
1397 | config += table[6] * preem; | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1401 | if (!config) { | ||
1402 | NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); | ||
1403 | return; | ||
1404 | } | ||
1405 | |||
1406 | nv_mask(device, 0x61c118 + loff, mask, config[1] << shift); | ||
1407 | nv_mask(device, 0x61c120 + loff, mask, config[2] << shift); | ||
1408 | nv_mask(device, 0x61c130 + loff, 0x0000ff00, config[3] << 8); | ||
1409 | nv_mask(device, 0x61c13c + loff, 0x00000000, 0x00000000); | ||
1410 | } | 1371 | } |
1411 | 1372 | ||
1412 | static void | 1373 | static void |
1413 | nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | 1374 | nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, |
1414 | int link_nr, u32 link_bw, bool enhframe) | 1375 | int link_nr, u32 link_bw, bool enhframe) |
1415 | { | 1376 | { |
1416 | struct nouveau_device *device = nouveau_dev(dev); | 1377 | struct nvd0_disp *disp = nvd0_disp(dev); |
1417 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 1378 | const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); |
1418 | const u32 loff = (or * 0x800) + (link * 0x80); | 1379 | const u32 moff = (crtc << 3) | (link << 2) | or; |
1419 | const u32 soff = (or * 0x800); | 1380 | u32 data = ((link_bw / 27000) << 8) | link_nr; |
1420 | u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & ~0x001f4000; | ||
1421 | u32 clksor = nv_rd32(device, 0x612300 + soff) & ~0x007c0000; | ||
1422 | u32 script = 0x0000, lane_mask = 0; | ||
1423 | u8 *table, *entry; | ||
1424 | int i; | ||
1425 | |||
1426 | link_bw /= 27000; | ||
1427 | |||
1428 | table = nouveau_dp_bios_data(dev, dcb, &entry); | ||
1429 | if (table) { | ||
1430 | if (table[0] == 0x30) entry = ROMPTR(dev, entry[10]); | ||
1431 | else if (table[0] == 0x40) entry = ROMPTR(dev, entry[9]); | ||
1432 | else entry = NULL; | ||
1433 | |||
1434 | while (entry) { | ||
1435 | if (entry[0] >= link_bw) | ||
1436 | break; | ||
1437 | entry += 3; | ||
1438 | } | ||
1439 | |||
1440 | nouveau_bios_run_init_table(dev, script, dcb, crtc); | ||
1441 | } | ||
1442 | |||
1443 | clksor |= link_bw << 18; | ||
1444 | dpctrl |= ((1 << link_nr) - 1) << 16; | ||
1445 | if (enhframe) | 1381 | if (enhframe) |
1446 | dpctrl |= 0x00004000; | 1382 | data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH; |
1447 | 1383 | nv_call(disp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data); | |
1448 | for (i = 0; i < link_nr; i++) | ||
1449 | lane_mask |= 1 << (nvd0_sor_dp_lane_map(dev, dcb, i) >> 3); | ||
1450 | |||
1451 | nv_wr32(device, 0x612300 + soff, clksor); | ||
1452 | nv_wr32(device, 0x61c10c + loff, dpctrl); | ||
1453 | nv_mask(device, 0x61c130 + loff, 0x0000000f, lane_mask); | ||
1454 | } | 1384 | } |
1455 | 1385 | ||
1456 | static void | 1386 | static void |