aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-02-18 17:50:51 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 01:01:02 -0500
commit5cc027f6b1ec651c18a4322ed3e30c6e9cf01e96 (patch)
tree1f39b3fb82ea8e7d395a974584f5915c95dcfa6c /drivers/gpu/drm/nouveau
parent7dcd060c0e6e4f76ce7eea94c66437ce8f546530 (diff)
drm/nv50-/disp: handle supervisor tasks from workqueue
i2c_algo_bit sleeps... Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.h6
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv84.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv94.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva0.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nva3.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c47
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nve0.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c5
9 files changed, 53 insertions, 32 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index c3806122d771..d22f6569768c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -940,7 +940,6 @@ nv50_disp_intr_unk10(struct nv50_disp_priv *priv, u32 super)
940 exec_script(priv, head, 1); 940 exec_script(priv, head, 1);
941 } 941 }
942 942
943 nv_wr32(priv, 0x610024, 0x00000010);
944 nv_wr32(priv, 0x610030, 0x80000000); 943 nv_wr32(priv, 0x610030, 0x80000000);
945} 944}
946 945
@@ -1097,7 +1096,6 @@ nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super)
1097 } 1096 }
1098 } 1097 }
1099 1098
1100 nv_wr32(priv, 0x610024, 0x00000020);
1101 nv_wr32(priv, 0x610030, 0x80000000); 1099 nv_wr32(priv, 0x610030, 0x80000000);
1102} 1100}
1103 1101
@@ -1136,22 +1134,23 @@ nv50_disp_intr_unk40(struct nv50_disp_priv *priv, u32 super)
1136 } 1134 }
1137 } 1135 }
1138 1136
1139 nv_wr32(priv, 0x610024, 0x00000040);
1140 nv_wr32(priv, 0x610030, 0x80000000); 1137 nv_wr32(priv, 0x610030, 0x80000000);
1141} 1138}
1142 1139
1143static void 1140void
1144nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1) 1141nv50_disp_intr_supervisor(struct work_struct *work)
1145{ 1142{
1143 struct nv50_disp_priv *priv =
1144 container_of(work, struct nv50_disp_priv, supervisor);
1146 u32 super = nv_rd32(priv, 0x610030); 1145 u32 super = nv_rd32(priv, 0x610030);
1147 1146
1148 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super); 1147 nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);
1149 1148
1150 if (intr1 & 0x00000010) 1149 if (priv->super & 0x00000010)
1151 nv50_disp_intr_unk10(priv, super); 1150 nv50_disp_intr_unk10(priv, super);
1152 if (intr1 & 0x00000020) 1151 if (priv->super & 0x00000020)
1153 nv50_disp_intr_unk20(priv, super); 1152 nv50_disp_intr_unk20(priv, super);
1154 if (intr1 & 0x00000040) 1153 if (priv->super & 0x00000040)
1155 nv50_disp_intr_unk40(priv, super); 1154 nv50_disp_intr_unk40(priv, super);
1156} 1155}
1157 1156
@@ -1180,7 +1179,9 @@ nv50_disp_intr(struct nouveau_subdev *subdev)
1180 } 1179 }
1181 1180
1182 if (intr1 & 0x00000070) { 1181 if (intr1 & 0x00000070) {
1183 nv50_disp_intr_super(priv, intr1); 1182 priv->super = (intr1 & 0x00000070);
1183 schedule_work(&priv->supervisor);
1184 nv_wr32(priv, 0x610024, priv->super);
1184 intr1 &= ~0x00000070; 1185 intr1 &= ~0x00000070;
1185 } 1186 }
1186} 1187}
@@ -1202,6 +1203,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1202 nv_engine(priv)->sclass = nv50_disp_base_oclass; 1203 nv_engine(priv)->sclass = nv50_disp_base_oclass;
1203 nv_engine(priv)->cclass = &nv50_disp_cclass; 1204 nv_engine(priv)->cclass = &nv50_disp_cclass;
1204 nv_subdev(priv)->intr = nv50_disp_intr; 1205 nv_subdev(priv)->intr = nv50_disp_intr;
1206 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
1205 priv->sclass = nv50_disp_sclass; 1207 priv->sclass = nv50_disp_sclass;
1206 priv->head.nr = 2; 1208 priv->head.nr = 2;
1207 priv->dac.nr = 3; 1209 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
index fc897181fa38..b88a62129814 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
@@ -15,6 +15,10 @@ struct dcb_output;
15struct nv50_disp_priv { 15struct nv50_disp_priv {
16 struct nouveau_disp base; 16 struct nouveau_disp base;
17 struct nouveau_oclass *sclass; 17 struct nouveau_oclass *sclass;
18
19 struct work_struct supervisor;
20 u32 super;
21
18 struct { 22 struct {
19 int nr; 23 int nr;
20 } head; 24 } head;
@@ -126,6 +130,7 @@ extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;
126extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; 130extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;
127extern struct nouveau_ofuncs nv50_disp_base_ofuncs; 131extern struct nouveau_ofuncs nv50_disp_base_ofuncs;
128extern struct nouveau_oclass nv50_disp_cclass; 132extern struct nouveau_oclass nv50_disp_cclass;
133void nv50_disp_intr_supervisor(struct work_struct *);
129void nv50_disp_intr(struct nouveau_subdev *); 134void nv50_disp_intr(struct nouveau_subdev *);
130 135
131extern struct nouveau_omthds nv84_disp_base_omthds[]; 136extern struct nouveau_omthds nv84_disp_base_omthds[];
@@ -139,6 +144,7 @@ extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;
139extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; 144extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs;
140extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; 145extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;
141extern struct nouveau_oclass nvd0_disp_cclass; 146extern struct nouveau_oclass nvd0_disp_cclass;
147void nvd0_disp_intr_supervisor(struct work_struct *);
142void nvd0_disp_intr(struct nouveau_subdev *); 148void nvd0_disp_intr(struct nouveau_subdev *);
143 149
144#endif 150#endif
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
index a2153424605d..9ec942a0f9f6 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
@@ -72,6 +72,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
72 nv_engine(priv)->sclass = nv84_disp_base_oclass; 72 nv_engine(priv)->sclass = nv84_disp_base_oclass;
73 nv_engine(priv)->cclass = &nv50_disp_cclass; 73 nv_engine(priv)->cclass = &nv50_disp_cclass;
74 nv_subdev(priv)->intr = nv50_disp_intr; 74 nv_subdev(priv)->intr = nv50_disp_intr;
75 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
75 priv->sclass = nv84_disp_sclass; 76 priv->sclass = nv84_disp_sclass;
76 priv->head.nr = 2; 77 priv->head.nr = 2;
77 priv->dac.nr = 3; 78 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
index a315e28ac17e..a838bdd2019b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
@@ -78,6 +78,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
78 nv_engine(priv)->sclass = nv94_disp_base_oclass; 78 nv_engine(priv)->sclass = nv94_disp_base_oclass;
79 nv_engine(priv)->cclass = &nv50_disp_cclass; 79 nv_engine(priv)->cclass = &nv50_disp_cclass;
80 nv_subdev(priv)->intr = nv50_disp_intr; 80 nv_subdev(priv)->intr = nv50_disp_intr;
81 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
81 priv->sclass = nv94_disp_sclass; 82 priv->sclass = nv94_disp_sclass;
82 priv->head.nr = 2; 83 priv->head.nr = 2;
83 priv->dac.nr = 3; 84 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
index 480e2ded95fa..ce539ca1d308 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
@@ -62,6 +62,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
62 nv_engine(priv)->sclass = nva0_disp_base_oclass; 62 nv_engine(priv)->sclass = nva0_disp_base_oclass;
63 nv_engine(priv)->cclass = &nv50_disp_cclass; 63 nv_engine(priv)->cclass = &nv50_disp_cclass;
64 nv_subdev(priv)->intr = nv50_disp_intr; 64 nv_subdev(priv)->intr = nv50_disp_intr;
65 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
65 priv->sclass = nva0_disp_sclass; 66 priv->sclass = nva0_disp_sclass;
66 priv->head.nr = 2; 67 priv->head.nr = 2;
67 priv->dac.nr = 3; 68 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
index 718b4f66352e..bd2bb4751089 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
@@ -79,6 +79,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
79 nv_engine(priv)->sclass = nva3_disp_base_oclass; 79 nv_engine(priv)->sclass = nva3_disp_base_oclass;
80 nv_engine(priv)->cclass = &nv50_disp_cclass; 80 nv_engine(priv)->cclass = &nv50_disp_cclass;
81 nv_subdev(priv)->intr = nv50_disp_intr; 81 nv_subdev(priv)->intr = nv50_disp_intr;
82 INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor);
82 priv->sclass = nva3_disp_sclass; 83 priv->sclass = nva3_disp_sclass;
83 priv->head.nr = 2; 84 priv->head.nr = 2;
84 priv->dac.nr = 3; 85 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index 77cc73024072..1c91eb1679a0 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -836,6 +836,26 @@ nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask)
836} 836}
837 837
838void 838void
839nvd0_disp_intr_supervisor(struct work_struct *work)
840{
841 struct nv50_disp_priv *priv =
842 container_of(work, struct nv50_disp_priv, supervisor);
843 u32 mask = 0, head = ~0;
844
845 while (!mask && ++head < priv->head.nr)
846 mask = nv_rd32(priv, 0x6101d4 + (head * 0x800));
847
848 nv_debug(priv, "supervisor %08x %08x %d\n", priv->super, mask, head);
849
850 if (priv->super & 0x00000001)
851 nvd0_display_unk1_handler(priv, head, mask);
852 if (priv->super & 0x00000002)
853 nvd0_display_unk2_handler(priv, head, mask);
854 if (priv->super & 0x00000004)
855 nvd0_display_unk4_handler(priv, head, mask);
856}
857
858void
839nvd0_disp_intr(struct nouveau_subdev *subdev) 859nvd0_disp_intr(struct nouveau_subdev *subdev)
840{ 860{
841 struct nv50_disp_priv *priv = (void *)subdev; 861 struct nv50_disp_priv *priv = (void *)subdev;
@@ -868,27 +888,11 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)
868 888
869 if (intr & 0x00100000) { 889 if (intr & 0x00100000) {
870 u32 stat = nv_rd32(priv, 0x6100ac); 890 u32 stat = nv_rd32(priv, 0x6100ac);
871 u32 mask = 0, crtc = ~0; 891 if (stat & 0x00000007) {
872 892 priv->super = (stat & 0x00000007);
873 while (!mask && ++crtc < priv->head.nr) 893 schedule_work(&priv->supervisor);
874 mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800)); 894 nv_wr32(priv, 0x6100ac, priv->super);
875 895 stat &= ~0x00000007;
876 if (stat & 0x00000001) {
877 nv_wr32(priv, 0x6100ac, 0x00000001);
878 nvd0_display_unk1_handler(priv, crtc, mask);
879 stat &= ~0x00000001;
880 }
881
882 if (stat & 0x00000002) {
883 nv_wr32(priv, 0x6100ac, 0x00000002);
884 nvd0_display_unk2_handler(priv, crtc, mask);
885 stat &= ~0x00000002;
886 }
887
888 if (stat & 0x00000004) {
889 nv_wr32(priv, 0x6100ac, 0x00000004);
890 nvd0_display_unk4_handler(priv, crtc, mask);
891 stat &= ~0x00000004;
892 } 896 }
893 897
894 if (stat) { 898 if (stat) {
@@ -929,6 +933,7 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
929 nv_engine(priv)->sclass = nvd0_disp_base_oclass; 933 nv_engine(priv)->sclass = nvd0_disp_base_oclass;
930 nv_engine(priv)->cclass = &nv50_disp_cclass; 934 nv_engine(priv)->cclass = &nv50_disp_cclass;
931 nv_subdev(priv)->intr = nvd0_disp_intr; 935 nv_subdev(priv)->intr = nvd0_disp_intr;
936 INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
932 priv->sclass = nvd0_disp_sclass; 937 priv->sclass = nvd0_disp_sclass;
933 priv->head.nr = heads; 938 priv->head.nr = heads;
934 priv->dac.nr = 3; 939 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
index 5512296a61d7..65c19ca073b1 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
@@ -63,6 +63,7 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
63 nv_engine(priv)->sclass = nve0_disp_base_oclass; 63 nv_engine(priv)->sclass = nve0_disp_base_oclass;
64 nv_engine(priv)->cclass = &nv50_disp_cclass; 64 nv_engine(priv)->cclass = &nv50_disp_cclass;
65 nv_subdev(priv)->intr = nvd0_disp_intr; 65 nv_subdev(priv)->intr = nvd0_disp_intr;
66 INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
66 priv->sclass = nve0_disp_sclass; 67 priv->sclass = nve0_disp_sclass;
67 priv->head.nr = heads; 68 priv->head.nr = heads;
68 priv->dac.nr = 3; 69 priv->dac.nr = 3;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 75d116137c0a..2cd37979dcd3 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -424,7 +424,10 @@ evo_kick(u32 *push, void *evoc)
424static bool 424static bool
425evo_sync_wait(void *data) 425evo_sync_wait(void *data)
426{ 426{
427 return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; 427 if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000)
428 return true;
429 usleep_range(1, 2);
430 return false;
428} 431}
429 432
430static int 433static int