aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-08-05 21:21:18 -0400
committerDave Airlie <airlied@redhat.com>2010-08-09 20:46:50 -0400
commit26b5bc986423cf3887e09188cb662ed651c5374d (patch)
tree568934e975f31029460b8e90f22580bdb84b19ec /drivers/gpu
parent179e8078a768be8c18539bebe44dd94447142ccf (diff)
drm/radeon/kms: add support for router objects
router objects are found on systems that use a mux to control ddc line to connector routing or to control the actual clock and data routing from the chip to the connectors. This patch implements ddc line routing. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c94
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c14
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c29
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h13
5 files changed, 147 insertions, 15 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index a841adead1a1..dc9102fc7ed5 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -48,7 +48,8 @@ radeon_add_atom_connector(struct drm_device *dev,
48 struct radeon_i2c_bus_rec *i2c_bus, 48 struct radeon_i2c_bus_rec *i2c_bus,
49 bool linkb, uint32_t igp_lane_info, 49 bool linkb, uint32_t igp_lane_info,
50 uint16_t connector_object_id, 50 uint16_t connector_object_id,
51 struct radeon_hpd *hpd); 51 struct radeon_hpd *hpd,
52 struct radeon_router *router);
52 53
53/* from radeon_legacy_encoder.c */ 54/* from radeon_legacy_encoder.c */
54extern void 55extern void
@@ -460,13 +461,15 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
460 u16 size, data_offset; 461 u16 size, data_offset;
461 u8 frev, crev; 462 u8 frev, crev;
462 ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 463 ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
464 ATOM_OBJECT_TABLE *router_obj;
463 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 465 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
464 ATOM_OBJECT_HEADER *obj_header; 466 ATOM_OBJECT_HEADER *obj_header;
465 int i, j, path_size, device_support; 467 int i, j, k, path_size, device_support;
466 int connector_type; 468 int connector_type;
467 u16 igp_lane_info, conn_id, connector_object_id; 469 u16 igp_lane_info, conn_id, connector_object_id;
468 bool linkb; 470 bool linkb;
469 struct radeon_i2c_bus_rec ddc_bus; 471 struct radeon_i2c_bus_rec ddc_bus;
472 struct radeon_router router;
470 struct radeon_gpio_rec gpio; 473 struct radeon_gpio_rec gpio;
471 struct radeon_hpd hpd; 474 struct radeon_hpd hpd;
472 475
@@ -476,6 +479,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
476 if (crev < 2) 479 if (crev < 2)
477 return false; 480 return false;
478 481
482 router.valid = false;
483
479 obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); 484 obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset);
480 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) 485 path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *)
481 (ctx->bios + data_offset + 486 (ctx->bios + data_offset +
@@ -483,6 +488,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
483 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) 488 con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *)
484 (ctx->bios + data_offset + 489 (ctx->bios + data_offset +
485 le16_to_cpu(obj_header->usConnectorObjectTableOffset)); 490 le16_to_cpu(obj_header->usConnectorObjectTableOffset));
491 router_obj = (ATOM_OBJECT_TABLE *)
492 (ctx->bios + data_offset +
493 le16_to_cpu(obj_header->usRouterObjectTableOffset));
486 device_support = le16_to_cpu(obj_header->usDeviceSupport); 494 device_support = le16_to_cpu(obj_header->usDeviceSupport);
487 495
488 path_size = 0; 496 path_size = 0;
@@ -569,33 +577,86 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
569 if (connector_type == DRM_MODE_CONNECTOR_Unknown) 577 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
570 continue; 578 continue;
571 579
572 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); 580 for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
573 j++) { 581 uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
574 uint8_t enc_obj_id, enc_obj_num, enc_obj_type;
575 582
576 enc_obj_id = 583 grph_obj_id =
577 (le16_to_cpu(path->usGraphicObjIds[j]) & 584 (le16_to_cpu(path->usGraphicObjIds[j]) &
578 OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; 585 OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
579 enc_obj_num = 586 grph_obj_num =
580 (le16_to_cpu(path->usGraphicObjIds[j]) & 587 (le16_to_cpu(path->usGraphicObjIds[j]) &
581 ENUM_ID_MASK) >> ENUM_ID_SHIFT; 588 ENUM_ID_MASK) >> ENUM_ID_SHIFT;
582 enc_obj_type = 589 grph_obj_type =
583 (le16_to_cpu(path->usGraphicObjIds[j]) & 590 (le16_to_cpu(path->usGraphicObjIds[j]) &
584 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; 591 OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
585 592
586 /* FIXME: add support for router objects */ 593 if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) {
587 if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { 594 if (grph_obj_num == 2)
588 if (enc_obj_num == 2)
589 linkb = true; 595 linkb = true;
590 else 596 else
591 linkb = false; 597 linkb = false;
592 598
593 radeon_add_atom_encoder(dev, 599 radeon_add_atom_encoder(dev,
594 enc_obj_id, 600 grph_obj_id,
595 le16_to_cpu 601 le16_to_cpu
596 (path-> 602 (path->
597 usDeviceTag)); 603 usDeviceTag));
598 604
605 } else if (grph_obj_type == GRAPH_OBJECT_TYPE_ROUTER) {
606 router.valid = false;
607 for (k = 0; k < router_obj->ucNumberOfObjects; k++) {
608 u16 router_obj_id = le16_to_cpu(router_obj->asObjects[j].usObjectID);
609 if (le16_to_cpu(path->usGraphicObjIds[j]) == router_obj_id) {
610 ATOM_COMMON_RECORD_HEADER *record = (ATOM_COMMON_RECORD_HEADER *)
611 (ctx->bios + data_offset +
612 le16_to_cpu(router_obj->asObjects[k].usRecordOffset));
613 ATOM_I2C_RECORD *i2c_record;
614 ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
615 ATOM_ROUTER_DDC_PATH_SELECT_RECORD *ddc_path;
616 ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *router_src_dst_table =
617 (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *)
618 (ctx->bios + data_offset +
619 le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset));
620 int enum_id;
621
622 router.router_id = router_obj_id;
623 for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst;
624 enum_id++) {
625 if (le16_to_cpu(path->usConnObjectId) ==
626 le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id]))
627 break;
628 }
629
630 while (record->ucRecordType > 0 &&
631 record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
632 switch (record->ucRecordType) {
633 case ATOM_I2C_RECORD_TYPE:
634 i2c_record =
635 (ATOM_I2C_RECORD *)
636 record;
637 i2c_config =
638 (ATOM_I2C_ID_CONFIG_ACCESS *)
639 &i2c_record->sucI2cId;
640 router.i2c_info =
641 radeon_lookup_i2c_gpio(rdev,
642 i2c_config->
643 ucAccess);
644 router.i2c_addr = i2c_record->ucI2CAddr >> 1;
645 break;
646 case ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE:
647 ddc_path = (ATOM_ROUTER_DDC_PATH_SELECT_RECORD *)
648 record;
649 router.valid = true;
650 router.mux_type = ddc_path->ucMuxType;
651 router.mux_control_pin = ddc_path->ucMuxControlPin;
652 router.mux_state = ddc_path->ucMuxState[enum_id];
653 break;
654 }
655 record = (ATOM_COMMON_RECORD_HEADER *)
656 ((char *)record + record->ucRecordSize);
657 }
658 }
659 }
599 } 660 }
600 } 661 }
601 662
@@ -675,7 +736,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
675 connector_type, &ddc_bus, 736 connector_type, &ddc_bus,
676 linkb, igp_lane_info, 737 linkb, igp_lane_info,
677 connector_object_id, 738 connector_object_id,
678 &hpd); 739 &hpd,
740 &router);
679 741
680 } 742 }
681 } 743 }
@@ -752,6 +814,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
752 int i, j, max_device; 814 int i, j, max_device;
753 struct bios_connector *bios_connectors; 815 struct bios_connector *bios_connectors;
754 size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; 816 size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE;
817 struct radeon_router router;
818
819 router.valid = false;
755 820
756 bios_connectors = kzalloc(bc_size, GFP_KERNEL); 821 bios_connectors = kzalloc(bc_size, GFP_KERNEL);
757 if (!bios_connectors) 822 if (!bios_connectors)
@@ -923,7 +988,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
923 &bios_connectors[i].ddc_bus, 988 &bios_connectors[i].ddc_bus,
924 false, 0, 989 false, 0,
925 connector_object_id, 990 connector_object_id,
926 &bios_connectors[i].hpd); 991 &bios_connectors[i].hpd,
992 &router);
927 } 993 }
928 } 994 }
929 995
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 185a6d962b72..47c4b276d30c 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1040,7 +1040,8 @@ radeon_add_atom_connector(struct drm_device *dev,
1040 bool linkb, 1040 bool linkb,
1041 uint32_t igp_lane_info, 1041 uint32_t igp_lane_info,
1042 uint16_t connector_object_id, 1042 uint16_t connector_object_id,
1043 struct radeon_hpd *hpd) 1043 struct radeon_hpd *hpd,
1044 struct radeon_router *router)
1044{ 1045{
1045 struct radeon_device *rdev = dev->dev_private; 1046 struct radeon_device *rdev = dev->dev_private;
1046 struct drm_connector *connector; 1047 struct drm_connector *connector;
@@ -1065,6 +1066,11 @@ radeon_add_atom_connector(struct drm_device *dev,
1065 radeon_connector->shared_ddc = true; 1066 radeon_connector->shared_ddc = true;
1066 shared_ddc = true; 1067 shared_ddc = true;
1067 } 1068 }
1069 if (radeon_connector->router_bus && router->valid &&
1070 (radeon_connector->router.router_id == router->router_id)) {
1071 radeon_connector->shared_ddc = false;
1072 shared_ddc = false;
1073 }
1068 } 1074 }
1069 } 1075 }
1070 1076
@@ -1079,6 +1085,12 @@ radeon_add_atom_connector(struct drm_device *dev,
1079 radeon_connector->shared_ddc = shared_ddc; 1085 radeon_connector->shared_ddc = shared_ddc;
1080 radeon_connector->connector_object_id = connector_object_id; 1086 radeon_connector->connector_object_id = connector_object_id;
1081 radeon_connector->hpd = *hpd; 1087 radeon_connector->hpd = *hpd;
1088 radeon_connector->router = *router;
1089 if (router->valid) {
1090 radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
1091 if (!radeon_connector->router_bus)
1092 goto failed;
1093 }
1082 switch (connector_type) { 1094 switch (connector_type) {
1083 case DRM_MODE_CONNECTOR_VGA: 1095 case DRM_MODE_CONNECTOR_VGA:
1084 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); 1096 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 52ac08e9a045..d49a14891f83 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -319,6 +319,10 @@ static void radeon_print_display_setup(struct drm_device *dev)
319 radeon_connector->ddc_bus->rec.en_data_reg, 319 radeon_connector->ddc_bus->rec.en_data_reg,
320 radeon_connector->ddc_bus->rec.y_clk_reg, 320 radeon_connector->ddc_bus->rec.y_clk_reg,
321 radeon_connector->ddc_bus->rec.y_data_reg); 321 radeon_connector->ddc_bus->rec.y_data_reg);
322 if (radeon_connector->router_bus)
323 DRM_INFO(" DDC Router 0x%x/0x%x\n",
324 radeon_connector->router.mux_control_pin,
325 radeon_connector->router.mux_state);
322 } else { 326 } else {
323 if (connector->connector_type == DRM_MODE_CONNECTOR_VGA || 327 if (connector->connector_type == DRM_MODE_CONNECTOR_VGA ||
324 connector->connector_type == DRM_MODE_CONNECTOR_DVII || 328 connector->connector_type == DRM_MODE_CONNECTOR_DVII ||
@@ -395,6 +399,10 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
395 struct radeon_device *rdev = dev->dev_private; 399 struct radeon_device *rdev = dev->dev_private;
396 int ret = 0; 400 int ret = 0;
397 401
402 /* on hw with routers, select right port */
403 if (radeon_connector->router.valid)
404 radeon_router_select_port(radeon_connector);
405
398 if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || 406 if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
399 (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { 407 (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) {
400 struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; 408 struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
@@ -425,6 +433,10 @@ static int radeon_ddc_dump(struct drm_connector *connector)
425 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 433 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
426 int ret = 0; 434 int ret = 0;
427 435
436 /* on hw with routers, select right port */
437 if (radeon_connector->router.valid)
438 radeon_router_select_port(radeon_connector);
439
428 if (!radeon_connector->ddc_bus) 440 if (!radeon_connector->ddc_bus)
429 return -1; 441 return -1;
430 edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); 442 edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index e71f2eb02ee2..bfd2ce5f5372 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -52,6 +52,10 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
52 } 52 }
53 }; 53 };
54 54
55 /* on hw with routers, select right port */
56 if (radeon_connector->router.valid)
57 radeon_router_select_port(radeon_connector);
58
55 ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); 59 ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
56 if (ret == 2) 60 if (ret == 2)
57 return true; 61 return true;
@@ -1073,3 +1077,28 @@ void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus,
1073 addr, val); 1077 addr, val);
1074} 1078}
1075 1079
1080/* router switching */
1081void radeon_router_select_port(struct radeon_connector *radeon_connector)
1082{
1083 u8 val;
1084
1085 if (!radeon_connector->router.valid)
1086 return;
1087
1088 radeon_i2c_get_byte(radeon_connector->router_bus,
1089 radeon_connector->router.i2c_addr,
1090 0x3, &val);
1091 val &= radeon_connector->router.mux_control_pin;
1092 radeon_i2c_put_byte(radeon_connector->router_bus,
1093 radeon_connector->router.i2c_addr,
1094 0x3, val);
1095 radeon_i2c_get_byte(radeon_connector->router_bus,
1096 radeon_connector->router.i2c_addr,
1097 0x1, &val);
1098 val &= radeon_connector->router.mux_control_pin;
1099 val |= radeon_connector->router.mux_state;
1100 radeon_i2c_put_byte(radeon_connector->router_bus,
1101 radeon_connector->router.i2c_addr,
1102 0x1, val);
1103}
1104
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 02d4e2af6180..5bbc086b9267 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -400,6 +400,16 @@ struct radeon_hpd {
400 struct radeon_gpio_rec gpio; 400 struct radeon_gpio_rec gpio;
401}; 401};
402 402
403struct radeon_router {
404 bool valid;
405 u32 router_id;
406 struct radeon_i2c_bus_rec i2c_info;
407 u8 i2c_addr;
408 u8 mux_type;
409 u8 mux_control_pin;
410 u8 mux_state;
411};
412
403struct radeon_connector { 413struct radeon_connector {
404 struct drm_connector base; 414 struct drm_connector base;
405 uint32_t connector_id; 415 uint32_t connector_id;
@@ -415,6 +425,8 @@ struct radeon_connector {
415 bool dac_load_detect; 425 bool dac_load_detect;
416 uint16_t connector_object_id; 426 uint16_t connector_object_id;
417 struct radeon_hpd hpd; 427 struct radeon_hpd hpd;
428 struct radeon_router router;
429 struct radeon_i2c_chan *router_bus;
418}; 430};
419 431
420struct radeon_framebuffer { 432struct radeon_framebuffer {
@@ -471,6 +483,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
471 u8 slave_addr, 483 u8 slave_addr,
472 u8 addr, 484 u8 addr,
473 u8 val); 485 u8 val);
486extern void radeon_router_select_port(struct radeon_connector *radeon_connector);
474extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); 487extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
475extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); 488extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
476 489