aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-05-20 21:39:07 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-06-11 02:10:45 -0400
commit2bd651ea4323e7fd1379593b701dd25289c68193 (patch)
tree85b7e96a14d4be5c848b45e6d44968adcadd73d5 /drivers/gpu/drm/nouveau
parent415f12efc1b2308411b2cbc3e82666b3db8a7758 (diff)
drm/gf119/disp: start removing direct vbios parsing from supervisor
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/nvd0.c158
1 files changed, 83 insertions, 75 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
index e5f5e425e3e2..27ec9954a70b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
@@ -915,19 +915,20 @@ nvd0_disp_sclass[] = {
915 * Display engine implementation 915 * Display engine implementation
916 ******************************************************************************/ 916 ******************************************************************************/
917 917
918static u16 918static struct nvkm_output *
919exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, 919exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl,
920 struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 920 u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
921 struct nvbios_outp *info) 921 struct nvbios_outp *info)
922{ 922{
923 struct nouveau_bios *bios = nouveau_bios(priv); 923 struct nouveau_bios *bios = nouveau_bios(priv);
924 u16 mask, type, data; 924 struct nvkm_output *outp;
925 u16 mask, type;
925 926
926 if (outp < 4) { 927 if (or < 4) {
927 type = DCB_OUTPUT_ANALOG; 928 type = DCB_OUTPUT_ANALOG;
928 mask = 0; 929 mask = 0;
929 } else { 930 } else {
930 outp -= 4; 931 or -= 4;
931 switch (ctrl & 0x00000f00) { 932 switch (ctrl & 0x00000f00) {
932 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; 933 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;
933 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; 934 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break;
@@ -939,47 +940,53 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,
939 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); 940 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
940 return 0x0000; 941 return 0x0000;
941 } 942 }
942 dcb->sorconf.link = mask;
943 } 943 }
944 944
945 mask = 0x00c0 & (mask << 6); 945 mask = 0x00c0 & (mask << 6);
946 mask |= 0x0001 << outp; 946 mask |= 0x0001 << or;
947 mask |= 0x0100 << head; 947 mask |= 0x0100 << head;
948 948
949 data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); 949 list_for_each_entry(outp, &priv->base.outp, head) {
950 if (!data) 950 if ((outp->info.hasht & 0xff) == type &&
951 return 0x0000; 951 (outp->info.hashm & mask) == mask) {
952 *data = nvbios_outp_match(bios, outp->info.hasht,
953 outp->info.hashm,
954 ver, hdr, cnt, len, info);
955 if (!*data)
956 return NULL;
957 return outp;
958 }
959 }
952 960
953 return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); 961 return NULL;
954} 962}
955 963
956static bool 964static bool
957exec_script(struct nv50_disp_priv *priv, int head, int id) 965exec_script(struct nv50_disp_priv *priv, int head, int id)
958{ 966{
959 struct nouveau_bios *bios = nouveau_bios(priv); 967 struct nouveau_bios *bios = nouveau_bios(priv);
968 struct nvkm_output *outp;
960 struct nvbios_outp info; 969 struct nvbios_outp info;
961 struct dcb_output dcb;
962 u8 ver, hdr, cnt, len; 970 u8 ver, hdr, cnt, len;
963 u32 ctrl = 0x00000000; 971 u32 data, ctrl = 0;
964 u16 data; 972 int or;
965 int outp;
966 973
967 for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { 974 for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
968 ctrl = nv_rd32(priv, 0x640180 + (outp * 0x20)); 975 ctrl = nv_rd32(priv, 0x640180 + (or * 0x20));
969 if (ctrl & (1 << head)) 976 if (ctrl & (1 << head))
970 break; 977 break;
971 } 978 }
972 979
973 if (outp == 8) 980 if (or == 8)
974 return false; 981 return false;
975 982
976 data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); 983 outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info);
977 if (data) { 984 if (outp) {
978 struct nvbios_init init = { 985 struct nvbios_init init = {
979 .subdev = nv_subdev(priv), 986 .subdev = nv_subdev(priv),
980 .bios = bios, 987 .bios = bios,
981 .offset = info.script[id], 988 .offset = info.script[id],
982 .outp = &dcb, 989 .outp = &outp->info,
983 .crtc = head, 990 .crtc = head,
984 .execute = 1, 991 .execute = 1,
985 }; 992 };
@@ -990,50 +997,49 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)
990 return false; 997 return false;
991} 998}
992 999
993static u32 1000static struct nvkm_output *
994exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, 1001exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)
995 u32 pclk, struct dcb_output *dcb)
996{ 1002{
997 struct nouveau_bios *bios = nouveau_bios(priv); 1003 struct nouveau_bios *bios = nouveau_bios(priv);
1004 struct nvkm_output *outp;
998 struct nvbios_outp info1; 1005 struct nvbios_outp info1;
999 struct nvbios_ocfg info2; 1006 struct nvbios_ocfg info2;
1000 u8 ver, hdr, cnt, len; 1007 u8 ver, hdr, cnt, len;
1001 u32 ctrl = 0x00000000; 1008 u32 data, ctrl = 0;
1002 u32 data, conf = ~0; 1009 int or;
1003 int outp;
1004 1010
1005 for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { 1011 for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) {
1006 ctrl = nv_rd32(priv, 0x660180 + (outp * 0x20)); 1012 ctrl = nv_rd32(priv, 0x660180 + (or * 0x20));
1007 if (ctrl & (1 << head)) 1013 if (ctrl & (1 << head))
1008 break; 1014 break;
1009 } 1015 }
1010 1016
1011 if (outp == 8) 1017 if (or == 8)
1012 return conf; 1018 return NULL;
1013 1019
1014 data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); 1020 outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1);
1015 if (data == 0x0000) 1021 if (!outp)
1016 return conf; 1022 return NULL;
1017 1023
1018 switch (dcb->type) { 1024 switch (outp->info.type) {
1019 case DCB_OUTPUT_TMDS: 1025 case DCB_OUTPUT_TMDS:
1020 conf = (ctrl & 0x00000f00) >> 8; 1026 *conf = (ctrl & 0x00000f00) >> 8;
1021 if (pclk >= 165000) 1027 if (pclk >= 165000)
1022 conf |= 0x0100; 1028 *conf |= 0x0100;
1023 break; 1029 break;
1024 case DCB_OUTPUT_LVDS: 1030 case DCB_OUTPUT_LVDS:
1025 conf = priv->sor.lvdsconf; 1031 *conf = priv->sor.lvdsconf;
1026 break; 1032 break;
1027 case DCB_OUTPUT_DP: 1033 case DCB_OUTPUT_DP:
1028 conf = (ctrl & 0x00000f00) >> 8; 1034 *conf = (ctrl & 0x00000f00) >> 8;
1029 break; 1035 break;
1030 case DCB_OUTPUT_ANALOG: 1036 case DCB_OUTPUT_ANALOG:
1031 default: 1037 default:
1032 conf = 0x00ff; 1038 *conf = 0x00ff;
1033 break; 1039 break;
1034 } 1040 }
1035 1041
1036 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 1042 data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
1037 if (data && id < 0xff) { 1043 if (data && id < 0xff) {
1038 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 1044 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
1039 if (data) { 1045 if (data) {
@@ -1041,7 +1047,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
1041 .subdev = nv_subdev(priv), 1047 .subdev = nv_subdev(priv),
1042 .bios = bios, 1048 .bios = bios,
1043 .offset = data, 1049 .offset = data,
1044 .outp = dcb, 1050 .outp = &outp->info,
1045 .crtc = head, 1051 .crtc = head,
1046 .execute = 1, 1052 .execute = 1,
1047 }; 1053 };
@@ -1050,7 +1056,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
1050 } 1056 }
1051 } 1057 }
1052 1058
1053 return conf; 1059 return outp;
1054} 1060}
1055 1061
1056static void 1062static void
@@ -1124,49 +1130,51 @@ nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head,
1124static void 1130static void
1125nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head) 1131nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head)
1126{ 1132{
1127 struct dcb_output outp; 1133 struct nvkm_output *outp;
1128 u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; 1134 u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
1129 u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); 1135 u32 conf, addr, data;
1130 if (conf != ~0) { 1136
1131 u32 addr, data; 1137 outp = exec_clkcmp(priv, head, 0xff, pclk, &conf);
1132 1138 if (!outp)
1133 if (outp.type == DCB_OUTPUT_DP) { 1139 return;
1134 u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); 1140
1135 switch ((sync & 0x000003c0) >> 6) { 1141 if (outp->info.type == DCB_OUTPUT_DP) {
1136 case 6: pclk = pclk * 30 / 8; break; 1142 u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300));
1137 case 5: pclk = pclk * 24 / 8; break; 1143 switch ((sync & 0x000003c0) >> 6) {
1138 case 2: 1144 case 6: pclk = pclk * 30 / 8; break;
1139 default: 1145 case 5: pclk = pclk * 24 / 8; break;
1140 pclk = pclk * 18 / 8; 1146 case 2:
1141 break; 1147 default:
1142 } 1148 pclk = pclk * 18 / 8;
1143 1149 break;
1144 nouveau_dp_train(&priv->base, priv->sor.dp,
1145 &outp, head, pclk);
1146 } 1150 }
1147 1151
1148 exec_clkcmp(priv, head, 0, pclk, &outp); 1152 nouveau_dp_train(&priv->base, priv->sor.dp,
1153 &outp->info, head, pclk);
1154 }
1149 1155
1150 if (outp.type == DCB_OUTPUT_ANALOG) { 1156 exec_clkcmp(priv, head, 0, pclk, &conf);
1151 addr = 0x612280 + (ffs(outp.or) - 1) * 0x800;
1152 data = 0x00000000;
1153 } else {
1154 if (outp.type == DCB_OUTPUT_DP)
1155 nvd0_disp_intr_unk2_2_tu(priv, head, &outp);
1156 addr = 0x612300 + (ffs(outp.or) - 1) * 0x800;
1157 data = (conf & 0x0100) ? 0x00000101 : 0x00000000;
1158 }
1159 1157
1160 nv_mask(priv, addr, 0x00000707, data); 1158 if (outp->info.type == DCB_OUTPUT_ANALOG) {
1159 addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800;
1160 data = 0x00000000;
1161 } else {
1162 if (outp->info.type == DCB_OUTPUT_DP)
1163 nvd0_disp_intr_unk2_2_tu(priv, head, &outp->info);
1164 addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800;
1165 data = (conf & 0x0100) ? 0x00000101 : 0x00000000;
1161 } 1166 }
1167
1168 nv_mask(priv, addr, 0x00000707, data);
1162} 1169}
1163 1170
1164static void 1171static void
1165nvd0_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head) 1172nvd0_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head)
1166{ 1173{
1167 struct dcb_output outp;
1168 u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; 1174 u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000;
1169 exec_clkcmp(priv, head, 1, pclk, &outp); 1175 u32 conf;
1176
1177 exec_clkcmp(priv, head, 1, pclk, &conf);
1170} 1178}
1171 1179
1172void 1180void