diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
40 files changed, 509 insertions, 299 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index c617f0480071..8bbb58f94a19 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c | |||
@@ -66,10 +66,8 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg, | |||
66 | 66 | ||
67 | ret = nouveau_handle_create(nv_object(client), ~0, ~0, | 67 | ret = nouveau_handle_create(nv_object(client), ~0, ~0, |
68 | nv_object(client), &client->root); | 68 | nv_object(client), &client->root); |
69 | if (ret) { | 69 | if (ret) |
70 | nouveau_namedb_destroy(&client->base); | ||
71 | return ret; | 70 | return ret; |
72 | } | ||
73 | 71 | ||
74 | /* prevent init/fini being called, os in in charge of this */ | 72 | /* prevent init/fini being called, os in in charge of this */ |
75 | atomic_set(&nv_object(client)->usecount, 2); | 73 | atomic_set(&nv_object(client)->usecount, 2); |
diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c index b8d2cbf8a7a7..264c2b338ac3 100644 --- a/drivers/gpu/drm/nouveau/core/core/handle.c +++ b/drivers/gpu/drm/nouveau/core/core/handle.c | |||
@@ -109,7 +109,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, | |||
109 | while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) | 109 | while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) |
110 | namedb = namedb->parent; | 110 | namedb = namedb->parent; |
111 | 111 | ||
112 | handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL); | 112 | handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
113 | if (!handle) | 113 | if (!handle) |
114 | return -ENOMEM; | 114 | return -ENOMEM; |
115 | 115 | ||
@@ -146,6 +146,9 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, | |||
146 | } | 146 | } |
147 | 147 | ||
148 | hprintk(handle, TRACE, "created\n"); | 148 | hprintk(handle, TRACE, "created\n"); |
149 | |||
150 | *phandle = handle; | ||
151 | |||
149 | return 0; | 152 | return 0; |
150 | } | 153 | } |
151 | 154 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 0f09af135415..ca1a7d76a95b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -851,20 +851,23 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
851 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 851 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) |
852 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); | 852 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); |
853 | 853 | ||
854 | if (nv_device(priv)->chipset < 0x90 || | 854 | if (!(ctrl & (1 << head))) { |
855 | nv_device(priv)->chipset == 0x92 || | 855 | if (nv_device(priv)->chipset < 0x90 || |
856 | nv_device(priv)->chipset == 0xa0) { | 856 | nv_device(priv)->chipset == 0x92 || |
857 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 857 | nv_device(priv)->chipset == 0xa0) { |
858 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); | 858 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) |
859 | i += 3; | 859 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); |
860 | } else { | 860 | i += 4; |
861 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 861 | } else { |
862 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); | 862 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) |
863 | i += 3; | 863 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); |
864 | i += 4; | ||
865 | } | ||
864 | } | 866 | } |
865 | 867 | ||
866 | if (!(ctrl & (1 << head))) | 868 | if (!(ctrl & (1 << head))) |
867 | return false; | 869 | return false; |
870 | i--; | ||
868 | 871 | ||
869 | data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); | 872 | data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); |
870 | if (data) { | 873 | if (data) { |
@@ -898,20 +901,23 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
898 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 901 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) |
899 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); | 902 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); |
900 | 903 | ||
901 | if (nv_device(priv)->chipset < 0x90 || | 904 | if (!(ctrl & (1 << head))) { |
902 | nv_device(priv)->chipset == 0x92 || | 905 | if (nv_device(priv)->chipset < 0x90 || |
903 | nv_device(priv)->chipset == 0xa0) { | 906 | nv_device(priv)->chipset == 0x92 || |
904 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 907 | nv_device(priv)->chipset == 0xa0) { |
905 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); | 908 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) |
906 | i += 3; | 909 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); |
907 | } else { | 910 | i += 4; |
908 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 911 | } else { |
909 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); | 912 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) |
910 | i += 3; | 913 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); |
914 | i += 4; | ||
915 | } | ||
911 | } | 916 | } |
912 | 917 | ||
913 | if (!(ctrl & (1 << head))) | 918 | if (!(ctrl & (1 << head))) |
914 | return 0x0000; | 919 | return 0x0000; |
920 | i--; | ||
915 | 921 | ||
916 | data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); | 922 | data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); |
917 | if (!data) | 923 | if (!data) |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc index 7b715fda2763..62ab231cd6b6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc | |||
@@ -57,6 +57,11 @@ chipsets: | |||
57 | .b16 #nve4_gpc_mmio_tail | 57 | .b16 #nve4_gpc_mmio_tail |
58 | .b16 #nve4_tpc_mmio_head | 58 | .b16 #nve4_tpc_mmio_head |
59 | .b16 #nve4_tpc_mmio_tail | 59 | .b16 #nve4_tpc_mmio_tail |
60 | .b8 0xe6 0 0 0 | ||
61 | .b16 #nve4_gpc_mmio_head | ||
62 | .b16 #nve4_gpc_mmio_tail | ||
63 | .b16 #nve4_tpc_mmio_head | ||
64 | .b16 #nve4_tpc_mmio_tail | ||
60 | .b8 0 0 0 0 | 65 | .b8 0 0 0 0 |
61 | 66 | ||
62 | // GPC mmio lists | 67 | // GPC mmio lists |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h index 26c2165bad0f..09ee4702c8b2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h | |||
@@ -34,13 +34,16 @@ uint32_t nve0_grgpc_data[] = { | |||
34 | 0x00000000, | 34 | 0x00000000, |
35 | /* 0x0064: chipsets */ | 35 | /* 0x0064: chipsets */ |
36 | 0x000000e4, | 36 | 0x000000e4, |
37 | 0x01040080, | 37 | 0x0110008c, |
38 | 0x014c0104, | 38 | 0x01580110, |
39 | 0x000000e7, | 39 | 0x000000e7, |
40 | 0x01040080, | 40 | 0x0110008c, |
41 | 0x014c0104, | 41 | 0x01580110, |
42 | 0x000000e6, | ||
43 | 0x0110008c, | ||
44 | 0x01580110, | ||
42 | 0x00000000, | 45 | 0x00000000, |
43 | /* 0x0080: nve4_gpc_mmio_head */ | 46 | /* 0x008c: nve4_gpc_mmio_head */ |
44 | 0x00000380, | 47 | 0x00000380, |
45 | 0x04000400, | 48 | 0x04000400, |
46 | 0x0800040c, | 49 | 0x0800040c, |
@@ -74,8 +77,8 @@ uint32_t nve0_grgpc_data[] = { | |||
74 | 0x14003100, | 77 | 0x14003100, |
75 | 0x000031d0, | 78 | 0x000031d0, |
76 | 0x040031e0, | 79 | 0x040031e0, |
77 | /* 0x0104: nve4_gpc_mmio_tail */ | 80 | /* 0x0110: nve4_gpc_mmio_tail */ |
78 | /* 0x0104: nve4_tpc_mmio_head */ | 81 | /* 0x0110: nve4_tpc_mmio_head */ |
79 | 0x00000048, | 82 | 0x00000048, |
80 | 0x00000064, | 83 | 0x00000064, |
81 | 0x00000088, | 84 | 0x00000088, |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc index acfc457654bd..0bcfa4d447e5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc | |||
@@ -754,6 +754,16 @@ ctx_mmio_exec: | |||
754 | // on load it means: "a save preceeded this load" | 754 | // on load it means: "a save preceeded this load" |
755 | // | 755 | // |
756 | ctx_xfer: | 756 | ctx_xfer: |
757 | // according to mwk, some kind of wait for idle | ||
758 | mov $r15 0xc00 | ||
759 | shl b32 $r15 6 | ||
760 | mov $r14 4 | ||
761 | iowr I[$r15 + 0x200] $r14 | ||
762 | ctx_xfer_idle: | ||
763 | iord $r14 I[$r15 + 0x000] | ||
764 | and $r14 0x2000 | ||
765 | bra ne #ctx_xfer_idle | ||
766 | |||
757 | bra not $p1 #ctx_xfer_pre | 767 | bra not $p1 #ctx_xfer_pre |
758 | bra $p2 #ctx_xfer_pre_load | 768 | bra $p2 #ctx_xfer_pre_load |
759 | ctx_xfer_pre: | 769 | ctx_xfer_pre: |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index 85a8d556f484..bb03d2a1d57b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h | |||
@@ -799,79 +799,80 @@ uint32_t nvc0_grhub_code[] = { | |||
799 | 0x01fa0613, | 799 | 0x01fa0613, |
800 | 0xf803f806, | 800 | 0xf803f806, |
801 | /* 0x0829: ctx_xfer */ | 801 | /* 0x0829: ctx_xfer */ |
802 | 0x0611f400, | 802 | 0x00f7f100, |
803 | /* 0x082f: ctx_xfer_pre */ | 803 | 0x06f4b60c, |
804 | 0xf01102f4, | 804 | 0xd004e7f0, |
805 | 0x21f510f7, | 805 | /* 0x0836: ctx_xfer_idle */ |
806 | 0x21f50698, | 806 | 0xfecf80fe, |
807 | 0x11f40631, | 807 | 0x00e4f100, |
808 | /* 0x083d: ctx_xfer_pre_load */ | 808 | 0xf91bf420, |
809 | 0x02f7f01c, | 809 | 0xf40611f4, |
810 | 0x065721f5, | 810 | /* 0x0846: ctx_xfer_pre */ |
811 | 0x066621f5, | 811 | 0xf7f01102, |
812 | 0x067821f5, | 812 | 0x9821f510, |
813 | 0x21f5f4bd, | 813 | 0x3121f506, |
814 | 0x21f50657, | 814 | 0x1c11f406, |
815 | /* 0x0856: ctx_xfer_exec */ | 815 | /* 0x0854: ctx_xfer_pre_load */ |
816 | 0x019806b8, | 816 | 0xf502f7f0, |
817 | 0x1427f116, | 817 | 0xf5065721, |
818 | 0x0624b604, | 818 | 0xf5066621, |
819 | 0xf10020d0, | 819 | 0xbd067821, |
820 | 0xf0a500e7, | 820 | 0x5721f5f4, |
821 | 0x1fb941e3, | 821 | 0xb821f506, |
822 | 0x8d21f402, | 822 | /* 0x086d: ctx_xfer_exec */ |
823 | 0xf004e0b6, | 823 | 0x16019806, |
824 | 0x2cf001fc, | 824 | 0x041427f1, |
825 | 0x0124b602, | 825 | 0xd00624b6, |
826 | 0xf405f2fd, | 826 | 0xe7f10020, |
827 | 0x17f18d21, | 827 | 0xe3f0a500, |
828 | 0x13f04afc, | 828 | 0x021fb941, |
829 | 0x0c27f002, | 829 | 0xb68d21f4, |
830 | 0xf50012d0, | 830 | 0xfcf004e0, |
831 | 0xf1020721, | 831 | 0x022cf001, |
832 | 0xf047fc27, | 832 | 0xfd0124b6, |
833 | 0x20d00223, | 833 | 0x21f405f2, |
834 | 0x012cf000, | 834 | 0xfc17f18d, |
835 | 0xd00320b6, | 835 | 0x0213f04a, |
836 | 0xacf00012, | 836 | 0xd00c27f0, |
837 | 0x06a5f001, | 837 | 0x21f50012, |
838 | 0x9800b7f0, | 838 | 0x27f10207, |
839 | 0x0d98140c, | 839 | 0x23f047fc, |
840 | 0x00e7f015, | 840 | 0x0020d002, |
841 | 0x015c21f5, | 841 | 0xb6012cf0, |
842 | 0xf508a7f0, | 842 | 0x12d00320, |
843 | 0xf5010321, | 843 | 0x01acf000, |
844 | 0xf4020721, | 844 | 0xf006a5f0, |
845 | 0xa7f02201, | 845 | 0x0c9800b7, |
846 | 0xc921f40c, | 846 | 0x150d9814, |
847 | 0x0a1017f1, | 847 | 0xf500e7f0, |
848 | 0xf00614b6, | 848 | 0xf0015c21, |
849 | 0x12d00527, | 849 | 0x21f508a7, |
850 | /* 0x08dd: ctx_xfer_post_save_wait */ | 850 | 0x21f50103, |
851 | 0x0012cf00, | 851 | 0x01f40207, |
852 | 0xf40522fd, | 852 | 0x0ca7f022, |
853 | 0x02f4fa1b, | 853 | 0xf1c921f4, |
854 | /* 0x08e9: ctx_xfer_post */ | 854 | 0xb60a1017, |
855 | 0x02f7f032, | 855 | 0x27f00614, |
856 | 0x065721f5, | 856 | 0x0012d005, |
857 | 0x21f5f4bd, | 857 | /* 0x08f4: ctx_xfer_post_save_wait */ |
858 | 0x21f50698, | 858 | 0xfd0012cf, |
859 | 0x21f50226, | 859 | 0x1bf40522, |
860 | 0xf4bd0666, | 860 | 0x3202f4fa, |
861 | 0x065721f5, | 861 | /* 0x0900: ctx_xfer_post */ |
862 | 0x981011f4, | 862 | 0xf502f7f0, |
863 | 0x11fd8001, | 863 | 0xbd065721, |
864 | 0x070bf405, | 864 | 0x9821f5f4, |
865 | 0x07df21f5, | 865 | 0x2621f506, |
866 | /* 0x0914: ctx_xfer_no_post_mmio */ | 866 | 0x6621f502, |
867 | 0x064921f5, | 867 | 0xf5f4bd06, |
868 | /* 0x0918: ctx_xfer_done */ | 868 | 0xf4065721, |
869 | 0x000000f8, | 869 | 0x01981011, |
870 | 0x00000000, | 870 | 0x0511fd80, |
871 | 0x00000000, | 871 | 0xf5070bf4, |
872 | 0x00000000, | 872 | /* 0x092b: ctx_xfer_no_post_mmio */ |
873 | 0x00000000, | 873 | 0xf507df21, |
874 | 0x00000000, | 874 | /* 0x092f: ctx_xfer_done */ |
875 | 0xf8064921, | ||
875 | 0x00000000, | 876 | 0x00000000, |
876 | 0x00000000, | 877 | 0x00000000, |
877 | 0x00000000, | 878 | 0x00000000, |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc index 138eeaa28665..7fe9d7cf486b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc | |||
@@ -44,6 +44,9 @@ chipsets: | |||
44 | .b8 0xe7 0 0 0 | 44 | .b8 0xe7 0 0 0 |
45 | .b16 #nve4_hub_mmio_head | 45 | .b16 #nve4_hub_mmio_head |
46 | .b16 #nve4_hub_mmio_tail | 46 | .b16 #nve4_hub_mmio_tail |
47 | .b8 0xe6 0 0 0 | ||
48 | .b16 #nve4_hub_mmio_head | ||
49 | .b16 #nve4_hub_mmio_tail | ||
47 | .b8 0 0 0 0 | 50 | .b8 0 0 0 0 |
48 | 51 | ||
49 | nve4_hub_mmio_head: | 52 | nve4_hub_mmio_head: |
@@ -680,6 +683,16 @@ ctx_mmio_exec: | |||
680 | // on load it means: "a save preceeded this load" | 683 | // on load it means: "a save preceeded this load" |
681 | // | 684 | // |
682 | ctx_xfer: | 685 | ctx_xfer: |
686 | // according to mwk, some kind of wait for idle | ||
687 | mov $r15 0xc00 | ||
688 | shl b32 $r15 6 | ||
689 | mov $r14 4 | ||
690 | iowr I[$r15 + 0x200] $r14 | ||
691 | ctx_xfer_idle: | ||
692 | iord $r14 I[$r15 + 0x000] | ||
693 | and $r14 0x2000 | ||
694 | bra ne #ctx_xfer_idle | ||
695 | |||
683 | bra not $p1 #ctx_xfer_pre | 696 | bra not $p1 #ctx_xfer_pre |
684 | bra $p2 #ctx_xfer_pre_load | 697 | bra $p2 #ctx_xfer_pre_load |
685 | ctx_xfer_pre: | 698 | ctx_xfer_pre: |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h index decf0c60ca3b..e3421af68ab9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h | |||
@@ -30,11 +30,13 @@ uint32_t nve0_grhub_data[] = { | |||
30 | 0x00000000, | 30 | 0x00000000, |
31 | /* 0x005c: chipsets */ | 31 | /* 0x005c: chipsets */ |
32 | 0x000000e4, | 32 | 0x000000e4, |
33 | 0x013c0070, | 33 | 0x01440078, |
34 | 0x000000e7, | 34 | 0x000000e7, |
35 | 0x013c0070, | 35 | 0x01440078, |
36 | 0x000000e6, | ||
37 | 0x01440078, | ||
36 | 0x00000000, | 38 | 0x00000000, |
37 | /* 0x0070: nve4_hub_mmio_head */ | 39 | /* 0x0078: nve4_hub_mmio_head */ |
38 | 0x0417e91c, | 40 | 0x0417e91c, |
39 | 0x04400204, | 41 | 0x04400204, |
40 | 0x18404010, | 42 | 0x18404010, |
@@ -86,9 +88,7 @@ uint32_t nve0_grhub_data[] = { | |||
86 | 0x00408840, | 88 | 0x00408840, |
87 | 0x08408900, | 89 | 0x08408900, |
88 | 0x00408980, | 90 | 0x00408980, |
89 | /* 0x013c: nve4_hub_mmio_tail */ | 91 | /* 0x0144: nve4_hub_mmio_tail */ |
90 | 0x00000000, | ||
91 | 0x00000000, | ||
92 | 0x00000000, | 92 | 0x00000000, |
93 | 0x00000000, | 93 | 0x00000000, |
94 | 0x00000000, | 94 | 0x00000000, |
@@ -781,77 +781,78 @@ uint32_t nve0_grhub_code[] = { | |||
781 | 0x0613f002, | 781 | 0x0613f002, |
782 | 0xf80601fa, | 782 | 0xf80601fa, |
783 | /* 0x07fb: ctx_xfer */ | 783 | /* 0x07fb: ctx_xfer */ |
784 | 0xf400f803, | 784 | 0xf100f803, |
785 | 0x02f40611, | 785 | 0xb60c00f7, |
786 | /* 0x0801: ctx_xfer_pre */ | 786 | 0xe7f006f4, |
787 | 0x10f7f00d, | 787 | 0x80fed004, |
788 | 0x067221f5, | 788 | /* 0x0808: ctx_xfer_idle */ |
789 | /* 0x080b: ctx_xfer_pre_load */ | 789 | 0xf100fecf, |
790 | 0xf01c11f4, | 790 | 0xf42000e4, |
791 | 0x21f502f7, | 791 | 0x11f4f91b, |
792 | 0x21f50631, | 792 | 0x0d02f406, |
793 | 0x21f50640, | 793 | /* 0x0818: ctx_xfer_pre */ |
794 | 0xf4bd0652, | 794 | 0xf510f7f0, |
795 | 0x063121f5, | 795 | 0xf4067221, |
796 | 0x069221f5, | 796 | /* 0x0822: ctx_xfer_pre_load */ |
797 | /* 0x0824: ctx_xfer_exec */ | 797 | 0xf7f01c11, |
798 | 0xf1160198, | 798 | 0x3121f502, |
799 | 0xb6041427, | 799 | 0x4021f506, |
800 | 0x20d00624, | 800 | 0x5221f506, |
801 | 0x00e7f100, | 801 | 0xf5f4bd06, |
802 | 0x41e3f0a5, | 802 | 0xf5063121, |
803 | 0xf4021fb9, | 803 | /* 0x083b: ctx_xfer_exec */ |
804 | 0xe0b68d21, | 804 | 0x98069221, |
805 | 0x01fcf004, | 805 | 0x27f11601, |
806 | 0xb6022cf0, | 806 | 0x24b60414, |
807 | 0xf2fd0124, | 807 | 0x0020d006, |
808 | 0x8d21f405, | 808 | 0xa500e7f1, |
809 | 0x4afc17f1, | 809 | 0xb941e3f0, |
810 | 0xf00213f0, | 810 | 0x21f4021f, |
811 | 0x12d00c27, | 811 | 0x04e0b68d, |
812 | 0x0721f500, | 812 | 0xf001fcf0, |
813 | 0xfc27f102, | 813 | 0x24b6022c, |
814 | 0x0223f047, | 814 | 0x05f2fd01, |
815 | 0xf00020d0, | 815 | 0xf18d21f4, |
816 | 0x20b6012c, | 816 | 0xf04afc17, |
817 | 0x0012d003, | 817 | 0x27f00213, |
818 | 0xf001acf0, | 818 | 0x0012d00c, |
819 | 0xb7f006a5, | 819 | 0x020721f5, |
820 | 0x140c9800, | 820 | 0x47fc27f1, |
821 | 0xf0150d98, | 821 | 0xd00223f0, |
822 | 0x21f500e7, | 822 | 0x2cf00020, |
823 | 0xa7f0015c, | 823 | 0x0320b601, |
824 | 0x0321f508, | 824 | 0xf00012d0, |
825 | 0x0721f501, | 825 | 0xa5f001ac, |
826 | 0x2201f402, | 826 | 0x00b7f006, |
827 | 0xf40ca7f0, | 827 | 0x98140c98, |
828 | 0x17f1c921, | 828 | 0xe7f0150d, |
829 | 0x14b60a10, | 829 | 0x5c21f500, |
830 | 0x0527f006, | 830 | 0x08a7f001, |
831 | /* 0x08ab: ctx_xfer_post_save_wait */ | 831 | 0x010321f5, |
832 | 0xcf0012d0, | 832 | 0x020721f5, |
833 | 0x22fd0012, | 833 | 0xf02201f4, |
834 | 0xfa1bf405, | 834 | 0x21f40ca7, |
835 | /* 0x08b7: ctx_xfer_post */ | 835 | 0x1017f1c9, |
836 | 0xf02e02f4, | 836 | 0x0614b60a, |
837 | 0x21f502f7, | 837 | 0xd00527f0, |
838 | 0xf4bd0631, | 838 | /* 0x08c2: ctx_xfer_post_save_wait */ |
839 | 0x067221f5, | 839 | 0x12cf0012, |
840 | 0x022621f5, | 840 | 0x0522fd00, |
841 | 0x064021f5, | 841 | 0xf4fa1bf4, |
842 | 0x21f5f4bd, | 842 | /* 0x08ce: ctx_xfer_post */ |
843 | 0x11f40631, | 843 | 0xf7f02e02, |
844 | 0x80019810, | 844 | 0x3121f502, |
845 | 0xf40511fd, | 845 | 0xf5f4bd06, |
846 | 0x21f5070b, | 846 | 0xf5067221, |
847 | /* 0x08e2: ctx_xfer_no_post_mmio */ | 847 | 0xf5022621, |
848 | /* 0x08e2: ctx_xfer_done */ | 848 | 0xbd064021, |
849 | 0x00f807b1, | 849 | 0x3121f5f4, |
850 | 0x00000000, | 850 | 0x1011f406, |
851 | 0x00000000, | 851 | 0xfd800198, |
852 | 0x00000000, | 852 | 0x0bf40511, |
853 | 0x00000000, | 853 | 0xb121f507, |
854 | 0x00000000, | 854 | /* 0x08f9: ctx_xfer_no_post_mmio */ |
855 | 0x00000000, | 855 | /* 0x08f9: ctx_xfer_done */ |
856 | 0x0000f807, | ||
856 | 0x00000000, | 857 | 0x00000000, |
857 | }; | 858 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 47a02081d708..45aff5f5085a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | |||
@@ -516,18 +516,9 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
516 | { | 516 | { |
517 | struct nouveau_device *device = nv_device(parent); | 517 | struct nouveau_device *device = nv_device(parent); |
518 | struct nvc0_graph_priv *priv; | 518 | struct nvc0_graph_priv *priv; |
519 | bool enable = true; | ||
520 | int ret, i; | 519 | int ret, i; |
521 | 520 | ||
522 | switch (device->chipset) { | 521 | ret = nouveau_graph_create(parent, engine, oclass, true, &priv); |
523 | case 0xd9: /* known broken without binary driver firmware */ | ||
524 | enable = false; | ||
525 | break; | ||
526 | default: | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | ret = nouveau_graph_create(parent, engine, oclass, enable, &priv); | ||
531 | *pobject = nv_object(priv); | 522 | *pobject = nv_object(priv); |
532 | if (ret) | 523 | if (ret) |
533 | return ret; | 524 | return ret; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index 18d2210e12eb..a1e78de46456 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | |||
@@ -121,6 +121,7 @@ nvc0_graph_class(void *obj) | |||
121 | return 0x9297; | 121 | return 0x9297; |
122 | case 0xe4: | 122 | case 0xe4: |
123 | case 0xe7: | 123 | case 0xe7: |
124 | case 0xe6: | ||
124 | return 0xa097; | 125 | return 0xa097; |
125 | default: | 126 | default: |
126 | return 0; | 127 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 539d4c72f192..9f82e9702b46 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | |||
@@ -203,7 +203,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
203 | struct nvc0_graph_priv *priv; | 203 | struct nvc0_graph_priv *priv; |
204 | int ret, i; | 204 | int ret, i; |
205 | 205 | ||
206 | ret = nouveau_graph_create(parent, engine, oclass, false, &priv); | 206 | ret = nouveau_graph_create(parent, engine, oclass, true, &priv); |
207 | *pobject = nv_object(priv); | 207 | *pobject = nv_object(priv); |
208 | if (ret) | 208 | if (ret) |
209 | return ret; | 209 | return ret; |
@@ -252,6 +252,7 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
252 | priv->magic_not_rop_nr = 1; | 252 | priv->magic_not_rop_nr = 1; |
253 | break; | 253 | break; |
254 | case 0xe7: | 254 | case 0xe7: |
255 | case 0xe6: | ||
255 | priv->magic_not_rop_nr = 1; | 256 | priv->magic_not_rop_nr = 1; |
256 | break; | 257 | break; |
257 | default: | 258 | default: |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h index 0193532ceac9..63acc0346ff2 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h | |||
@@ -36,6 +36,9 @@ nouveau_client(void *obj) | |||
36 | 36 | ||
37 | int nouveau_client_create_(const char *name, u64 device, const char *cfg, | 37 | int nouveau_client_create_(const char *name, u64 device, const char *cfg, |
38 | const char *dbg, int, void **); | 38 | const char *dbg, int, void **); |
39 | #define nouveau_client_destroy(p) \ | ||
40 | nouveau_namedb_destroy(&(p)->base) | ||
41 | |||
39 | int nouveau_client_init(struct nouveau_client *); | 42 | int nouveau_client_init(struct nouveau_client *); |
40 | int nouveau_client_fini(struct nouveau_client *, bool suspend); | 43 | int nouveau_client_fini(struct nouveau_client *, bool suspend); |
41 | 44 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h index d145b25e6be4..5bd1ca8cd20d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios.h | |||
@@ -17,6 +17,7 @@ struct nouveau_bios { | |||
17 | u8 chip; | 17 | u8 chip; |
18 | u8 minor; | 18 | u8 minor; |
19 | u8 micro; | 19 | u8 micro; |
20 | u8 patch; | ||
20 | } version; | 21 | } version; |
21 | }; | 22 | }; |
22 | 23 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index 2bf178082a36..e6563b5cb08e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h | |||
@@ -25,9 +25,11 @@ struct dcb_gpio_func { | |||
25 | u8 param; | 25 | u8 param; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | u16 dcb_gpio_table(struct nouveau_bios *); | 28 | u16 dcb_gpio_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); |
29 | u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver); | 29 | u16 dcb_gpio_entry(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len); |
30 | int dcb_gpio_parse(struct nouveau_bios *, int idx, u8 func, u8 line, | 30 | u16 dcb_gpio_parse(struct nouveau_bios *, int idx, int ent, u8 *ver, u8 *len, |
31 | struct dcb_gpio_func *); | 31 | struct dcb_gpio_func *); |
32 | u16 dcb_gpio_match(struct nouveau_bios *, int idx, u8 func, u8 line, | ||
33 | u8 *ver, u8 *len, struct dcb_gpio_func *); | ||
32 | 34 | ||
33 | #endif | 35 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h index e69a8bdc6e97..ca2f6bf37f46 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/init.h | |||
@@ -13,6 +13,7 @@ struct nvbios_init { | |||
13 | u32 nested; | 13 | u32 nested; |
14 | u16 repeat; | 14 | u16 repeat; |
15 | u16 repend; | 15 | u16 repend; |
16 | u32 ramcfg; | ||
16 | }; | 17 | }; |
17 | 18 | ||
18 | int nvbios_exec(struct nvbios_init *); | 19 | int nvbios_exec(struct nvbios_init *); |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h index c345097592f2..b2f3d4d0aa49 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | |||
@@ -38,6 +38,8 @@ enum nvbios_pll_type { | |||
38 | PLL_UNK42 = 0x42, | 38 | PLL_UNK42 = 0x42, |
39 | PLL_VPLL0 = 0x80, | 39 | PLL_VPLL0 = 0x80, |
40 | PLL_VPLL1 = 0x81, | 40 | PLL_VPLL1 = 0x81, |
41 | PLL_VPLL2 = 0x82, | ||
42 | PLL_VPLL3 = 0x83, | ||
41 | PLL_MAX = 0xff | 43 | PLL_MAX = 0xff |
42 | }; | 44 | }; |
43 | 45 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index 9ea2b12cc15d..b75e8f18e52c 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h | |||
@@ -11,7 +11,7 @@ struct nouveau_gpio { | |||
11 | struct nouveau_subdev base; | 11 | struct nouveau_subdev base; |
12 | 12 | ||
13 | /* hardware interfaces */ | 13 | /* hardware interfaces */ |
14 | void (*reset)(struct nouveau_gpio *); | 14 | void (*reset)(struct nouveau_gpio *, u8 func); |
15 | int (*drive)(struct nouveau_gpio *, int line, int dir, int out); | 15 | int (*drive)(struct nouveau_gpio *, int line, int dir, int out); |
16 | int (*sense)(struct nouveau_gpio *, int line); | 16 | int (*sense)(struct nouveau_gpio *, int line); |
17 | void (*irq_enable)(struct nouveau_gpio *, int line, bool); | 17 | void (*irq_enable)(struct nouveau_gpio *, int line, bool); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index dd111947eb86..f621f69fa1a2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c | |||
@@ -447,6 +447,7 @@ nouveau_bios_ctor(struct nouveau_object *parent, | |||
447 | bios->version.chip = nv_ro08(bios, bit_i.offset + 2); | 447 | bios->version.chip = nv_ro08(bios, bit_i.offset + 2); |
448 | bios->version.minor = nv_ro08(bios, bit_i.offset + 1); | 448 | bios->version.minor = nv_ro08(bios, bit_i.offset + 1); |
449 | bios->version.micro = nv_ro08(bios, bit_i.offset + 0); | 449 | bios->version.micro = nv_ro08(bios, bit_i.offset + 0); |
450 | bios->version.patch = nv_ro08(bios, bit_i.offset + 4); | ||
450 | } else | 451 | } else |
451 | if (bmp_version(bios)) { | 452 | if (bmp_version(bios)) { |
452 | bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); | 453 | bios->version.major = nv_ro08(bios, bios->bmp_offset + 13); |
@@ -455,9 +456,9 @@ nouveau_bios_ctor(struct nouveau_object *parent, | |||
455 | bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); | 456 | bios->version.micro = nv_ro08(bios, bios->bmp_offset + 10); |
456 | } | 457 | } |
457 | 458 | ||
458 | nv_info(bios, "version %02x.%02x.%02x.%02x\n", | 459 | nv_info(bios, "version %02x.%02x.%02x.%02x.%02x\n", |
459 | bios->version.major, bios->version.chip, | 460 | bios->version.major, bios->version.chip, |
460 | bios->version.minor, bios->version.micro); | 461 | bios->version.minor, bios->version.micro, bios->version.patch); |
461 | 462 | ||
462 | return 0; | 463 | return 0; |
463 | } | 464 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index c90d4aa3ae4f..c84e93fa6d95 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c | |||
@@ -27,84 +27,105 @@ | |||
27 | #include <subdev/bios/gpio.h> | 27 | #include <subdev/bios/gpio.h> |
28 | 28 | ||
29 | u16 | 29 | u16 |
30 | dcb_gpio_table(struct nouveau_bios *bios) | 30 | dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) |
31 | { | 31 | { |
32 | u8 ver, hdr, cnt, len; | 32 | u16 data = 0x0000; |
33 | u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len); | 33 | u16 dcb = dcb_table(bios, ver, hdr, cnt, len); |
34 | if (dcb) { | 34 | if (dcb) { |
35 | if (ver >= 0x30 && hdr >= 0x0c) | 35 | if (*ver >= 0x30 && *hdr >= 0x0c) |
36 | return nv_ro16(bios, dcb + 0x0a); | 36 | data = nv_ro16(bios, dcb + 0x0a); |
37 | if (ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) | 37 | else |
38 | return nv_ro16(bios, dcb - 0x0f); | 38 | if (*ver >= 0x22 && nv_ro08(bios, dcb - 1) >= 0x13) |
39 | data = nv_ro16(bios, dcb - 0x0f); | ||
40 | |||
41 | if (data) { | ||
42 | *ver = nv_ro08(bios, data + 0x00); | ||
43 | if (*ver < 0x30) { | ||
44 | *hdr = 3; | ||
45 | *cnt = nv_ro08(bios, data + 0x02); | ||
46 | *len = nv_ro08(bios, data + 0x01); | ||
47 | } else | ||
48 | if (*ver <= 0x41) { | ||
49 | *hdr = nv_ro08(bios, data + 0x01); | ||
50 | *cnt = nv_ro08(bios, data + 0x02); | ||
51 | *len = nv_ro08(bios, data + 0x03); | ||
52 | } else { | ||
53 | data = 0x0000; | ||
54 | } | ||
55 | } | ||
39 | } | 56 | } |
40 | return 0x0000; | 57 | return data; |
41 | } | 58 | } |
42 | 59 | ||
43 | u16 | 60 | u16 |
44 | dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver) | 61 | dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len) |
45 | { | 62 | { |
46 | u16 gpio = dcb_gpio_table(bios); | 63 | u8 hdr, cnt; |
47 | if (gpio) { | 64 | u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000; |
48 | *ver = nv_ro08(bios, gpio); | 65 | if (gpio && ent < cnt) |
49 | if (*ver < 0x30 && ent < nv_ro08(bios, gpio + 2)) | 66 | return gpio + hdr + (ent * *len); |
50 | return gpio + 3 + (ent * nv_ro08(bios, gpio + 1)); | ||
51 | else if (ent < nv_ro08(bios, gpio + 2)) | ||
52 | return gpio + nv_ro08(bios, gpio + 1) + | ||
53 | (ent * nv_ro08(bios, gpio + 3)); | ||
54 | } | ||
55 | return 0x0000; | 67 | return 0x0000; |
56 | } | 68 | } |
57 | 69 | ||
58 | int | 70 | u16 |
59 | dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, | 71 | dcb_gpio_parse(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len, |
60 | struct dcb_gpio_func *gpio) | 72 | struct dcb_gpio_func *gpio) |
61 | { | 73 | { |
62 | u8 ver, hdr, cnt, len; | 74 | u16 data = dcb_gpio_entry(bios, idx, ent, ver, len); |
63 | u16 entry; | 75 | if (data) { |
64 | int i = -1; | 76 | if (*ver < 0x40) { |
65 | 77 | u16 info = nv_ro16(bios, data); | |
66 | while ((entry = dcb_gpio_entry(bios, idx, ++i, &ver))) { | ||
67 | if (ver < 0x40) { | ||
68 | u16 data = nv_ro16(bios, entry); | ||
69 | *gpio = (struct dcb_gpio_func) { | 78 | *gpio = (struct dcb_gpio_func) { |
70 | .line = (data & 0x001f) >> 0, | 79 | .line = (info & 0x001f) >> 0, |
71 | .func = (data & 0x07e0) >> 5, | 80 | .func = (info & 0x07e0) >> 5, |
72 | .log[0] = (data & 0x1800) >> 11, | 81 | .log[0] = (info & 0x1800) >> 11, |
73 | .log[1] = (data & 0x6000) >> 13, | 82 | .log[1] = (info & 0x6000) >> 13, |
74 | .param = !!(data & 0x8000), | 83 | .param = !!(info & 0x8000), |
75 | }; | 84 | }; |
76 | } else | 85 | } else |
77 | if (ver < 0x41) { | 86 | if (*ver < 0x41) { |
78 | u32 data = nv_ro32(bios, entry); | 87 | u32 info = nv_ro32(bios, data); |
79 | *gpio = (struct dcb_gpio_func) { | 88 | *gpio = (struct dcb_gpio_func) { |
80 | .line = (data & 0x0000001f) >> 0, | 89 | .line = (info & 0x0000001f) >> 0, |
81 | .func = (data & 0x0000ff00) >> 8, | 90 | .func = (info & 0x0000ff00) >> 8, |
82 | .log[0] = (data & 0x18000000) >> 27, | 91 | .log[0] = (info & 0x18000000) >> 27, |
83 | .log[1] = (data & 0x60000000) >> 29, | 92 | .log[1] = (info & 0x60000000) >> 29, |
84 | .param = !!(data & 0x80000000), | 93 | .param = !!(info & 0x80000000), |
85 | }; | 94 | }; |
86 | } else { | 95 | } else { |
87 | u32 data = nv_ro32(bios, entry + 0); | 96 | u32 info = nv_ro32(bios, data + 0); |
88 | u8 data1 = nv_ro32(bios, entry + 4); | 97 | u8 info1 = nv_ro32(bios, data + 4); |
89 | *gpio = (struct dcb_gpio_func) { | 98 | *gpio = (struct dcb_gpio_func) { |
90 | .line = (data & 0x0000003f) >> 0, | 99 | .line = (info & 0x0000003f) >> 0, |
91 | .func = (data & 0x0000ff00) >> 8, | 100 | .func = (info & 0x0000ff00) >> 8, |
92 | .log[0] = (data1 & 0x30) >> 4, | 101 | .log[0] = (info1 & 0x30) >> 4, |
93 | .log[1] = (data1 & 0xc0) >> 6, | 102 | .log[1] = (info1 & 0xc0) >> 6, |
94 | .param = !!(data & 0x80000000), | 103 | .param = !!(info & 0x80000000), |
95 | }; | 104 | }; |
96 | } | 105 | } |
106 | } | ||
107 | |||
108 | return data; | ||
109 | } | ||
97 | 110 | ||
111 | u16 | ||
112 | dcb_gpio_match(struct nouveau_bios *bios, int idx, u8 func, u8 line, | ||
113 | u8 *ver, u8 *len, struct dcb_gpio_func *gpio) | ||
114 | { | ||
115 | u8 hdr, cnt, i = 0; | ||
116 | u16 data; | ||
117 | |||
118 | while ((data = dcb_gpio_parse(bios, idx, i++, ver, len, gpio))) { | ||
98 | if ((line == 0xff || line == gpio->line) && | 119 | if ((line == 0xff || line == gpio->line) && |
99 | (func == 0xff || func == gpio->func)) | 120 | (func == 0xff || func == gpio->func)) |
100 | return 0; | 121 | return data; |
101 | } | 122 | } |
102 | 123 | ||
103 | /* DCB 2.2, fixed TVDAC GPIO data */ | 124 | /* DCB 2.2, fixed TVDAC GPIO data */ |
104 | if ((entry = dcb_table(bios, &ver, &hdr, &cnt, &len))) { | 125 | if ((data = dcb_table(bios, ver, &hdr, &cnt, len))) { |
105 | if (ver >= 0x22 && ver < 0x30 && func == DCB_GPIO_TVDAC0) { | 126 | if (*ver >= 0x22 && *ver < 0x30 && func == DCB_GPIO_TVDAC0) { |
106 | u8 conf = nv_ro08(bios, entry - 5); | 127 | u8 conf = nv_ro08(bios, data - 5); |
107 | u8 addr = nv_ro08(bios, entry - 4); | 128 | u8 addr = nv_ro08(bios, data - 4); |
108 | if (conf & 0x01) { | 129 | if (conf & 0x01) { |
109 | *gpio = (struct dcb_gpio_func) { | 130 | *gpio = (struct dcb_gpio_func) { |
110 | .func = DCB_GPIO_TVDAC0, | 131 | .func = DCB_GPIO_TVDAC0, |
@@ -112,10 +133,11 @@ dcb_gpio_parse(struct nouveau_bios *bios, int idx, u8 func, u8 line, | |||
112 | .log[0] = !!(conf & 0x02), | 133 | .log[0] = !!(conf & 0x02), |
113 | .log[1] = !(conf & 0x02), | 134 | .log[1] = !(conf & 0x02), |
114 | }; | 135 | }; |
115 | return 0; | 136 | *ver = 0x00; |
137 | return data; | ||
116 | } | 138 | } |
117 | } | 139 | } |
118 | } | 140 | } |
119 | 141 | ||
120 | return -EINVAL; | 142 | return 0x0000; |
121 | } | 143 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index ae168bbb86d8..690ed438b2ad 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c | |||
@@ -2,11 +2,12 @@ | |||
2 | #include <core/device.h> | 2 | #include <core/device.h> |
3 | 3 | ||
4 | #include <subdev/bios.h> | 4 | #include <subdev/bios.h> |
5 | #include <subdev/bios/conn.h> | ||
6 | #include <subdev/bios/bmp.h> | 5 | #include <subdev/bios/bmp.h> |
7 | #include <subdev/bios/bit.h> | 6 | #include <subdev/bios/bit.h> |
7 | #include <subdev/bios/conn.h> | ||
8 | #include <subdev/bios/dcb.h> | 8 | #include <subdev/bios/dcb.h> |
9 | #include <subdev/bios/dp.h> | 9 | #include <subdev/bios/dp.h> |
10 | #include <subdev/bios/gpio.h> | ||
10 | #include <subdev/bios/init.h> | 11 | #include <subdev/bios/init.h> |
11 | #include <subdev/devinit.h> | 12 | #include <subdev/devinit.h> |
12 | #include <subdev/clock.h> | 13 | #include <subdev/clock.h> |
@@ -410,9 +411,25 @@ init_ram_restrict_group_count(struct nvbios_init *init) | |||
410 | } | 411 | } |
411 | 412 | ||
412 | static u8 | 413 | static u8 |
414 | init_ram_restrict_strap(struct nvbios_init *init) | ||
415 | { | ||
416 | /* This appears to be the behaviour of the VBIOS parser, and *is* | ||
417 | * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to | ||
418 | * avoid fucking up the memory controller (somehow) by reading it | ||
419 | * on every INIT_RAM_RESTRICT_ZM_GROUP opcode. | ||
420 | * | ||
421 | * Preserving the non-caching behaviour on earlier chipsets just | ||
422 | * in case *not* re-reading the strap causes similar breakage. | ||
423 | */ | ||
424 | if (!init->ramcfg || init->bios->version.major < 0x70) | ||
425 | init->ramcfg = init_rd32(init, 0x101000); | ||
426 | return (init->ramcfg & 0x00000003c) >> 2; | ||
427 | } | ||
428 | |||
429 | static u8 | ||
413 | init_ram_restrict(struct nvbios_init *init) | 430 | init_ram_restrict(struct nvbios_init *init) |
414 | { | 431 | { |
415 | u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2; | 432 | u8 strap = init_ram_restrict_strap(init); |
416 | u16 table = init_ram_restrict_table(init); | 433 | u16 table = init_ram_restrict_table(init); |
417 | if (table) | 434 | if (table) |
418 | return nv_ro08(init->bios, table + strap); | 435 | return nv_ro08(init->bios, table + strap); |
@@ -1517,7 +1534,6 @@ init_io(struct nvbios_init *init) | |||
1517 | mdelay(10); | 1534 | mdelay(10); |
1518 | init_wr32(init, 0x614100, 0x10000018); | 1535 | init_wr32(init, 0x614100, 0x10000018); |
1519 | init_wr32(init, 0x614900, 0x10000018); | 1536 | init_wr32(init, 0x614900, 0x10000018); |
1520 | return; | ||
1521 | } | 1537 | } |
1522 | 1538 | ||
1523 | value = init_rdport(init, port) & mask; | 1539 | value = init_rdport(init, port) & mask; |
@@ -1781,7 +1797,7 @@ init_gpio(struct nvbios_init *init) | |||
1781 | init->offset += 1; | 1797 | init->offset += 1; |
1782 | 1798 | ||
1783 | if (init_exec(init) && gpio && gpio->reset) | 1799 | if (init_exec(init) && gpio && gpio->reset) |
1784 | gpio->reset(gpio); | 1800 | gpio->reset(gpio, DCB_GPIO_UNUSED); |
1785 | } | 1801 | } |
1786 | 1802 | ||
1787 | /** | 1803 | /** |
@@ -1995,6 +2011,47 @@ init_i2c_long_if(struct nvbios_init *init) | |||
1995 | init_exec_set(init, false); | 2011 | init_exec_set(init, false); |
1996 | } | 2012 | } |
1997 | 2013 | ||
2014 | /** | ||
2015 | * INIT_GPIO_NE - opcode 0xa9 | ||
2016 | * | ||
2017 | */ | ||
2018 | static void | ||
2019 | init_gpio_ne(struct nvbios_init *init) | ||
2020 | { | ||
2021 | struct nouveau_bios *bios = init->bios; | ||
2022 | struct nouveau_gpio *gpio = nouveau_gpio(bios); | ||
2023 | struct dcb_gpio_func func; | ||
2024 | u8 count = nv_ro08(bios, init->offset + 1); | ||
2025 | u8 idx = 0, ver, len; | ||
2026 | u16 data, i; | ||
2027 | |||
2028 | trace("GPIO_NE\t"); | ||
2029 | init->offset += 2; | ||
2030 | |||
2031 | for (i = init->offset; i < init->offset + count; i++) | ||
2032 | cont("0x%02x ", nv_ro08(bios, i)); | ||
2033 | cont("\n"); | ||
2034 | |||
2035 | while ((data = dcb_gpio_parse(bios, 0, idx++, &ver, &len, &func))) { | ||
2036 | if (func.func != DCB_GPIO_UNUSED) { | ||
2037 | for (i = init->offset; i < init->offset + count; i++) { | ||
2038 | if (func.func == nv_ro08(bios, i)) | ||
2039 | break; | ||
2040 | } | ||
2041 | |||
2042 | trace("\tFUNC[0x%02x]", func.func); | ||
2043 | if (i == (init->offset + count)) { | ||
2044 | cont(" *"); | ||
2045 | if (init_exec(init) && gpio && gpio->reset) | ||
2046 | gpio->reset(gpio, func.func); | ||
2047 | } | ||
2048 | cont("\n"); | ||
2049 | } | ||
2050 | } | ||
2051 | |||
2052 | init->offset += count; | ||
2053 | } | ||
2054 | |||
1998 | static struct nvbios_init_opcode { | 2055 | static struct nvbios_init_opcode { |
1999 | void (*exec)(struct nvbios_init *); | 2056 | void (*exec)(struct nvbios_init *); |
2000 | } init_opcode[] = { | 2057 | } init_opcode[] = { |
@@ -2059,6 +2116,7 @@ static struct nvbios_init_opcode { | |||
2059 | [0x98] = { init_auxch }, | 2116 | [0x98] = { init_auxch }, |
2060 | [0x99] = { init_zm_auxch }, | 2117 | [0x99] = { init_zm_auxch }, |
2061 | [0x9a] = { init_i2c_long_if }, | 2118 | [0x9a] = { init_i2c_long_if }, |
2119 | [0xa9] = { init_gpio_ne }, | ||
2062 | }; | 2120 | }; |
2063 | 2121 | ||
2064 | #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) | 2122 | #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index f6962c9b6c36..7c9626258a46 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | |||
@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | |||
52 | switch (info.type) { | 52 | switch (info.type) { |
53 | case PLL_VPLL0: | 53 | case PLL_VPLL0: |
54 | case PLL_VPLL1: | 54 | case PLL_VPLL1: |
55 | case PLL_VPLL2: | ||
56 | case PLL_VPLL3: | ||
55 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); | 57 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); |
56 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); | 58 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); |
57 | nv_wr32(priv, info.reg + 0x10, fN << 16); | 59 | nv_wr32(priv, info.reg + 0x10, fN << 16); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 9b7881e76634..03a652876e73 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c | |||
@@ -109,6 +109,34 @@ nve0_identify(struct nouveau_device *device) | |||
109 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; | 109 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; |
110 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; | 110 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; |
111 | break; | 111 | break; |
112 | case 0xe6: | ||
113 | device->cname = "GK106"; | ||
114 | device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; | ||
115 | device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; | ||
116 | device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; | ||
117 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; | ||
118 | device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; | ||
119 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | ||
120 | device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; | ||
121 | device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; | ||
122 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | ||
123 | device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; | ||
124 | device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; | ||
125 | device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; | ||
126 | device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; | ||
127 | device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; | ||
128 | device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; | ||
129 | device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; | ||
130 | device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass; | ||
131 | device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass; | ||
132 | device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass; | ||
133 | device->oclass[NVDEV_ENGINE_DISP ] = &nve0_disp_oclass; | ||
134 | device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; | ||
135 | device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; | ||
136 | device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass; | ||
137 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; | ||
138 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; | ||
139 | break; | ||
112 | default: | 140 | default: |
113 | nv_fatal(device, "unknown Kepler chipset\n"); | 141 | nv_fatal(device, "unknown Kepler chipset\n"); |
114 | return -EINVAL; | 142 | return -EINVAL; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 306bdf121452..7606ed15b6fa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | |||
@@ -145,14 +145,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
145 | mem->memtype = type; | 145 | mem->memtype = type; |
146 | mem->size = size; | 146 | mem->size = size; |
147 | 147 | ||
148 | mutex_lock(&mm->mutex); | 148 | mutex_lock(&pfb->base.mutex); |
149 | do { | 149 | do { |
150 | if (back) | 150 | if (back) |
151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); | 151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); |
152 | else | 152 | else |
153 | ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); | 153 | ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); |
154 | if (ret) { | 154 | if (ret) { |
155 | mutex_unlock(&mm->mutex); | 155 | mutex_unlock(&pfb->base.mutex); |
156 | pfb->ram.put(pfb, &mem); | 156 | pfb->ram.put(pfb, &mem); |
157 | return ret; | 157 | return ret; |
158 | } | 158 | } |
@@ -160,7 +160,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
160 | list_add_tail(&r->rl_entry, &mem->regions); | 160 | list_add_tail(&r->rl_entry, &mem->regions); |
161 | size -= r->length; | 161 | size -= r->length; |
162 | } while (size); | 162 | } while (size); |
163 | mutex_unlock(&mm->mutex); | 163 | mutex_unlock(&pfb->base.mutex); |
164 | 164 | ||
165 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); | 165 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); |
166 | mem->offset = (u64)r->offset << 12; | 166 | mem->offset = (u64)r->offset << 12; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index acf818c58bf0..9fb0f9b92d49 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c | |||
@@ -43,10 +43,15 @@ static int | |||
43 | nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, | 43 | nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, |
44 | struct dcb_gpio_func *func) | 44 | struct dcb_gpio_func *func) |
45 | { | 45 | { |
46 | struct nouveau_bios *bios = nouveau_bios(gpio); | ||
47 | u8 ver, len; | ||
48 | u16 data; | ||
49 | |||
46 | if (line == 0xff && tag == 0xff) | 50 | if (line == 0xff && tag == 0xff) |
47 | return -EINVAL; | 51 | return -EINVAL; |
48 | 52 | ||
49 | if (!dcb_gpio_parse(nouveau_bios(gpio), idx, tag, line, func)) | 53 | data = dcb_gpio_match(bios, idx, tag, line, &ver, &len, func); |
54 | if (data) | ||
50 | return 0; | 55 | return 0; |
51 | 56 | ||
52 | /* Apple iMac G4 NV18 */ | 57 | /* Apple iMac G4 NV18 */ |
@@ -265,7 +270,7 @@ nouveau_gpio_init(struct nouveau_gpio *gpio) | |||
265 | int ret = nouveau_subdev_init(&gpio->base); | 270 | int ret = nouveau_subdev_init(&gpio->base); |
266 | if (ret == 0 && gpio->reset) { | 271 | if (ret == 0 && gpio->reset) { |
267 | if (dmi_check_system(gpio_reset_ids)) | 272 | if (dmi_check_system(gpio_reset_ids)) |
268 | gpio->reset(gpio); | 273 | gpio->reset(gpio, DCB_GPIO_UNUSED); |
269 | } | 274 | } |
270 | return ret; | 275 | return ret; |
271 | } | 276 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index f3502c961cd9..bf13a1200f26 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c | |||
@@ -29,15 +29,15 @@ struct nv50_gpio_priv { | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | static void | 31 | static void |
32 | nv50_gpio_reset(struct nouveau_gpio *gpio) | 32 | nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match) |
33 | { | 33 | { |
34 | struct nouveau_bios *bios = nouveau_bios(gpio); | 34 | struct nouveau_bios *bios = nouveau_bios(gpio); |
35 | struct nv50_gpio_priv *priv = (void *)gpio; | 35 | struct nv50_gpio_priv *priv = (void *)gpio; |
36 | u8 ver, len; | ||
36 | u16 entry; | 37 | u16 entry; |
37 | u8 ver; | ||
38 | int ent = -1; | 38 | int ent = -1; |
39 | 39 | ||
40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { | 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { |
41 | static const u32 regs[] = { 0xe100, 0xe28c }; | 41 | static const u32 regs[] = { 0xe100, 0xe28c }; |
42 | u32 data = nv_ro32(bios, entry); | 42 | u32 data = nv_ro32(bios, entry); |
43 | u8 line = (data & 0x0000001f); | 43 | u8 line = (data & 0x0000001f); |
@@ -48,7 +48,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio) | |||
48 | u32 val = (unk1 << 16) | unk0; | 48 | u32 val = (unk1 << 16) | unk0; |
49 | u32 reg = regs[line >> 4]; line &= 0x0f; | 49 | u32 reg = regs[line >> 4]; line &= 0x0f; |
50 | 50 | ||
51 | if (func == 0xff) | 51 | if ( func == DCB_GPIO_UNUSED || |
52 | (match != DCB_GPIO_UNUSED && match != func)) | ||
52 | continue; | 53 | continue; |
53 | 54 | ||
54 | gpio->set(gpio, 0, func, line, defs); | 55 | gpio->set(gpio, 0, func, line, defs); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index 8d18fcad26e0..83e8b8f16e6a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c | |||
@@ -29,15 +29,15 @@ struct nvd0_gpio_priv { | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | static void | 31 | static void |
32 | nvd0_gpio_reset(struct nouveau_gpio *gpio) | 32 | nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) |
33 | { | 33 | { |
34 | struct nouveau_bios *bios = nouveau_bios(gpio); | 34 | struct nouveau_bios *bios = nouveau_bios(gpio); |
35 | struct nvd0_gpio_priv *priv = (void *)gpio; | 35 | struct nvd0_gpio_priv *priv = (void *)gpio; |
36 | u8 ver, len; | ||
36 | u16 entry; | 37 | u16 entry; |
37 | u8 ver; | ||
38 | int ent = -1; | 38 | int ent = -1; |
39 | 39 | ||
40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver))) { | 40 | while ((entry = dcb_gpio_entry(bios, 0, ++ent, &ver, &len))) { |
41 | u32 data = nv_ro32(bios, entry); | 41 | u32 data = nv_ro32(bios, entry); |
42 | u8 line = (data & 0x0000003f); | 42 | u8 line = (data & 0x0000003f); |
43 | u8 defs = !!(data & 0x00000080); | 43 | u8 defs = !!(data & 0x00000080); |
@@ -45,7 +45,8 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio) | |||
45 | u8 unk0 = (data & 0x00ff0000) >> 16; | 45 | u8 unk0 = (data & 0x00ff0000) >> 16; |
46 | u8 unk1 = (data & 0x1f000000) >> 24; | 46 | u8 unk1 = (data & 0x1f000000) >> 24; |
47 | 47 | ||
48 | if (func == 0xff) | 48 | if ( func == DCB_GPIO_UNUSED || |
49 | (match != DCB_GPIO_UNUSED && match != func)) | ||
49 | continue; | 50 | continue; |
50 | 51 | ||
51 | gpio->set(gpio, 0, func, line, defs); | 52 | gpio->set(gpio, 0, func, line, defs); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c index 1188227ca6aa..6565f3dbbe04 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | |||
@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_object *parent, | |||
40 | if (ret) | 40 | if (ret) |
41 | return ret; | 41 | return ret; |
42 | 42 | ||
43 | mutex_lock(&imem->base.mutex); | ||
43 | list_add(&iobj->head, &imem->list); | 44 | list_add(&iobj->head, &imem->list); |
45 | mutex_unlock(&imem->base.mutex); | ||
44 | return 0; | 46 | return 0; |
45 | } | 47 | } |
46 | 48 | ||
47 | void | 49 | void |
48 | nouveau_instobj_destroy(struct nouveau_instobj *iobj) | 50 | nouveau_instobj_destroy(struct nouveau_instobj *iobj) |
49 | { | 51 | { |
50 | if (iobj->head.prev) | 52 | struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); |
51 | list_del(&iobj->head); | 53 | |
54 | mutex_lock(&subdev->mutex); | ||
55 | list_del(&iobj->head); | ||
56 | mutex_unlock(&subdev->mutex); | ||
57 | |||
52 | return nouveau_object_destroy(&iobj->base); | 58 | return nouveau_object_destroy(&iobj->base); |
53 | } | 59 | } |
54 | 60 | ||
@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) | |||
88 | if (ret) | 94 | if (ret) |
89 | return ret; | 95 | return ret; |
90 | 96 | ||
97 | mutex_lock(&imem->base.mutex); | ||
98 | |||
91 | list_for_each_entry(iobj, &imem->list, head) { | 99 | list_for_each_entry(iobj, &imem->list, head) { |
92 | if (iobj->suspend) { | 100 | if (iobj->suspend) { |
93 | for (i = 0; i < iobj->size; i += 4) | 101 | for (i = 0; i < iobj->size; i += 4) |
@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) | |||
97 | } | 105 | } |
98 | } | 106 | } |
99 | 107 | ||
108 | mutex_unlock(&imem->base.mutex); | ||
109 | |||
100 | return 0; | 110 | return 0; |
101 | } | 111 | } |
102 | 112 | ||
@@ -104,17 +114,26 @@ int | |||
104 | nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) | 114 | nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) |
105 | { | 115 | { |
106 | struct nouveau_instobj *iobj; | 116 | struct nouveau_instobj *iobj; |
107 | int i; | 117 | int i, ret = 0; |
108 | 118 | ||
109 | if (suspend) { | 119 | if (suspend) { |
120 | mutex_lock(&imem->base.mutex); | ||
121 | |||
110 | list_for_each_entry(iobj, &imem->list, head) { | 122 | list_for_each_entry(iobj, &imem->list, head) { |
111 | iobj->suspend = vmalloc(iobj->size); | 123 | iobj->suspend = vmalloc(iobj->size); |
112 | if (iobj->suspend) { | 124 | if (!iobj->suspend) { |
113 | for (i = 0; i < iobj->size; i += 4) | 125 | ret = -ENOMEM; |
114 | iobj->suspend[i / 4] = nv_ro32(iobj, i); | 126 | break; |
115 | } else | 127 | } |
116 | return -ENOMEM; | 128 | |
129 | for (i = 0; i < iobj->size; i += 4) | ||
130 | iobj->suspend[i / 4] = nv_ro32(iobj, i); | ||
117 | } | 131 | } |
132 | |||
133 | mutex_unlock(&imem->base.mutex); | ||
134 | |||
135 | if (ret) | ||
136 | return ret; | ||
118 | } | 137 | } |
119 | 138 | ||
120 | return nouveau_subdev_fini(&imem->base, suspend); | 139 | return nouveau_subdev_fini(&imem->base, suspend); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index 93e3ddf7303a..e286e132c7e7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c | |||
@@ -260,7 +260,7 @@ nouveau_mxm_create_(struct nouveau_object *parent, | |||
260 | 260 | ||
261 | data = mxm_table(bios, &ver, &len); | 261 | data = mxm_table(bios, &ver, &len); |
262 | if (!data || !(ver = nv_ro08(bios, data))) { | 262 | if (!data || !(ver = nv_ro08(bios, data))) { |
263 | nv_info(mxm, "no VBIOS data, nothing to do\n"); | 263 | nv_debug(mxm, "no VBIOS data, nothing to do\n"); |
264 | return 0; | 264 | return 0; |
265 | } | 265 | } |
266 | 266 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 082c11b75acb..77c67fc970e6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c | |||
@@ -352,7 +352,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
352 | u64 mm_length = (offset + length) - mm_offset; | 352 | u64 mm_length = (offset + length) - mm_offset; |
353 | int ret; | 353 | int ret; |
354 | 354 | ||
355 | vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL); | 355 | vm = kzalloc(sizeof(*vm), GFP_KERNEL); |
356 | if (!vm) | 356 | if (!vm) |
357 | return -ENOMEM; | 357 | return -ENOMEM; |
358 | 358 | ||
@@ -376,6 +376,8 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
376 | return ret; | 376 | return ret; |
377 | } | 377 | } |
378 | 378 | ||
379 | *pvm = vm; | ||
380 | |||
379 | return 0; | 381 | return 0; |
380 | } | 382 | } |
381 | 383 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5614c89148cb..69d7b1d0b9d6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -1276,7 +1276,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
1276 | if (drm->agp.stat == ENABLED) { | 1276 | if (drm->agp.stat == ENABLED) { |
1277 | mem->bus.offset = mem->start << PAGE_SHIFT; | 1277 | mem->bus.offset = mem->start << PAGE_SHIFT; |
1278 | mem->bus.base = drm->agp.base; | 1278 | mem->bus.base = drm->agp.base; |
1279 | mem->bus.is_iomem = true; | 1279 | mem->bus.is_iomem = !dev->agp->cant_use_aperture; |
1280 | } | 1280 | } |
1281 | #endif | 1281 | #endif |
1282 | break; | 1282 | break; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index ac340ba32017..e620ba8271b4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -127,12 +127,26 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
127 | struct nouveau_encoder **pnv_encoder) | 127 | struct nouveau_encoder **pnv_encoder) |
128 | { | 128 | { |
129 | struct drm_device *dev = connector->dev; | 129 | struct drm_device *dev = connector->dev; |
130 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
130 | struct nouveau_drm *drm = nouveau_drm(dev); | 131 | struct nouveau_drm *drm = nouveau_drm(dev); |
132 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||
131 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | 133 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |
132 | int i; | 134 | struct nouveau_i2c_port *port = NULL; |
135 | int i, panel = -ENODEV; | ||
136 | |||
137 | /* eDP panels need powering on by us (if the VBIOS doesn't default it | ||
138 | * to on) before doing any AUX channel transactions. LVDS panel power | ||
139 | * is handled by the SOR itself, and not required for LVDS DDC. | ||
140 | */ | ||
141 | if (nv_connector->type == DCB_CONNECTOR_eDP) { | ||
142 | panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); | ||
143 | if (panel == 0) { | ||
144 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||
145 | msleep(300); | ||
146 | } | ||
147 | } | ||
133 | 148 | ||
134 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | 149 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
135 | struct nouveau_i2c_port *port = NULL; | ||
136 | struct nouveau_encoder *nv_encoder; | 150 | struct nouveau_encoder *nv_encoder; |
137 | struct drm_mode_object *obj; | 151 | struct drm_mode_object *obj; |
138 | int id; | 152 | int id; |
@@ -150,11 +164,19 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
150 | port = i2c->find(i2c, nv_encoder->dcb->i2c_index); | 164 | port = i2c->find(i2c, nv_encoder->dcb->i2c_index); |
151 | if (port && nv_probe_i2c(port, 0x50)) { | 165 | if (port && nv_probe_i2c(port, 0x50)) { |
152 | *pnv_encoder = nv_encoder; | 166 | *pnv_encoder = nv_encoder; |
153 | return port; | 167 | break; |
154 | } | 168 | } |
169 | |||
170 | port = NULL; | ||
155 | } | 171 | } |
156 | 172 | ||
157 | return NULL; | 173 | /* eDP panel not detected, restore panel power GPIO to previous |
174 | * state to avoid confusing the SOR for other output types. | ||
175 | */ | ||
176 | if (!port && panel == 0) | ||
177 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); | ||
178 | |||
179 | return port; | ||
158 | } | 180 | } |
159 | 181 | ||
160 | static struct nouveau_encoder * | 182 | static struct nouveau_encoder * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e4188f24fc75..508b00a2ce0d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -225,15 +225,6 @@ nouveau_display_init(struct drm_device *dev) | |||
225 | if (ret) | 225 | if (ret) |
226 | return ret; | 226 | return ret; |
227 | 227 | ||
228 | /* power on internal panel if it's not already. the init tables of | ||
229 | * some vbios default this to off for some reason, causing the | ||
230 | * panel to not work after resume | ||
231 | */ | ||
232 | if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) { | ||
233 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||
234 | msleep(300); | ||
235 | } | ||
236 | |||
237 | /* enable polling for external displays */ | 228 | /* enable polling for external displays */ |
238 | drm_kms_helper_poll_enable(dev); | 229 | drm_kms_helper_poll_enable(dev); |
239 | 230 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 01c403ddb99b..8b090f1eb51d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -84,11 +84,16 @@ nouveau_cli_create(struct pci_dev *pdev, const char *name, | |||
84 | struct nouveau_cli *cli; | 84 | struct nouveau_cli *cli; |
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | *pcli = NULL; | ||
87 | ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, | 88 | ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, |
88 | nouveau_debug, size, pcli); | 89 | nouveau_debug, size, pcli); |
89 | cli = *pcli; | 90 | cli = *pcli; |
90 | if (ret) | 91 | if (ret) { |
92 | if (cli) | ||
93 | nouveau_client_destroy(&cli->base); | ||
94 | *pcli = NULL; | ||
91 | return ret; | 95 | return ret; |
96 | } | ||
92 | 97 | ||
93 | mutex_init(&cli->mutex); | 98 | mutex_init(&cli->mutex); |
94 | return 0; | 99 | return 0; |
@@ -189,8 +194,8 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
189 | nouveau_bo_move_init(drm); | 194 | nouveau_bo_move_init(drm); |
190 | } | 195 | } |
191 | 196 | ||
192 | static int __devinit | 197 | static int nouveau_drm_probe(struct pci_dev *pdev, |
193 | nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) | 198 | const struct pci_device_id *pent) |
194 | { | 199 | { |
195 | struct nouveau_device *device; | 200 | struct nouveau_device *device; |
196 | struct apertures_struct *aper; | 201 | struct apertures_struct *aper; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index bedafd1c9539..cdb83acdffe2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h | |||
@@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_channel *); | |||
60 | void nv10_fence_context_del(struct nouveau_channel *); | 60 | void nv10_fence_context_del(struct nouveau_channel *); |
61 | void nv10_fence_destroy(struct nouveau_drm *); | 61 | void nv10_fence_destroy(struct nouveau_drm *); |
62 | int nv10_fence_create(struct nouveau_drm *); | 62 | int nv10_fence_create(struct nouveau_drm *); |
63 | void nv17_fence_resume(struct nouveau_drm *drm); | ||
63 | 64 | ||
64 | int nv50_fence_create(struct nouveau_drm *); | 65 | int nv50_fence_create(struct nouveau_drm *); |
65 | int nv84_fence_create(struct nouveau_drm *); | 66 | int nv84_fence_create(struct nouveau_drm *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 5566172774df..a701ff5ffa5b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -698,10 +698,10 @@ static int | |||
698 | nouveau_hwmon_init(struct drm_device *dev) | 698 | nouveau_hwmon_init(struct drm_device *dev) |
699 | { | 699 | { |
700 | struct nouveau_pm *pm = nouveau_pm(dev); | 700 | struct nouveau_pm *pm = nouveau_pm(dev); |
701 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
702 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
703 | 701 | ||
704 | #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) | 702 | #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) |
703 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
704 | struct nouveau_therm *therm = nouveau_therm(drm->device); | ||
705 | struct device *hwmon_dev; | 705 | struct device *hwmon_dev; |
706 | int ret = 0; | 706 | int ret = 0; |
707 | 707 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 3543fec2355e..b8e05ae38212 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c | |||
@@ -193,6 +193,7 @@ struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev, | |||
193 | if (nvbo->gem) { | 193 | if (nvbo->gem) { |
194 | if (nvbo->gem->dev == dev) { | 194 | if (nvbo->gem->dev == dev) { |
195 | drm_gem_object_reference(nvbo->gem); | 195 | drm_gem_object_reference(nvbo->gem); |
196 | dma_buf_put(dma_buf); | ||
196 | return nvbo->gem; | 197 | return nvbo->gem; |
197 | } | 198 | } |
198 | } | 199 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 184cdf806761..39ffc07f906b 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) | |||
505 | 505 | ||
506 | static inline bool is_powersaving_dpms(int mode) | 506 | static inline bool is_powersaving_dpms(int mode) |
507 | { | 507 | { |
508 | return (mode != DRM_MODE_DPMS_ON); | 508 | return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; |
509 | } | 509 | } |
510 | 510 | ||
511 | static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) | 511 | static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) |
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 7ae7f97a6d4d..03017f24d593 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c | |||
@@ -162,6 +162,13 @@ nv10_fence_destroy(struct nouveau_drm *drm) | |||
162 | kfree(priv); | 162 | kfree(priv); |
163 | } | 163 | } |
164 | 164 | ||
165 | void nv17_fence_resume(struct nouveau_drm *drm) | ||
166 | { | ||
167 | struct nv10_fence_priv *priv = drm->fence; | ||
168 | |||
169 | nouveau_bo_wr32(priv->bo, 0, priv->sequence); | ||
170 | } | ||
171 | |||
165 | int | 172 | int |
166 | nv10_fence_create(struct nouveau_drm *drm) | 173 | nv10_fence_create(struct nouveau_drm *drm) |
167 | { | 174 | { |
@@ -197,6 +204,7 @@ nv10_fence_create(struct nouveau_drm *drm) | |||
197 | if (ret == 0) { | 204 | if (ret == 0) { |
198 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); | 205 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); |
199 | priv->base.sync = nv17_fence_sync; | 206 | priv->base.sync = nv17_fence_sync; |
207 | priv->base.resume = nv17_fence_resume; | ||
200 | } | 208 | } |
201 | } | 209 | } |
202 | 210 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index c20f2727ea0b..d889f3ac0d41 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c | |||
@@ -122,6 +122,7 @@ nv50_fence_create(struct nouveau_drm *drm) | |||
122 | if (ret == 0) { | 122 | if (ret == 0) { |
123 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); | 123 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); |
124 | priv->base.sync = nv17_fence_sync; | 124 | priv->base.sync = nv17_fence_sync; |
125 | priv->base.resume = nv17_fence_resume; | ||
125 | } | 126 | } |
126 | 127 | ||
127 | if (ret) | 128 | if (ret) |