diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-08-05 00:07:04 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 02:11:18 -0400 |
commit | 5f1800bd8a774f773e3be71702da7ec77188b283 (patch) | |
tree | 00ee052cf8f838434c92a24409e5bbfb6e8c807f | |
parent | 721b0821ad8fea80ea1b6b84cb9646881959e662 (diff) |
drm/nouveau/dp: return master dp table pointer too when looking up encoder
Will need to be able to distinguish 2.0/2.1 from 3.0 soon. Also, move
the vbios parsing to nouveau_dp where it belongs.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 53 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dp.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 3 |
4 files changed, 66 insertions, 70 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 73b590a71949..58b2535e3b6b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -1182,18 +1182,16 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1182 | struct dcb_entry *dcb = bios->display.output; | 1182 | struct dcb_entry *dcb = bios->display.output; |
1183 | struct drm_device *dev = bios->dev; | 1183 | struct drm_device *dev = bios->dev; |
1184 | uint8_t cond = bios->data[offset + 1]; | 1184 | uint8_t cond = bios->data[offset + 1]; |
1185 | uint8_t *table, headerlen; | 1185 | uint8_t *table, *entry; |
1186 | 1186 | ||
1187 | BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); | 1187 | BIOSLOG(bios, "0x%04X: subop 0x%02X\n", offset, cond); |
1188 | 1188 | ||
1189 | if (!iexec->execute) | 1189 | if (!iexec->execute) |
1190 | return 3; | 1190 | return 3; |
1191 | 1191 | ||
1192 | table = nouveau_bios_dp_table(dev, dcb, &headerlen); | 1192 | table = nouveau_dp_bios_data(dev, dcb, &entry); |
1193 | if (!table) { | 1193 | if (!table) |
1194 | NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); | ||
1195 | return 3; | 1194 | return 3; |
1196 | } | ||
1197 | 1195 | ||
1198 | switch (cond) { | 1196 | switch (cond) { |
1199 | case 0: | 1197 | case 0: |
@@ -1207,7 +1205,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1207 | break; | 1205 | break; |
1208 | case 1: | 1206 | case 1: |
1209 | case 2: | 1207 | case 2: |
1210 | if (!(table[5] & cond)) | 1208 | if (!(entry[5] & cond)) |
1211 | iexec->execute = false; | 1209 | iexec->execute = false; |
1212 | break; | 1210 | break; |
1213 | case 5: | 1211 | case 5: |
@@ -4454,40 +4452,6 @@ bios_encoder_match(struct dcb_entry *dcb, u32 hash) | |||
4454 | } | 4452 | } |
4455 | } | 4453 | } |
4456 | 4454 | ||
4457 | void * | ||
4458 | nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, | ||
4459 | uint8_t *headerlen) | ||
4460 | { | ||
4461 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
4462 | struct nvbios *bios = &dev_priv->vbios; | ||
4463 | uint8_t *table, *entry; | ||
4464 | int i; | ||
4465 | |||
4466 | if (!bios->display.dp_table_ptr) { | ||
4467 | NV_ERROR(dev, "No pointer to DisplayPort table\n"); | ||
4468 | return NULL; | ||
4469 | } | ||
4470 | table = &bios->data[bios->display.dp_table_ptr]; | ||
4471 | |||
4472 | if (table[0] != 0x20 && table[0] != 0x21) { | ||
4473 | NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n", | ||
4474 | table[0]); | ||
4475 | return NULL; | ||
4476 | } | ||
4477 | |||
4478 | entry = table + table[1]; | ||
4479 | for (i = 0; i < table[3]; i++, entry += table[2]) { | ||
4480 | u8 *etable = ROMPTR(bios, entry[0]); | ||
4481 | if (etable && bios_encoder_match(dcbent, ROM32(etable[0]))) { | ||
4482 | *headerlen = table[4]; | ||
4483 | return etable; | ||
4484 | } | ||
4485 | } | ||
4486 | |||
4487 | NV_ERROR(dev, "DisplayPort encoder table not found\n"); | ||
4488 | return NULL; | ||
4489 | } | ||
4490 | |||
4491 | int | 4455 | int |
4492 | nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | 4456 | nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, |
4493 | struct dcb_entry *dcbent, int crtc) | 4457 | struct dcb_entry *dcbent, int crtc) |
@@ -5503,14 +5467,6 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, | |||
5503 | return 0; | 5467 | return 0; |
5504 | } | 5468 | } |
5505 | 5469 | ||
5506 | static int | ||
5507 | parse_bit_displayport_tbl_entry(struct drm_device *dev, struct nvbios *bios, | ||
5508 | struct bit_entry *bitentry) | ||
5509 | { | ||
5510 | bios->display.dp_table_ptr = ROM16(bios->data[bitentry->offset]); | ||
5511 | return 0; | ||
5512 | } | ||
5513 | |||
5514 | struct bit_table { | 5470 | struct bit_table { |
5515 | const char id; | 5471 | const char id; |
5516 | int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); | 5472 | int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); |
@@ -5584,7 +5540,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) | |||
5584 | parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); | 5540 | parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); |
5585 | parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); | 5541 | parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); |
5586 | parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); | 5542 | parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); |
5587 | parse_bit_table(bios, bitoffset, &BIT_TABLE('d', displayport)); | ||
5588 | 5543 | ||
5589 | return 0; | 5544 | return 0; |
5590 | } | 5545 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index b28f0bceaed4..8adb69e4a6b1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -291,7 +291,6 @@ struct nvbios { | |||
291 | struct dcb_entry *output; | 291 | struct dcb_entry *output; |
292 | int crtc; | 292 | int crtc; |
293 | uint16_t script_table_ptr; | 293 | uint16_t script_table_ptr; |
294 | uint16_t dp_table_ptr; | ||
295 | } display; | 294 | } display; |
296 | 295 | ||
297 | struct { | 296 | struct { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index d3552e766647..25ecb776c7bc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -270,11 +270,57 @@ nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) | |||
270 | unk); | 270 | unk); |
271 | } | 271 | } |
272 | 272 | ||
273 | u8 * | ||
274 | nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) | ||
275 | { | ||
276 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
277 | struct nvbios *bios = &dev_priv->vbios; | ||
278 | struct bit_entry d; | ||
279 | u8 *table; | ||
280 | int i; | ||
281 | |||
282 | if (bit_table(dev, 'd', &d)) { | ||
283 | NV_ERROR(dev, "BIT 'd' table not found\n"); | ||
284 | return NULL; | ||
285 | } | ||
286 | |||
287 | if (d.version != 1) { | ||
288 | NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); | ||
289 | return NULL; | ||
290 | } | ||
291 | |||
292 | table = ROMPTR(bios, d.data[0]); | ||
293 | if (!table) { | ||
294 | NV_ERROR(dev, "displayport table pointer invalid\n"); | ||
295 | return NULL; | ||
296 | } | ||
297 | |||
298 | switch (table[0]) { | ||
299 | case 0x20: | ||
300 | case 0x21: | ||
301 | break; | ||
302 | default: | ||
303 | NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); | ||
304 | return NULL; | ||
305 | } | ||
306 | |||
307 | for (i = 0; i < table[3]; i++) { | ||
308 | *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); | ||
309 | if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) | ||
310 | return table; | ||
311 | } | ||
312 | |||
313 | NV_ERROR(dev, "displayport encoder table not found\n"); | ||
314 | return NULL; | ||
315 | } | ||
316 | |||
273 | /****************************************************************************** | 317 | /****************************************************************************** |
274 | * link training | 318 | * link training |
275 | *****************************************************************************/ | 319 | *****************************************************************************/ |
276 | struct dp_state { | 320 | struct dp_state { |
277 | struct dcb_entry *dcb; | 321 | struct dcb_entry *dcb; |
322 | u8 *table; | ||
323 | u8 *entry; | ||
278 | int auxch; | 324 | int auxch; |
279 | int crtc; | 325 | int crtc; |
280 | int or; | 326 | int or; |
@@ -291,7 +337,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) | |||
291 | { | 337 | { |
292 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 338 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
293 | int or = dp->or, link = dp->link; | 339 | int or = dp->or, link = dp->link; |
294 | u8 *bios, headerlen, sink[2]; | 340 | u8 *entry, sink[2]; |
295 | u32 dp_ctrl; | 341 | u32 dp_ctrl; |
296 | 342 | ||
297 | NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); | 343 | NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); |
@@ -312,12 +358,12 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) | |||
312 | * table, that has (among other things) pointers to more scripts that | 358 | * table, that has (among other things) pointers to more scripts that |
313 | * need to be executed, this time depending on link speed. | 359 | * need to be executed, this time depending on link speed. |
314 | */ | 360 | */ |
315 | bios = nouveau_bios_dp_table(dev, dp->dcb, &headerlen); | 361 | entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); |
316 | if (bios && (bios = ROMPTR(&dev_priv->vbios, bios[10]))) { | 362 | if (entry) { |
317 | while (dp->link_bw < (ROM16(bios[0]) * 10)) | 363 | while (dp->link_bw < (ROM16(entry[0]) * 10)) |
318 | bios += 4; | 364 | entry += 4; |
319 | 365 | ||
320 | nouveau_bios_run_init_table(dev, ROM16(bios[2]), dp->dcb, dp->crtc); | 366 | nouveau_bios_run_init_table(dev, ROM16(entry[2]), dp->dcb, dp->crtc); |
321 | } | 367 | } |
322 | 368 | ||
323 | /* configure lane count on the source */ | 369 | /* configure lane count on the source */ |
@@ -357,7 +403,6 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) | |||
357 | { | 403 | { |
358 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 404 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
359 | u32 mask = 0, drv = 0, pre = 0, unk = 0; | 405 | u32 mask = 0, drv = 0, pre = 0, unk = 0; |
360 | u8 *bios, *last, headerlen; | ||
361 | const u8 *shifts; | 406 | const u8 *shifts; |
362 | int link = dp->link; | 407 | int link = dp->link; |
363 | int or = dp->or; | 408 | int or = dp->or; |
@@ -368,11 +413,10 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) | |||
368 | else | 413 | else |
369 | shifts = nvaf_lane_map; | 414 | shifts = nvaf_lane_map; |
370 | 415 | ||
371 | bios = nouveau_bios_dp_table(dev, dp->dcb, &headerlen); | ||
372 | last = bios + headerlen + (bios[4] * 5); | ||
373 | for (i = 0; i < dp->link_nr; i++) { | 416 | for (i = 0; i < dp->link_nr; i++) { |
374 | u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; | 417 | u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; |
375 | u8 *conf = bios + headerlen; | 418 | u8 *conf = dp->entry + dp->table[4]; |
419 | u8 *last = conf + (dp->entry[4] * dp->table[5]); | ||
376 | 420 | ||
377 | while (conf < last) { | 421 | while (conf < last) { |
378 | if ((lane & 3) == conf[0] && | 422 | if ((lane & 3) == conf[0] && |
@@ -500,14 +544,13 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) | |||
500 | const u32 bw_list[] = { 270000, 162000, 0 }; | 544 | const u32 bw_list[] = { 270000, 162000, 0 }; |
501 | const u32 *link_bw = bw_list; | 545 | const u32 *link_bw = bw_list; |
502 | struct dp_state dp; | 546 | struct dp_state dp; |
503 | u8 *bios, headerlen; | ||
504 | 547 | ||
505 | auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | 548 | auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); |
506 | if (!auxch) | 549 | if (!auxch) |
507 | return false; | 550 | return false; |
508 | 551 | ||
509 | bios = nouveau_bios_dp_table(dev, nv_encoder->dcb, &headerlen); | 552 | dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); |
510 | if (!bios) | 553 | if (!dp.table) |
511 | return -EINVAL; | 554 | return -EINVAL; |
512 | 555 | ||
513 | dp.dcb = nv_encoder->dcb; | 556 | dp.dcb = nv_encoder->dcb; |
@@ -524,16 +567,16 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) | |||
524 | pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); | 567 | pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); |
525 | 568 | ||
526 | /* enable down-spreading, if possible */ | 569 | /* enable down-spreading, if possible */ |
527 | if (headerlen >= 16) { | 570 | if (dp.table[1] >= 16) { |
528 | u16 script = ROM16(bios[14]); | 571 | u16 script = ROM16(dp.entry[14]); |
529 | if (nv_encoder->dp.dpcd[3] & 1) | 572 | if (nv_encoder->dp.dpcd[3] & 1) |
530 | script = ROM16(bios[12]); | 573 | script = ROM16(dp.entry[12]); |
531 | 574 | ||
532 | nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); | 575 | nouveau_bios_run_init_table(dev, script, dp.dcb, dp.crtc); |
533 | } | 576 | } |
534 | 577 | ||
535 | /* execute pre-train script from vbios */ | 578 | /* execute pre-train script from vbios */ |
536 | nouveau_bios_run_init_table(dev, ROM16(bios[6]), dp.dcb, dp.crtc); | 579 | nouveau_bios_run_init_table(dev, ROM16(dp.entry[6]), dp.dcb, dp.crtc); |
537 | 580 | ||
538 | /* start off at highest link rate supported by encoder and display */ | 581 | /* start off at highest link rate supported by encoder and display */ |
539 | while (*link_bw > nv_encoder->dp.link_bw) | 582 | while (*link_bw > nv_encoder->dp.link_bw) |
@@ -567,7 +610,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) | |||
567 | dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); | 610 | dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); |
568 | 611 | ||
569 | /* execute post-train script from vbios */ | 612 | /* execute post-train script from vbios */ |
570 | nouveau_bios_run_init_table(dev, ROM16(bios[8]), dp.dcb, dp.crtc); | 613 | nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); |
571 | 614 | ||
572 | /* re-enable hotplug detect */ | 615 | /* re-enable hotplug detect */ |
573 | pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); | 616 | pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index d269b7ba45cc..ecaa4ffbeab9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -1080,8 +1080,6 @@ extern int get_pll_limits(struct drm_device *, uint32_t limit_match, | |||
1080 | struct pll_lims *); | 1080 | struct pll_lims *); |
1081 | extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, | 1081 | extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, |
1082 | struct dcb_entry *, int crtc); | 1082 | struct dcb_entry *, int crtc); |
1083 | extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, | ||
1084 | u8 *headerlen); | ||
1085 | extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); | 1083 | extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); |
1086 | extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); | 1084 | extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); |
1087 | extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, | 1085 | extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, |
@@ -1103,6 +1101,7 @@ int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, | |||
1103 | bool nouveau_dp_detect(struct drm_encoder *); | 1101 | bool nouveau_dp_detect(struct drm_encoder *); |
1104 | bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); | 1102 | bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); |
1105 | void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); | 1103 | void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); |
1104 | u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); | ||
1106 | 1105 | ||
1107 | /* nv04_fb.c */ | 1106 | /* nv04_fb.c */ |
1108 | extern int nv04_fb_init(struct drm_device *); | 1107 | extern int nv04_fb_init(struct drm_device *); |