aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_atombios.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-12-04 14:45:27 -0500
committerDave Airlie <airlied@redhat.com>2009-12-07 19:46:28 -0500
commiteed45b30cd1423f8dc10b4312700773cac13c1c8 (patch)
treef47c667d753ce1fc2abd116449ca7c2ce290cecf /drivers/gpu/drm/radeon/radeon_atombios.c
parent53c1e09fea4cf3fc0ec1f735a5fcab78c43cb55d (diff)
drm/radeon/kms: get HPD info for connectors
This populates the connectors with HPD (Hot Plug Detect) information. This will be used in subsequent patches for automatic digital monitor connect/disconnect handling. Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_atombios.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c190
1 files changed, 149 insertions, 41 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 87bf6b9d10a4..d7b0feb7d47f 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -47,7 +47,8 @@ radeon_add_atom_connector(struct drm_device *dev,
47 int connector_type, 47 int connector_type,
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 52
52/* from radeon_legacy_encoder.c */ 53/* from radeon_legacy_encoder.c */
53extern void 54extern void
@@ -60,10 +61,9 @@ union atom_supported_devices {
60 struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; 61 struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
61}; 62};
62 63
63static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *dev, 64static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
64 uint8_t id) 65 uint8_t id)
65{ 66{
66 struct radeon_device *rdev = dev->dev_private;
67 struct atom_context *ctx = rdev->mode_info.atom_context; 67 struct atom_context *ctx = rdev->mode_info.atom_context;
68 ATOM_GPIO_I2C_ASSIGMENT *gpio; 68 ATOM_GPIO_I2C_ASSIGMENT *gpio;
69 struct radeon_i2c_bus_rec i2c; 69 struct radeon_i2c_bus_rec i2c;
@@ -114,11 +114,80 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device *de
114 return i2c; 114 return i2c;
115} 115}
116 116
117static inline struct radeon_gpio_rec radeon_lookup_gpio(struct radeon_device *rdev,
118 u8 id)
119{
120 struct atom_context *ctx = rdev->mode_info.atom_context;
121 struct radeon_gpio_rec gpio;
122 int index = GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT);
123 struct _ATOM_GPIO_PIN_LUT *gpio_info;
124 ATOM_GPIO_PIN_ASSIGNMENT *pin;
125 u16 data_offset, size;
126 int i, num_indices;
127
128 memset(&gpio, 0, sizeof(struct radeon_gpio_rec));
129 gpio.valid = false;
130
131 atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset);
132
133 gpio_info = (struct _ATOM_GPIO_PIN_LUT *)(ctx->bios + data_offset);
134
135 num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / sizeof(ATOM_GPIO_PIN_ASSIGNMENT);
136
137 for (i = 0; i < num_indices; i++) {
138 pin = &gpio_info->asGPIO_Pin[i];
139 if (id == pin->ucGPIO_ID) {
140 gpio.id = pin->ucGPIO_ID;
141 gpio.reg = pin->usGpioPin_AIndex * 4;
142 gpio.mask = (1 << pin->ucGpioPinBitShift);
143 gpio.valid = true;
144 break;
145 }
146 }
147
148 return gpio;
149}
150
151static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device *rdev,
152 struct radeon_gpio_rec *gpio)
153{
154 struct radeon_hpd hpd;
155 hpd.gpio = *gpio;
156 if (gpio->reg == AVIVO_DC_GPIO_HPD_A) {
157 switch(gpio->mask) {
158 case (1 << 0):
159 hpd.hpd = RADEON_HPD_1;
160 break;
161 case (1 << 8):
162 hpd.hpd = RADEON_HPD_2;
163 break;
164 case (1 << 16):
165 hpd.hpd = RADEON_HPD_3;
166 break;
167 case (1 << 24):
168 hpd.hpd = RADEON_HPD_4;
169 break;
170 case (1 << 26):
171 hpd.hpd = RADEON_HPD_5;
172 break;
173 case (1 << 28):
174 hpd.hpd = RADEON_HPD_6;
175 break;
176 default:
177 hpd.hpd = RADEON_HPD_NONE;
178 break;
179 }
180 } else
181 hpd.hpd = RADEON_HPD_NONE;
182 return hpd;
183}
184
117static bool radeon_atom_apply_quirks(struct drm_device *dev, 185static bool radeon_atom_apply_quirks(struct drm_device *dev,
118 uint32_t supported_device, 186 uint32_t supported_device,
119 int *connector_type, 187 int *connector_type,
120 struct radeon_i2c_bus_rec *i2c_bus, 188 struct radeon_i2c_bus_rec *i2c_bus,
121 uint16_t *line_mux) 189 uint16_t *line_mux,
190 struct radeon_hpd *hpd)
122{ 191{
123 192
124 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ 193 /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
@@ -279,16 +348,19 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
279 struct radeon_mode_info *mode_info = &rdev->mode_info; 348 struct radeon_mode_info *mode_info = &rdev->mode_info;
280 struct atom_context *ctx = mode_info->atom_context; 349 struct atom_context *ctx = mode_info->atom_context;
281 int index = GetIndexIntoMasterTable(DATA, Object_Header); 350 int index = GetIndexIntoMasterTable(DATA, Object_Header);
282 uint16_t size, data_offset; 351 u16 size, data_offset;
283 uint8_t frev, crev, line_mux = 0; 352 u8 frev, crev;
284 ATOM_CONNECTOR_OBJECT_TABLE *con_obj; 353 ATOM_CONNECTOR_OBJECT_TABLE *con_obj;
285 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; 354 ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj;
286 ATOM_OBJECT_HEADER *obj_header; 355 ATOM_OBJECT_HEADER *obj_header;
287 int i, j, path_size, device_support; 356 int i, j, path_size, device_support;
288 int connector_type; 357 int connector_type;
289 uint16_t igp_lane_info, conn_id, connector_object_id; 358 u16 igp_lane_info, conn_id, connector_object_id;
290 bool linkb; 359 bool linkb;
291 struct radeon_i2c_bus_rec ddc_bus; 360 struct radeon_i2c_bus_rec ddc_bus;
361 struct radeon_gpio_rec gpio;
362 struct radeon_hpd hpd;
363
292 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); 364 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
293 365
294 if (data_offset == 0) 366 if (data_offset == 0)
@@ -414,10 +486,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
414 } 486 }
415 } 487 }
416 488
417 /* look up gpio for ddc */ 489 /* look up gpio for ddc, hpd */
418 if ((le16_to_cpu(path->usDeviceTag) & 490 if ((le16_to_cpu(path->usDeviceTag) &
419 (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) 491 (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) == 0) {
420 == 0) {
421 for (j = 0; j < con_obj->ucNumberOfObjects; j++) { 492 for (j = 0; j < con_obj->ucNumberOfObjects; j++) {
422 if (le16_to_cpu(path->usConnObjectId) == 493 if (le16_to_cpu(path->usConnObjectId) ==
423 le16_to_cpu(con_obj->asObjects[j]. 494 le16_to_cpu(con_obj->asObjects[j].
@@ -431,21 +502,31 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
431 asObjects[j]. 502 asObjects[j].
432 usRecordOffset)); 503 usRecordOffset));
433 ATOM_I2C_RECORD *i2c_record; 504 ATOM_I2C_RECORD *i2c_record;
505 ATOM_HPD_INT_RECORD *hpd_record;
506 hpd.hpd = RADEON_HPD_NONE;
434 507
435 while (record->ucRecordType > 0 508 while (record->ucRecordType > 0
436 && record-> 509 && record->
437 ucRecordType <= 510 ucRecordType <=
438 ATOM_MAX_OBJECT_RECORD_NUMBER) { 511 ATOM_MAX_OBJECT_RECORD_NUMBER) {
439 switch (record-> 512 switch (record->ucRecordType) {
440 ucRecordType) {
441 case ATOM_I2C_RECORD_TYPE: 513 case ATOM_I2C_RECORD_TYPE:
442 i2c_record = 514 i2c_record =
443 (ATOM_I2C_RECORD 515 (ATOM_I2C_RECORD *)
444 *) record; 516 record;
445 line_mux = 517 ddc_bus = radeon_lookup_i2c_gpio(rdev,
446 i2c_record-> 518 i2c_record->
447 sucI2cId. 519 sucI2cId.
448 bfI2C_LineMux; 520 bfI2C_LineMux);
521 break;
522 case ATOM_HPD_INT_RECORD_TYPE:
523 hpd_record =
524 (ATOM_HPD_INT_RECORD *)
525 record;
526 gpio = radeon_lookup_gpio(rdev,
527 hpd_record->ucHPDIntGPIOID);
528 hpd = radeon_atom_get_hpd_info_from_gpio(rdev, &gpio);
529 hpd.plugged_state = hpd_record->ucPlugged_PinState;
449 break; 530 break;
450 } 531 }
451 record = 532 record =
@@ -458,24 +539,16 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
458 break; 539 break;
459 } 540 }
460 } 541 }
461 } else 542 } else {
462 line_mux = 0; 543 hpd.hpd = RADEON_HPD_NONE;
463
464 if ((le16_to_cpu(path->usDeviceTag) ==
465 ATOM_DEVICE_TV1_SUPPORT)
466 || (le16_to_cpu(path->usDeviceTag) ==
467 ATOM_DEVICE_TV2_SUPPORT)
468 || (le16_to_cpu(path->usDeviceTag) ==
469 ATOM_DEVICE_CV_SUPPORT))
470 ddc_bus.valid = false; 544 ddc_bus.valid = false;
471 else 545 }
472 ddc_bus = radeon_lookup_gpio(dev, line_mux);
473 546
474 conn_id = le16_to_cpu(path->usConnObjectId); 547 conn_id = le16_to_cpu(path->usConnObjectId);
475 548
476 if (!radeon_atom_apply_quirks 549 if (!radeon_atom_apply_quirks
477 (dev, le16_to_cpu(path->usDeviceTag), &connector_type, 550 (dev, le16_to_cpu(path->usDeviceTag), &connector_type,
478 &ddc_bus, &conn_id)) 551 &ddc_bus, &conn_id, &hpd))
479 continue; 552 continue;
480 553
481 radeon_add_atom_connector(dev, 554 radeon_add_atom_connector(dev,
@@ -484,7 +557,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
484 usDeviceTag), 557 usDeviceTag),
485 connector_type, &ddc_bus, 558 connector_type, &ddc_bus,
486 linkb, igp_lane_info, 559 linkb, igp_lane_info,
487 connector_object_id); 560 connector_object_id,
561 &hpd);
488 562
489 } 563 }
490 } 564 }
@@ -539,6 +613,7 @@ struct bios_connector {
539 uint16_t devices; 613 uint16_t devices;
540 int connector_type; 614 int connector_type;
541 struct radeon_i2c_bus_rec ddc_bus; 615 struct radeon_i2c_bus_rec ddc_bus;
616 struct radeon_hpd hpd;
542}; 617};
543 618
544bool radeon_get_atom_connector_info_from_supported_devices_table(struct 619bool radeon_get_atom_connector_info_from_supported_devices_table(struct
@@ -554,7 +629,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
554 uint16_t device_support; 629 uint16_t device_support;
555 uint8_t dac; 630 uint8_t dac;
556 union atom_supported_devices *supported_devices; 631 union atom_supported_devices *supported_devices;
557 int i, j; 632 int i, j, max_device;
558 struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE]; 633 struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE];
559 634
560 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); 635 atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
@@ -564,7 +639,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
564 639
565 device_support = le16_to_cpu(supported_devices->info.usDeviceSupport); 640 device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
566 641
567 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 642 if (frev > 1)
643 max_device = ATOM_MAX_SUPPORTED_DEVICE;
644 else
645 max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
646
647 for (i = 0; i < max_device; i++) {
568 ATOM_CONNECTOR_INFO_I2C ci = 648 ATOM_CONNECTOR_INFO_I2C ci =
569 supported_devices->info.asConnInfo[i]; 649 supported_devices->info.asConnInfo[i];
570 650
@@ -619,8 +699,30 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
619 bios_connectors[i].line_mux = 52; 699 bios_connectors[i].line_mux = 52;
620 } else 700 } else
621 bios_connectors[i].ddc_bus = 701 bios_connectors[i].ddc_bus =
622 radeon_lookup_gpio(dev, 702 radeon_lookup_i2c_gpio(rdev,
623 bios_connectors[i].line_mux); 703 bios_connectors[i].line_mux);
704
705 if ((crev > 1) && (frev > 1)) {
706 u8 isb = supported_devices->info_2d1.asIntSrcInfo[i].ucIntSrcBitmap;
707 switch (isb) {
708 case 0x4:
709 bios_connectors[i].hpd.hpd = RADEON_HPD_1;
710 break;
711 case 0xa:
712 bios_connectors[i].hpd.hpd = RADEON_HPD_2;
713 break;
714 default:
715 bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
716 break;
717 }
718 } else {
719 if (i == ATOM_DEVICE_DFP1_INDEX)
720 bios_connectors[i].hpd.hpd = RADEON_HPD_1;
721 else if (i == ATOM_DEVICE_DFP2_INDEX)
722 bios_connectors[i].hpd.hpd = RADEON_HPD_2;
723 else
724 bios_connectors[i].hpd.hpd = RADEON_HPD_NONE;
725 }
624 726
625 /* Always set the connector type to VGA for CRT1/CRT2. if they are 727 /* Always set the connector type to VGA for CRT1/CRT2. if they are
626 * shared with a DVI port, we'll pick up the DVI connector when we 728 * shared with a DVI port, we'll pick up the DVI connector when we
@@ -632,7 +734,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
632 734
633 if (!radeon_atom_apply_quirks 735 if (!radeon_atom_apply_quirks
634 (dev, (1 << i), &bios_connectors[i].connector_type, 736 (dev, (1 << i), &bios_connectors[i].connector_type,
635 &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux)) 737 &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux,
738 &bios_connectors[i].hpd))
636 continue; 739 continue;
637 740
638 bios_connectors[i].valid = true; 741 bios_connectors[i].valid = true;
@@ -654,9 +757,9 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
654 } 757 }
655 758
656 /* combine shared connectors */ 759 /* combine shared connectors */
657 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 760 for (i = 0; i < max_device; i++) {
658 if (bios_connectors[i].valid) { 761 if (bios_connectors[i].valid) {
659 for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { 762 for (j = 0; j < max_device; j++) {
660 if (bios_connectors[j].valid && (i != j)) { 763 if (bios_connectors[j].valid && (i != j)) {
661 if (bios_connectors[i].line_mux == 764 if (bios_connectors[i].line_mux ==
662 bios_connectors[j].line_mux) { 765 bios_connectors[j].line_mux) {
@@ -680,6 +783,10 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
680 bios_connectors[i]. 783 bios_connectors[i].
681 connector_type = 784 connector_type =
682 DRM_MODE_CONNECTOR_DVII; 785 DRM_MODE_CONNECTOR_DVII;
786 if (bios_connectors[j].devices &
787 (ATOM_DEVICE_DFP_SUPPORT))
788 bios_connectors[i].hpd =
789 bios_connectors[j].hpd;
683 bios_connectors[j]. 790 bios_connectors[j].
684 valid = false; 791 valid = false;
685 } 792 }
@@ -690,7 +797,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
690 } 797 }
691 798
692 /* add the connectors */ 799 /* add the connectors */
693 for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { 800 for (i = 0; i < max_device; i++) {
694 if (bios_connectors[i].valid) { 801 if (bios_connectors[i].valid) {
695 uint16_t connector_object_id = 802 uint16_t connector_object_id =
696 atombios_get_connector_object_id(dev, 803 atombios_get_connector_object_id(dev,
@@ -703,7 +810,8 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
703 connector_type, 810 connector_type,
704 &bios_connectors[i].ddc_bus, 811 &bios_connectors[i].ddc_bus,
705 false, 0, 812 false, 0,
706 connector_object_id); 813 connector_object_id,
814 &bios_connectors[i].hpd);
707 } 815 }
708 } 816 }
709 817