aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index abc382a9918b..c11039f90d2e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -26,6 +26,7 @@
26#define NV_DEBUG_NOTRACE 26#define NV_DEBUG_NOTRACE
27#include "nouveau_drv.h" 27#include "nouveau_drv.h"
28#include "nouveau_hw.h" 28#include "nouveau_hw.h"
29#include "nouveau_encoder.h"
29 30
30/* these defines are made up */ 31/* these defines are made up */
31#define NV_CIO_CRE_44_HEADA 0x0 32#define NV_CIO_CRE_44_HEADA 0x0
@@ -1067,6 +1068,126 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset,
1067} 1068}
1068 1069
1069static int 1070static int
1071init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
1072{
1073 /*
1074 * INIT_DP_CONDITION opcode: 0x3A ('')
1075 *
1076 * offset (8 bit): opcode
1077 * offset + 1 (8 bit): "sub" opcode
1078 * offset + 2 (8 bit): unknown
1079 *
1080 */
1081
1082 struct bit_displayport_encoder_table *dpe = NULL;
1083 struct dcb_entry *dcb = bios->display.output;
1084 struct drm_device *dev = bios->dev;
1085 uint8_t cond = bios->data[offset + 1];
1086 int dummy;
1087
1088 BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond);
1089
1090 if (!iexec->execute)
1091 return 3;
1092
1093 dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
1094 if (!dpe) {
1095 NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
1096 return -EINVAL;
1097 }
1098
1099 switch (cond) {
1100 case 0:
1101 {
1102 struct dcb_connector_table_entry *ent =
1103 &bios->dcb.connector.entry[dcb->connector];
1104
1105 if (ent->type != DCB_CONNECTOR_eDP)
1106 iexec->execute = false;
1107 }
1108 break;
1109 case 1:
1110 case 2:
1111 if (!(dpe->unknown & cond))
1112 iexec->execute = false;
1113 break;
1114 case 5:
1115 {
1116 struct nouveau_i2c_chan *auxch;
1117 int ret;
1118
1119 auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index);
1120 if (!auxch)
1121 return -ENODEV;
1122
1123 ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1);
1124 if (ret)
1125 return ret;
1126
1127 if (cond & 1)
1128 iexec->execute = false;
1129 }
1130 break;
1131 default:
1132 NV_WARN(dev, "0x%04X: unknown INIT_3A op: %d\n", offset, cond);
1133 break;
1134 }
1135
1136 if (iexec->execute)
1137 BIOSLOG(bios, "0x%04X: continuing to execute\n", offset);
1138 else
1139 BIOSLOG(bios, "0x%04X: skipping following commands\n", offset);
1140
1141 return 3;
1142}
1143
1144static int
1145init_op_3b(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
1146{
1147 /*
1148 * INIT_3B opcode: 0x3B ('')
1149 *
1150 * offset (8 bit): opcode
1151 * offset + 1 (8 bit): crtc index
1152 *
1153 */
1154
1155 uint8_t or = ffs(bios->display.output->or) - 1;
1156 uint8_t index = bios->data[offset + 1];
1157 uint8_t data;
1158
1159 if (!iexec->execute)
1160 return 2;
1161
1162 data = bios_idxprt_rd(bios, 0x3d4, index);
1163 bios_idxprt_wr(bios, 0x3d4, index, data & ~(1 << or));
1164 return 2;
1165}
1166
1167static int
1168init_op_3c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
1169{
1170 /*
1171 * INIT_3C opcode: 0x3C ('')
1172 *
1173 * offset (8 bit): opcode
1174 * offset + 1 (8 bit): crtc index
1175 *
1176 */
1177
1178 uint8_t or = ffs(bios->display.output->or) - 1;
1179 uint8_t index = bios->data[offset + 1];
1180 uint8_t data;
1181
1182 if (!iexec->execute)
1183 return 2;
1184
1185 data = bios_idxprt_rd(bios, 0x3d4, index);
1186 bios_idxprt_wr(bios, 0x3d4, index, data | (1 << or));
1187 return 2;
1188}
1189
1190static int
1070init_idx_addr_latched(struct nvbios *bios, uint16_t offset, 1191init_idx_addr_latched(struct nvbios *bios, uint16_t offset,
1071 struct init_exec *iexec) 1192 struct init_exec *iexec)
1072{ 1193{
@@ -2934,6 +3055,9 @@ static struct init_tbl_entry itbl_entry[] = {
2934 { "INIT_COPY" , 0x37, init_copy }, 3055 { "INIT_COPY" , 0x37, init_copy },
2935 { "INIT_NOT" , 0x38, init_not }, 3056 { "INIT_NOT" , 0x38, init_not },
2936 { "INIT_IO_FLAG_CONDITION" , 0x39, init_io_flag_condition }, 3057 { "INIT_IO_FLAG_CONDITION" , 0x39, init_io_flag_condition },
3058 { "INIT_DP_CONDITION" , 0x3A, init_dp_condition },
3059 { "INIT_OP_3B" , 0x3B, init_op_3b },
3060 { "INIT_OP_3C" , 0x3C, init_op_3c },
2937 { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, init_idx_addr_latched }, 3061 { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, init_idx_addr_latched },
2938 { "INIT_IO_RESTRICT_PLL2" , 0x4A, init_io_restrict_pll2 }, 3062 { "INIT_IO_RESTRICT_PLL2" , 0x4A, init_io_restrict_pll2 },
2939 { "INIT_PLL2" , 0x4B, init_pll2 }, 3063 { "INIT_PLL2" , 0x4B, init_pll2 },