diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 872 |
1 files changed, 773 insertions, 99 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 407215469102..fbe6f3931b1b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -40,13 +40,59 @@ | |||
40 | struct intel_sdvo_priv { | 40 | struct intel_sdvo_priv { |
41 | struct intel_i2c_chan *i2c_bus; | 41 | struct intel_i2c_chan *i2c_bus; |
42 | int slaveaddr; | 42 | int slaveaddr; |
43 | |||
44 | /* Register for the SDVO device: SDVOB or SDVOC */ | ||
43 | int output_device; | 45 | int output_device; |
44 | 46 | ||
45 | u16 active_outputs; | 47 | /* Active outputs controlled by this SDVO output */ |
48 | uint16_t controlled_output; | ||
46 | 49 | ||
50 | /* | ||
51 | * Capabilities of the SDVO device returned by | ||
52 | * i830_sdvo_get_capabilities() | ||
53 | */ | ||
47 | struct intel_sdvo_caps caps; | 54 | struct intel_sdvo_caps caps; |
55 | |||
56 | /* Pixel clock limitations reported by the SDVO device, in kHz */ | ||
48 | int pixel_clock_min, pixel_clock_max; | 57 | int pixel_clock_min, pixel_clock_max; |
49 | 58 | ||
59 | /** | ||
60 | * This is set if we're going to treat the device as TV-out. | ||
61 | * | ||
62 | * While we have these nice friendly flags for output types that ought | ||
63 | * to decide this for us, the S-Video output on our HDMI+S-Video card | ||
64 | * shows up as RGB1 (VGA). | ||
65 | */ | ||
66 | bool is_tv; | ||
67 | |||
68 | /** | ||
69 | * This is set if we treat the device as HDMI, instead of DVI. | ||
70 | */ | ||
71 | bool is_hdmi; | ||
72 | |||
73 | /** | ||
74 | * Returned SDTV resolutions allowed for the current format, if the | ||
75 | * device reported it. | ||
76 | */ | ||
77 | struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions; | ||
78 | |||
79 | /** | ||
80 | * Current selected TV format. | ||
81 | * | ||
82 | * This is stored in the same structure that's passed to the device, for | ||
83 | * convenience. | ||
84 | */ | ||
85 | struct intel_sdvo_tv_format tv_format; | ||
86 | |||
87 | /* | ||
88 | * supported encoding mode, used to determine whether HDMI is | ||
89 | * supported | ||
90 | */ | ||
91 | struct intel_sdvo_encode encode; | ||
92 | |||
93 | /* DDC bus used by this SDVO output */ | ||
94 | uint8_t ddc_bus; | ||
95 | |||
50 | int save_sdvo_mult; | 96 | int save_sdvo_mult; |
51 | u16 save_active_outputs; | 97 | u16 save_active_outputs; |
52 | struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; | 98 | struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; |
@@ -147,9 +193,9 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | |||
147 | 193 | ||
148 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} | 194 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} |
149 | /** Mapping of command numbers to names, for debug output */ | 195 | /** Mapping of command numbers to names, for debug output */ |
150 | const static struct _sdvo_cmd_name { | 196 | static const struct _sdvo_cmd_name { |
151 | u8 cmd; | 197 | u8 cmd; |
152 | char *name; | 198 | char *name; |
153 | } sdvo_cmd_names[] = { | 199 | } sdvo_cmd_names[] = { |
154 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), | 200 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), |
155 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), | 201 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), |
@@ -186,8 +232,35 @@ const static struct _sdvo_cmd_name { | |||
186 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), | 232 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), |
187 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), | 233 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), |
188 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), | 234 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), |
189 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), | 235 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES), |
236 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_POWER_STATE), | ||
237 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE), | ||
238 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_DISPLAY_POWER_STATE), | ||
190 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), | 239 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), |
240 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT), | ||
241 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT), | ||
242 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS), | ||
243 | /* HDMI op code */ | ||
244 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPP_ENCODE), | ||
245 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODE), | ||
246 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODE), | ||
247 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_PIXEL_REPLI), | ||
248 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PIXEL_REPLI), | ||
249 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY_CAP), | ||
250 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_COLORIMETRY), | ||
251 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_COLORIMETRY), | ||
252 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER), | ||
253 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_AUDIO_STAT), | ||
254 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_AUDIO_STAT), | ||
255 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INDEX), | ||
256 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_INDEX), | ||
257 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_INFO), | ||
258 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_AV_SPLIT), | ||
259 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_AV_SPLIT), | ||
260 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_TXRATE), | ||
261 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_TXRATE), | ||
262 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_HBUF_DATA), | ||
263 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA), | ||
191 | }; | 264 | }; |
192 | 265 | ||
193 | #define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") | 266 | #define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") |
@@ -506,6 +579,50 @@ static bool intel_sdvo_set_output_timing(struct intel_output *intel_output, | |||
506 | SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); | 579 | SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); |
507 | } | 580 | } |
508 | 581 | ||
582 | static bool | ||
583 | intel_sdvo_create_preferred_input_timing(struct intel_output *output, | ||
584 | uint16_t clock, | ||
585 | uint16_t width, | ||
586 | uint16_t height) | ||
587 | { | ||
588 | struct intel_sdvo_preferred_input_timing_args args; | ||
589 | uint8_t status; | ||
590 | |||
591 | args.clock = clock; | ||
592 | args.width = width; | ||
593 | args.height = height; | ||
594 | intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING, | ||
595 | &args, sizeof(args)); | ||
596 | status = intel_sdvo_read_response(output, NULL, 0); | ||
597 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
598 | return false; | ||
599 | |||
600 | return true; | ||
601 | } | ||
602 | |||
603 | static bool intel_sdvo_get_preferred_input_timing(struct intel_output *output, | ||
604 | struct intel_sdvo_dtd *dtd) | ||
605 | { | ||
606 | bool status; | ||
607 | |||
608 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, | ||
609 | NULL, 0); | ||
610 | |||
611 | status = intel_sdvo_read_response(output, &dtd->part1, | ||
612 | sizeof(dtd->part1)); | ||
613 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
614 | return false; | ||
615 | |||
616 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, | ||
617 | NULL, 0); | ||
618 | |||
619 | status = intel_sdvo_read_response(output, &dtd->part2, | ||
620 | sizeof(dtd->part2)); | ||
621 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
622 | return false; | ||
623 | |||
624 | return false; | ||
625 | } | ||
509 | 626 | ||
510 | static int intel_sdvo_get_clock_rate_mult(struct intel_output *intel_output) | 627 | static int intel_sdvo_get_clock_rate_mult(struct intel_output *intel_output) |
511 | { | 628 | { |
@@ -536,36 +653,12 @@ static bool intel_sdvo_set_clock_rate_mult(struct intel_output *intel_output, u8 | |||
536 | return true; | 653 | return true; |
537 | } | 654 | } |
538 | 655 | ||
539 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | 656 | static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd, |
540 | struct drm_display_mode *mode, | 657 | struct drm_display_mode *mode) |
541 | struct drm_display_mode *adjusted_mode) | ||
542 | { | ||
543 | /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO | ||
544 | * device will be told of the multiplier during mode_set. | ||
545 | */ | ||
546 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
547 | return true; | ||
548 | } | ||
549 | |||
550 | static void intel_sdvo_mode_set(struct drm_encoder *encoder, | ||
551 | struct drm_display_mode *mode, | ||
552 | struct drm_display_mode *adjusted_mode) | ||
553 | { | 658 | { |
554 | struct drm_device *dev = encoder->dev; | 659 | uint16_t width, height; |
555 | struct drm_i915_private *dev_priv = dev->dev_private; | 660 | uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; |
556 | struct drm_crtc *crtc = encoder->crtc; | 661 | uint16_t h_sync_offset, v_sync_offset; |
557 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
558 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
559 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
560 | u16 width, height; | ||
561 | u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; | ||
562 | u16 h_sync_offset, v_sync_offset; | ||
563 | u32 sdvox; | ||
564 | struct intel_sdvo_dtd output_dtd; | ||
565 | int sdvo_pixel_multiply; | ||
566 | |||
567 | if (!mode) | ||
568 | return; | ||
569 | 662 | ||
570 | width = mode->crtc_hdisplay; | 663 | width = mode->crtc_hdisplay; |
571 | height = mode->crtc_vdisplay; | 664 | height = mode->crtc_vdisplay; |
@@ -580,93 +673,423 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, | |||
580 | h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; | 673 | h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; |
581 | v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; | 674 | v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; |
582 | 675 | ||
583 | output_dtd.part1.clock = mode->clock / 10; | 676 | dtd->part1.clock = mode->clock / 10; |
584 | output_dtd.part1.h_active = width & 0xff; | 677 | dtd->part1.h_active = width & 0xff; |
585 | output_dtd.part1.h_blank = h_blank_len & 0xff; | 678 | dtd->part1.h_blank = h_blank_len & 0xff; |
586 | output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | | 679 | dtd->part1.h_high = (((width >> 8) & 0xf) << 4) | |
587 | ((h_blank_len >> 8) & 0xf); | 680 | ((h_blank_len >> 8) & 0xf); |
588 | output_dtd.part1.v_active = height & 0xff; | 681 | dtd->part1.v_active = height & 0xff; |
589 | output_dtd.part1.v_blank = v_blank_len & 0xff; | 682 | dtd->part1.v_blank = v_blank_len & 0xff; |
590 | output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | | 683 | dtd->part1.v_high = (((height >> 8) & 0xf) << 4) | |
591 | ((v_blank_len >> 8) & 0xf); | 684 | ((v_blank_len >> 8) & 0xf); |
592 | 685 | ||
593 | output_dtd.part2.h_sync_off = h_sync_offset; | 686 | dtd->part2.h_sync_off = h_sync_offset; |
594 | output_dtd.part2.h_sync_width = h_sync_len & 0xff; | 687 | dtd->part2.h_sync_width = h_sync_len & 0xff; |
595 | output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | | 688 | dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | |
596 | (v_sync_len & 0xf); | 689 | (v_sync_len & 0xf); |
597 | output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | | 690 | dtd->part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | |
598 | ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | | 691 | ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | |
599 | ((v_sync_len & 0x30) >> 4); | 692 | ((v_sync_len & 0x30) >> 4); |
600 | 693 | ||
601 | output_dtd.part2.dtd_flags = 0x18; | 694 | dtd->part2.dtd_flags = 0x18; |
602 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | 695 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) |
603 | output_dtd.part2.dtd_flags |= 0x2; | 696 | dtd->part2.dtd_flags |= 0x2; |
604 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | 697 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) |
605 | output_dtd.part2.dtd_flags |= 0x4; | 698 | dtd->part2.dtd_flags |= 0x4; |
699 | |||
700 | dtd->part2.sdvo_flags = 0; | ||
701 | dtd->part2.v_sync_off_high = v_sync_offset & 0xc0; | ||
702 | dtd->part2.reserved = 0; | ||
703 | } | ||
704 | |||
705 | static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, | ||
706 | struct intel_sdvo_dtd *dtd) | ||
707 | { | ||
708 | uint16_t width, height; | ||
709 | uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; | ||
710 | uint16_t h_sync_offset, v_sync_offset; | ||
711 | |||
712 | width = mode->crtc_hdisplay; | ||
713 | height = mode->crtc_vdisplay; | ||
714 | |||
715 | /* do some mode translations */ | ||
716 | h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; | ||
717 | h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; | ||
718 | |||
719 | v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; | ||
720 | v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; | ||
721 | |||
722 | h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; | ||
723 | v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; | ||
724 | |||
725 | mode->hdisplay = dtd->part1.h_active; | ||
726 | mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; | ||
727 | mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off; | ||
728 | mode->hsync_start += (dtd->part2.sync_off_width_high & 0xa0) << 2; | ||
729 | mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width; | ||
730 | mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; | ||
731 | mode->htotal = mode->hdisplay + dtd->part1.h_blank; | ||
732 | mode->htotal += (dtd->part1.h_high & 0xf) << 8; | ||
733 | |||
734 | mode->vdisplay = dtd->part1.v_active; | ||
735 | mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; | ||
736 | mode->vsync_start = mode->vdisplay; | ||
737 | mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; | ||
738 | mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0a) << 2; | ||
739 | mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0; | ||
740 | mode->vsync_end = mode->vsync_start + | ||
741 | (dtd->part2.v_sync_off_width & 0xf); | ||
742 | mode->vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4; | ||
743 | mode->vtotal = mode->vdisplay + dtd->part1.v_blank; | ||
744 | mode->vtotal += (dtd->part1.v_high & 0xf) << 8; | ||
745 | |||
746 | mode->clock = dtd->part1.clock * 10; | ||
747 | |||
748 | mode->flags &= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); | ||
749 | if (dtd->part2.dtd_flags & 0x2) | ||
750 | mode->flags |= DRM_MODE_FLAG_PHSYNC; | ||
751 | if (dtd->part2.dtd_flags & 0x4) | ||
752 | mode->flags |= DRM_MODE_FLAG_PVSYNC; | ||
753 | } | ||
754 | |||
755 | static bool intel_sdvo_get_supp_encode(struct intel_output *output, | ||
756 | struct intel_sdvo_encode *encode) | ||
757 | { | ||
758 | uint8_t status; | ||
759 | |||
760 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_SUPP_ENCODE, NULL, 0); | ||
761 | status = intel_sdvo_read_response(output, encode, sizeof(*encode)); | ||
762 | if (status != SDVO_CMD_STATUS_SUCCESS) { /* non-support means DVI */ | ||
763 | memset(encode, 0, sizeof(*encode)); | ||
764 | return false; | ||
765 | } | ||
766 | |||
767 | return true; | ||
768 | } | ||
769 | |||
770 | static bool intel_sdvo_set_encode(struct intel_output *output, uint8_t mode) | ||
771 | { | ||
772 | uint8_t status; | ||
773 | |||
774 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODE, &mode, 1); | ||
775 | status = intel_sdvo_read_response(output, NULL, 0); | ||
776 | |||
777 | return (status == SDVO_CMD_STATUS_SUCCESS); | ||
778 | } | ||
779 | |||
780 | static bool intel_sdvo_set_colorimetry(struct intel_output *output, | ||
781 | uint8_t mode) | ||
782 | { | ||
783 | uint8_t status; | ||
784 | |||
785 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_COLORIMETRY, &mode, 1); | ||
786 | status = intel_sdvo_read_response(output, NULL, 0); | ||
787 | |||
788 | return (status == SDVO_CMD_STATUS_SUCCESS); | ||
789 | } | ||
790 | |||
791 | #if 0 | ||
792 | static void intel_sdvo_dump_hdmi_buf(struct intel_output *output) | ||
793 | { | ||
794 | int i, j; | ||
795 | uint8_t set_buf_index[2]; | ||
796 | uint8_t av_split; | ||
797 | uint8_t buf_size; | ||
798 | uint8_t buf[48]; | ||
799 | uint8_t *pos; | ||
800 | |||
801 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_AV_SPLIT, NULL, 0); | ||
802 | intel_sdvo_read_response(output, &av_split, 1); | ||
803 | |||
804 | for (i = 0; i <= av_split; i++) { | ||
805 | set_buf_index[0] = i; set_buf_index[1] = 0; | ||
806 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX, | ||
807 | set_buf_index, 2); | ||
808 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_INFO, NULL, 0); | ||
809 | intel_sdvo_read_response(output, &buf_size, 1); | ||
810 | |||
811 | pos = buf; | ||
812 | for (j = 0; j <= buf_size; j += 8) { | ||
813 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_DATA, | ||
814 | NULL, 0); | ||
815 | intel_sdvo_read_response(output, pos, 8); | ||
816 | pos += 8; | ||
817 | } | ||
818 | } | ||
819 | } | ||
820 | #endif | ||
821 | |||
822 | static void intel_sdvo_set_hdmi_buf(struct intel_output *output, int index, | ||
823 | uint8_t *data, int8_t size, uint8_t tx_rate) | ||
824 | { | ||
825 | uint8_t set_buf_index[2]; | ||
826 | |||
827 | set_buf_index[0] = index; | ||
828 | set_buf_index[1] = 0; | ||
829 | |||
830 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2); | ||
831 | |||
832 | for (; size > 0; size -= 8) { | ||
833 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_DATA, data, 8); | ||
834 | data += 8; | ||
835 | } | ||
836 | |||
837 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1); | ||
838 | } | ||
839 | |||
840 | static uint8_t intel_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size) | ||
841 | { | ||
842 | uint8_t csum = 0; | ||
843 | int i; | ||
844 | |||
845 | for (i = 0; i < size; i++) | ||
846 | csum += data[i]; | ||
847 | |||
848 | return 0x100 - csum; | ||
849 | } | ||
850 | |||
851 | #define DIP_TYPE_AVI 0x82 | ||
852 | #define DIP_VERSION_AVI 0x2 | ||
853 | #define DIP_LEN_AVI 13 | ||
854 | |||
855 | struct dip_infoframe { | ||
856 | uint8_t type; | ||
857 | uint8_t version; | ||
858 | uint8_t len; | ||
859 | uint8_t checksum; | ||
860 | union { | ||
861 | struct { | ||
862 | /* Packet Byte #1 */ | ||
863 | uint8_t S:2; | ||
864 | uint8_t B:2; | ||
865 | uint8_t A:1; | ||
866 | uint8_t Y:2; | ||
867 | uint8_t rsvd1:1; | ||
868 | /* Packet Byte #2 */ | ||
869 | uint8_t R:4; | ||
870 | uint8_t M:2; | ||
871 | uint8_t C:2; | ||
872 | /* Packet Byte #3 */ | ||
873 | uint8_t SC:2; | ||
874 | uint8_t Q:2; | ||
875 | uint8_t EC:3; | ||
876 | uint8_t ITC:1; | ||
877 | /* Packet Byte #4 */ | ||
878 | uint8_t VIC:7; | ||
879 | uint8_t rsvd2:1; | ||
880 | /* Packet Byte #5 */ | ||
881 | uint8_t PR:4; | ||
882 | uint8_t rsvd3:4; | ||
883 | /* Packet Byte #6~13 */ | ||
884 | uint16_t top_bar_end; | ||
885 | uint16_t bottom_bar_start; | ||
886 | uint16_t left_bar_end; | ||
887 | uint16_t right_bar_start; | ||
888 | } avi; | ||
889 | struct { | ||
890 | /* Packet Byte #1 */ | ||
891 | uint8_t channel_count:3; | ||
892 | uint8_t rsvd1:1; | ||
893 | uint8_t coding_type:4; | ||
894 | /* Packet Byte #2 */ | ||
895 | uint8_t sample_size:2; /* SS0, SS1 */ | ||
896 | uint8_t sample_frequency:3; | ||
897 | uint8_t rsvd2:3; | ||
898 | /* Packet Byte #3 */ | ||
899 | uint8_t coding_type_private:5; | ||
900 | uint8_t rsvd3:3; | ||
901 | /* Packet Byte #4 */ | ||
902 | uint8_t channel_allocation; | ||
903 | /* Packet Byte #5 */ | ||
904 | uint8_t rsvd4:3; | ||
905 | uint8_t level_shift:4; | ||
906 | uint8_t downmix_inhibit:1; | ||
907 | } audio; | ||
908 | uint8_t payload[28]; | ||
909 | } __attribute__ ((packed)) u; | ||
910 | } __attribute__((packed)); | ||
911 | |||
912 | static void intel_sdvo_set_avi_infoframe(struct intel_output *output, | ||
913 | struct drm_display_mode * mode) | ||
914 | { | ||
915 | struct dip_infoframe avi_if = { | ||
916 | .type = DIP_TYPE_AVI, | ||
917 | .version = DIP_VERSION_AVI, | ||
918 | .len = DIP_LEN_AVI, | ||
919 | }; | ||
920 | |||
921 | avi_if.checksum = intel_sdvo_calc_hbuf_csum((uint8_t *)&avi_if, | ||
922 | 4 + avi_if.len); | ||
923 | intel_sdvo_set_hdmi_buf(output, 1, (uint8_t *)&avi_if, 4 + avi_if.len, | ||
924 | SDVO_HBUF_TX_VSYNC); | ||
925 | } | ||
926 | |||
927 | static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, | ||
928 | struct drm_display_mode *mode, | ||
929 | struct drm_display_mode *adjusted_mode) | ||
930 | { | ||
931 | struct intel_output *output = enc_to_intel_output(encoder); | ||
932 | struct intel_sdvo_priv *dev_priv = output->dev_priv; | ||
606 | 933 | ||
607 | output_dtd.part2.sdvo_flags = 0; | 934 | if (!dev_priv->is_tv) { |
608 | output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; | 935 | /* Make the CRTC code factor in the SDVO pixel multiplier. The |
609 | output_dtd.part2.reserved = 0; | 936 | * SDVO device will be told of the multiplier during mode_set. |
937 | */ | ||
938 | adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); | ||
939 | } else { | ||
940 | struct intel_sdvo_dtd output_dtd; | ||
941 | bool success; | ||
942 | |||
943 | /* We need to construct preferred input timings based on our | ||
944 | * output timings. To do that, we have to set the output | ||
945 | * timings, even though this isn't really the right place in | ||
946 | * the sequence to do it. Oh well. | ||
947 | */ | ||
948 | |||
949 | |||
950 | /* Set output timings */ | ||
951 | intel_sdvo_get_dtd_from_mode(&output_dtd, mode); | ||
952 | intel_sdvo_set_target_output(output, | ||
953 | dev_priv->controlled_output); | ||
954 | intel_sdvo_set_output_timing(output, &output_dtd); | ||
955 | |||
956 | /* Set the input timing to the screen. Assume always input 0. */ | ||
957 | intel_sdvo_set_target_input(output, true, false); | ||
958 | |||
959 | |||
960 | success = intel_sdvo_create_preferred_input_timing(output, | ||
961 | mode->clock / 10, | ||
962 | mode->hdisplay, | ||
963 | mode->vdisplay); | ||
964 | if (success) { | ||
965 | struct intel_sdvo_dtd input_dtd; | ||
610 | 966 | ||
611 | /* Set the output timing to the screen */ | 967 | intel_sdvo_get_preferred_input_timing(output, |
612 | intel_sdvo_set_target_output(intel_output, sdvo_priv->active_outputs); | 968 | &input_dtd); |
613 | intel_sdvo_set_output_timing(intel_output, &output_dtd); | 969 | intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); |
970 | |||
971 | } else { | ||
972 | return false; | ||
973 | } | ||
974 | } | ||
975 | return true; | ||
976 | } | ||
977 | |||
978 | static void intel_sdvo_mode_set(struct drm_encoder *encoder, | ||
979 | struct drm_display_mode *mode, | ||
980 | struct drm_display_mode *adjusted_mode) | ||
981 | { | ||
982 | struct drm_device *dev = encoder->dev; | ||
983 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
984 | struct drm_crtc *crtc = encoder->crtc; | ||
985 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
986 | struct intel_output *output = enc_to_intel_output(encoder); | ||
987 | struct intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
988 | u32 sdvox = 0; | ||
989 | int sdvo_pixel_multiply; | ||
990 | struct intel_sdvo_in_out_map in_out; | ||
991 | struct intel_sdvo_dtd input_dtd; | ||
992 | u8 status; | ||
993 | |||
994 | if (!mode) | ||
995 | return; | ||
996 | |||
997 | /* First, set the input mapping for the first input to our controlled | ||
998 | * output. This is only correct if we're a single-input device, in | ||
999 | * which case the first input is the output from the appropriate SDVO | ||
1000 | * channel on the motherboard. In a two-input device, the first input | ||
1001 | * will be SDVOB and the second SDVOC. | ||
1002 | */ | ||
1003 | in_out.in0 = sdvo_priv->controlled_output; | ||
1004 | in_out.in1 = 0; | ||
1005 | |||
1006 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, | ||
1007 | &in_out, sizeof(in_out)); | ||
1008 | status = intel_sdvo_read_response(output, NULL, 0); | ||
1009 | |||
1010 | if (sdvo_priv->is_hdmi) { | ||
1011 | intel_sdvo_set_avi_infoframe(output, mode); | ||
1012 | sdvox |= SDVO_AUDIO_ENABLE; | ||
1013 | } | ||
1014 | |||
1015 | intel_sdvo_get_dtd_from_mode(&input_dtd, mode); | ||
1016 | |||
1017 | /* If it's a TV, we already set the output timing in mode_fixup. | ||
1018 | * Otherwise, the output timing is equal to the input timing. | ||
1019 | */ | ||
1020 | if (!sdvo_priv->is_tv) { | ||
1021 | /* Set the output timing to the screen */ | ||
1022 | intel_sdvo_set_target_output(output, | ||
1023 | sdvo_priv->controlled_output); | ||
1024 | intel_sdvo_set_output_timing(output, &input_dtd); | ||
1025 | } | ||
614 | 1026 | ||
615 | /* Set the input timing to the screen. Assume always input 0. */ | 1027 | /* Set the input timing to the screen. Assume always input 0. */ |
616 | intel_sdvo_set_target_input(intel_output, true, false); | 1028 | intel_sdvo_set_target_input(output, true, false); |
617 | 1029 | ||
618 | /* We would like to use i830_sdvo_create_preferred_input_timing() to | 1030 | /* We would like to use intel_sdvo_create_preferred_input_timing() to |
619 | * provide the device with a timing it can support, if it supports that | 1031 | * provide the device with a timing it can support, if it supports that |
620 | * feature. However, presumably we would need to adjust the CRTC to | 1032 | * feature. However, presumably we would need to adjust the CRTC to |
621 | * output the preferred timing, and we don't support that currently. | 1033 | * output the preferred timing, and we don't support that currently. |
622 | */ | 1034 | */ |
623 | intel_sdvo_set_input_timing(intel_output, &output_dtd); | 1035 | #if 0 |
1036 | success = intel_sdvo_create_preferred_input_timing(output, clock, | ||
1037 | width, height); | ||
1038 | if (success) { | ||
1039 | struct intel_sdvo_dtd *input_dtd; | ||
1040 | |||
1041 | intel_sdvo_get_preferred_input_timing(output, &input_dtd); | ||
1042 | intel_sdvo_set_input_timing(output, &input_dtd); | ||
1043 | } | ||
1044 | #else | ||
1045 | intel_sdvo_set_input_timing(output, &input_dtd); | ||
1046 | #endif | ||
624 | 1047 | ||
625 | switch (intel_sdvo_get_pixel_multiplier(mode)) { | 1048 | switch (intel_sdvo_get_pixel_multiplier(mode)) { |
626 | case 1: | 1049 | case 1: |
627 | intel_sdvo_set_clock_rate_mult(intel_output, | 1050 | intel_sdvo_set_clock_rate_mult(output, |
628 | SDVO_CLOCK_RATE_MULT_1X); | 1051 | SDVO_CLOCK_RATE_MULT_1X); |
629 | break; | 1052 | break; |
630 | case 2: | 1053 | case 2: |
631 | intel_sdvo_set_clock_rate_mult(intel_output, | 1054 | intel_sdvo_set_clock_rate_mult(output, |
632 | SDVO_CLOCK_RATE_MULT_2X); | 1055 | SDVO_CLOCK_RATE_MULT_2X); |
633 | break; | 1056 | break; |
634 | case 4: | 1057 | case 4: |
635 | intel_sdvo_set_clock_rate_mult(intel_output, | 1058 | intel_sdvo_set_clock_rate_mult(output, |
636 | SDVO_CLOCK_RATE_MULT_4X); | 1059 | SDVO_CLOCK_RATE_MULT_4X); |
637 | break; | 1060 | break; |
638 | } | 1061 | } |
639 | 1062 | ||
640 | /* Set the SDVO control regs. */ | 1063 | /* Set the SDVO control regs. */ |
641 | if (0/*IS_I965GM(dev)*/) { | 1064 | if (IS_I965G(dev)) { |
642 | sdvox = SDVO_BORDER_ENABLE; | 1065 | sdvox |= SDVO_BORDER_ENABLE | |
643 | } else { | 1066 | SDVO_VSYNC_ACTIVE_HIGH | |
644 | sdvox = I915_READ(sdvo_priv->output_device); | 1067 | SDVO_HSYNC_ACTIVE_HIGH; |
645 | switch (sdvo_priv->output_device) { | 1068 | } else { |
646 | case SDVOB: | 1069 | sdvox |= I915_READ(sdvo_priv->output_device); |
647 | sdvox &= SDVOB_PRESERVE_MASK; | 1070 | switch (sdvo_priv->output_device) { |
648 | break; | 1071 | case SDVOB: |
649 | case SDVOC: | 1072 | sdvox &= SDVOB_PRESERVE_MASK; |
650 | sdvox &= SDVOC_PRESERVE_MASK; | 1073 | break; |
651 | break; | 1074 | case SDVOC: |
652 | } | 1075 | sdvox &= SDVOC_PRESERVE_MASK; |
653 | sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; | 1076 | break; |
654 | } | 1077 | } |
1078 | sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; | ||
1079 | } | ||
655 | if (intel_crtc->pipe == 1) | 1080 | if (intel_crtc->pipe == 1) |
656 | sdvox |= SDVO_PIPE_B_SELECT; | 1081 | sdvox |= SDVO_PIPE_B_SELECT; |
657 | 1082 | ||
658 | sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); | 1083 | sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); |
659 | if (IS_I965G(dev)) { | 1084 | if (IS_I965G(dev)) { |
660 | /* done in crtc_mode_set as the dpll_md reg must be written | 1085 | /* done in crtc_mode_set as the dpll_md reg must be written early */ |
661 | early */ | 1086 | } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { |
662 | } else if (IS_I945G(dev) || IS_I945GM(dev)) { | 1087 | /* done in crtc_mode_set as it lives inside the dpll register */ |
663 | /* done in crtc_mode_set as it lives inside the | ||
664 | dpll register */ | ||
665 | } else { | 1088 | } else { |
666 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; | 1089 | sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; |
667 | } | 1090 | } |
668 | 1091 | ||
669 | intel_sdvo_write_sdvox(intel_output, sdvox); | 1092 | intel_sdvo_write_sdvox(output, sdvox); |
670 | } | 1093 | } |
671 | 1094 | ||
672 | static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) | 1095 | static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) |
@@ -714,7 +1137,7 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) | |||
714 | 1137 | ||
715 | if (0) | 1138 | if (0) |
716 | intel_sdvo_set_encoder_power_state(intel_output, mode); | 1139 | intel_sdvo_set_encoder_power_state(intel_output, mode); |
717 | intel_sdvo_set_active_outputs(intel_output, sdvo_priv->active_outputs); | 1140 | intel_sdvo_set_active_outputs(intel_output, sdvo_priv->controlled_output); |
718 | } | 1141 | } |
719 | return; | 1142 | return; |
720 | } | 1143 | } |
@@ -752,6 +1175,9 @@ static void intel_sdvo_save(struct drm_connector *connector) | |||
752 | &sdvo_priv->save_output_dtd[o]); | 1175 | &sdvo_priv->save_output_dtd[o]); |
753 | } | 1176 | } |
754 | } | 1177 | } |
1178 | if (sdvo_priv->is_tv) { | ||
1179 | /* XXX: Save TV format/enhancements. */ | ||
1180 | } | ||
755 | 1181 | ||
756 | sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device); | 1182 | sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device); |
757 | } | 1183 | } |
@@ -759,7 +1185,6 @@ static void intel_sdvo_save(struct drm_connector *connector) | |||
759 | static void intel_sdvo_restore(struct drm_connector *connector) | 1185 | static void intel_sdvo_restore(struct drm_connector *connector) |
760 | { | 1186 | { |
761 | struct drm_device *dev = connector->dev; | 1187 | struct drm_device *dev = connector->dev; |
762 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
763 | struct intel_output *intel_output = to_intel_output(connector); | 1188 | struct intel_output *intel_output = to_intel_output(connector); |
764 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 1189 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
765 | int o; | 1190 | int o; |
@@ -790,7 +1215,11 @@ static void intel_sdvo_restore(struct drm_connector *connector) | |||
790 | 1215 | ||
791 | intel_sdvo_set_clock_rate_mult(intel_output, sdvo_priv->save_sdvo_mult); | 1216 | intel_sdvo_set_clock_rate_mult(intel_output, sdvo_priv->save_sdvo_mult); |
792 | 1217 | ||
793 | I915_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); | 1218 | if (sdvo_priv->is_tv) { |
1219 | /* XXX: Restore TV format/enhancements. */ | ||
1220 | } | ||
1221 | |||
1222 | intel_sdvo_write_sdvox(intel_output, sdvo_priv->save_SDVOX); | ||
794 | 1223 | ||
795 | if (sdvo_priv->save_SDVOX & SDVO_ENABLE) | 1224 | if (sdvo_priv->save_SDVOX & SDVO_ENABLE) |
796 | { | 1225 | { |
@@ -916,20 +1345,173 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect | |||
916 | status = intel_sdvo_read_response(intel_output, &response, 2); | 1345 | status = intel_sdvo_read_response(intel_output, &response, 2); |
917 | 1346 | ||
918 | DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); | 1347 | DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); |
1348 | |||
1349 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
1350 | return connector_status_unknown; | ||
1351 | |||
919 | if ((response[0] != 0) || (response[1] != 0)) | 1352 | if ((response[0] != 0) || (response[1] != 0)) |
920 | return connector_status_connected; | 1353 | return connector_status_connected; |
921 | else | 1354 | else |
922 | return connector_status_disconnected; | 1355 | return connector_status_disconnected; |
923 | } | 1356 | } |
924 | 1357 | ||
925 | static int intel_sdvo_get_modes(struct drm_connector *connector) | 1358 | static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) |
926 | { | 1359 | { |
927 | struct intel_output *intel_output = to_intel_output(connector); | 1360 | struct intel_output *intel_output = to_intel_output(connector); |
1361 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
928 | 1362 | ||
929 | /* set the bus switch and get the modes */ | 1363 | /* set the bus switch and get the modes */ |
930 | intel_sdvo_set_control_bus_switch(intel_output, SDVO_CONTROL_BUS_DDC2); | 1364 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); |
931 | intel_ddc_get_modes(intel_output); | 1365 | intel_ddc_get_modes(intel_output); |
932 | 1366 | ||
1367 | #if 0 | ||
1368 | struct drm_device *dev = encoder->dev; | ||
1369 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1370 | /* Mac mini hack. On this device, I get DDC through the analog, which | ||
1371 | * load-detects as disconnected. I fail to DDC through the SDVO DDC, | ||
1372 | * but it does load-detect as connected. So, just steal the DDC bits | ||
1373 | * from analog when we fail at finding it the right way. | ||
1374 | */ | ||
1375 | crt = xf86_config->output[0]; | ||
1376 | intel_output = crt->driver_private; | ||
1377 | if (intel_output->type == I830_OUTPUT_ANALOG && | ||
1378 | crt->funcs->detect(crt) == XF86OutputStatusDisconnected) { | ||
1379 | I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A"); | ||
1380 | edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus); | ||
1381 | xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true); | ||
1382 | } | ||
1383 | if (edid_mon) { | ||
1384 | xf86OutputSetEDID(output, edid_mon); | ||
1385 | modes = xf86OutputGetEDIDModes(output); | ||
1386 | } | ||
1387 | #endif | ||
1388 | } | ||
1389 | |||
1390 | /** | ||
1391 | * This function checks the current TV format, and chooses a default if | ||
1392 | * it hasn't been set. | ||
1393 | */ | ||
1394 | static void | ||
1395 | intel_sdvo_check_tv_format(struct intel_output *output) | ||
1396 | { | ||
1397 | struct intel_sdvo_priv *dev_priv = output->dev_priv; | ||
1398 | struct intel_sdvo_tv_format format, unset; | ||
1399 | uint8_t status; | ||
1400 | |||
1401 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0); | ||
1402 | status = intel_sdvo_read_response(output, &format, sizeof(format)); | ||
1403 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
1404 | return; | ||
1405 | |||
1406 | memset(&unset, 0, sizeof(unset)); | ||
1407 | if (memcmp(&format, &unset, sizeof(format))) { | ||
1408 | DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n", | ||
1409 | SDVO_NAME(dev_priv)); | ||
1410 | |||
1411 | format.ntsc_m = true; | ||
1412 | intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0); | ||
1413 | status = intel_sdvo_read_response(output, NULL, 0); | ||
1414 | } | ||
1415 | } | ||
1416 | |||
1417 | /* | ||
1418 | * Set of SDVO TV modes. | ||
1419 | * Note! This is in reply order (see loop in get_tv_modes). | ||
1420 | * XXX: all 60Hz refresh? | ||
1421 | */ | ||
1422 | struct drm_display_mode sdvo_tv_modes[] = { | ||
1423 | { DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815680, 321, 384, 416, | ||
1424 | 200, 0, 232, 201, 233, 4196112, 0, | ||
1425 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1426 | { DRM_MODE("320x240", DRM_MODE_TYPE_DRIVER, 6814080, 321, 384, 416, | ||
1427 | 240, 0, 272, 241, 273, 4196112, 0, | ||
1428 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1429 | { DRM_MODE("400x300", DRM_MODE_TYPE_DRIVER, 9910080, 401, 464, 496, | ||
1430 | 300, 0, 332, 301, 333, 4196112, 0, | ||
1431 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1432 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 16913280, 641, 704, 736, | ||
1433 | 350, 0, 382, 351, 383, 4196112, 0, | ||
1434 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1435 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736, | ||
1436 | 400, 0, 432, 401, 433, 4196112, 0, | ||
1437 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1438 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 19121280, 641, 704, 736, | ||
1439 | 400, 0, 432, 401, 433, 4196112, 0, | ||
1440 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1441 | { DRM_MODE("704x480", DRM_MODE_TYPE_DRIVER, 24624000, 705, 768, 800, | ||
1442 | 480, 0, 512, 481, 513, 4196112, 0, | ||
1443 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1444 | { DRM_MODE("704x576", DRM_MODE_TYPE_DRIVER, 29232000, 705, 768, 800, | ||
1445 | 576, 0, 608, 577, 609, 4196112, 0, | ||
1446 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1447 | { DRM_MODE("720x350", DRM_MODE_TYPE_DRIVER, 18751680, 721, 784, 816, | ||
1448 | 350, 0, 382, 351, 383, 4196112, 0, | ||
1449 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1450 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 21199680, 721, 784, 816, | ||
1451 | 400, 0, 432, 401, 433, 4196112, 0, | ||
1452 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1453 | { DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 25116480, 721, 784, 816, | ||
1454 | 480, 0, 512, 481, 513, 4196112, 0, | ||
1455 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1456 | { DRM_MODE("720x540", DRM_MODE_TYPE_DRIVER, 28054080, 721, 784, 816, | ||
1457 | 540, 0, 572, 541, 573, 4196112, 0, | ||
1458 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1459 | { DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 29816640, 721, 784, 816, | ||
1460 | 576, 0, 608, 577, 609, 4196112, 0, | ||
1461 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1462 | { DRM_MODE("768x576", DRM_MODE_TYPE_DRIVER, 31570560, 769, 832, 864, | ||
1463 | 576, 0, 608, 577, 609, 4196112, 0, | ||
1464 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1465 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 34030080, 801, 864, 896, | ||
1466 | 600, 0, 632, 601, 633, 4196112, 0, | ||
1467 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1468 | { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 36581760, 833, 896, 928, | ||
1469 | 624, 0, 656, 625, 657, 4196112, 0, | ||
1470 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1471 | { DRM_MODE("920x766", DRM_MODE_TYPE_DRIVER, 48707040, 921, 984, 1016, | ||
1472 | 766, 0, 798, 767, 799, 4196112, 0, | ||
1473 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1474 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 53827200, 1025, 1088, 1120, | ||
1475 | 768, 0, 800, 769, 801, 4196112, 0, | ||
1476 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1477 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 87265920, 1281, 1344, 1376, | ||
1478 | 1024, 0, 1056, 1025, 1057, 4196112, 0, | ||
1479 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
1480 | }; | ||
1481 | |||
1482 | static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | ||
1483 | { | ||
1484 | struct intel_output *output = to_intel_output(connector); | ||
1485 | uint32_t reply = 0; | ||
1486 | uint8_t status; | ||
1487 | int i = 0; | ||
1488 | |||
1489 | intel_sdvo_check_tv_format(output); | ||
1490 | |||
1491 | /* Read the list of supported input resolutions for the selected TV | ||
1492 | * format. | ||
1493 | */ | ||
1494 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, | ||
1495 | NULL, 0); | ||
1496 | status = intel_sdvo_read_response(output, &reply, 3); | ||
1497 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
1498 | return; | ||
1499 | |||
1500 | for (i = 0; i < ARRAY_SIZE(sdvo_tv_modes); i++) | ||
1501 | if (reply & (1 << i)) | ||
1502 | drm_mode_probed_add(connector, &sdvo_tv_modes[i]); | ||
1503 | } | ||
1504 | |||
1505 | static int intel_sdvo_get_modes(struct drm_connector *connector) | ||
1506 | { | ||
1507 | struct intel_output *output = to_intel_output(connector); | ||
1508 | struct intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
1509 | |||
1510 | if (sdvo_priv->is_tv) | ||
1511 | intel_sdvo_get_tv_modes(connector); | ||
1512 | else | ||
1513 | intel_sdvo_get_ddc_modes(connector); | ||
1514 | |||
933 | if (list_empty(&connector->probed_modes)) | 1515 | if (list_empty(&connector->probed_modes)) |
934 | return 0; | 1516 | return 0; |
935 | return 1; | 1517 | return 1; |
@@ -978,6 +1560,65 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { | |||
978 | }; | 1560 | }; |
979 | 1561 | ||
980 | 1562 | ||
1563 | /** | ||
1564 | * Choose the appropriate DDC bus for control bus switch command for this | ||
1565 | * SDVO output based on the controlled output. | ||
1566 | * | ||
1567 | * DDC bus number assignment is in a priority order of RGB outputs, then TMDS | ||
1568 | * outputs, then LVDS outputs. | ||
1569 | */ | ||
1570 | static void | ||
1571 | intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv) | ||
1572 | { | ||
1573 | uint16_t mask = 0; | ||
1574 | unsigned int num_bits; | ||
1575 | |||
1576 | /* Make a mask of outputs less than or equal to our own priority in the | ||
1577 | * list. | ||
1578 | */ | ||
1579 | switch (dev_priv->controlled_output) { | ||
1580 | case SDVO_OUTPUT_LVDS1: | ||
1581 | mask |= SDVO_OUTPUT_LVDS1; | ||
1582 | case SDVO_OUTPUT_LVDS0: | ||
1583 | mask |= SDVO_OUTPUT_LVDS0; | ||
1584 | case SDVO_OUTPUT_TMDS1: | ||
1585 | mask |= SDVO_OUTPUT_TMDS1; | ||
1586 | case SDVO_OUTPUT_TMDS0: | ||
1587 | mask |= SDVO_OUTPUT_TMDS0; | ||
1588 | case SDVO_OUTPUT_RGB1: | ||
1589 | mask |= SDVO_OUTPUT_RGB1; | ||
1590 | case SDVO_OUTPUT_RGB0: | ||
1591 | mask |= SDVO_OUTPUT_RGB0; | ||
1592 | break; | ||
1593 | } | ||
1594 | |||
1595 | /* Count bits to find what number we are in the priority list. */ | ||
1596 | mask &= dev_priv->caps.output_flags; | ||
1597 | num_bits = hweight16(mask); | ||
1598 | if (num_bits > 3) { | ||
1599 | /* if more than 3 outputs, default to DDC bus 3 for now */ | ||
1600 | num_bits = 3; | ||
1601 | } | ||
1602 | |||
1603 | /* Corresponds to SDVO_CONTROL_BUS_DDCx */ | ||
1604 | dev_priv->ddc_bus = 1 << num_bits; | ||
1605 | } | ||
1606 | |||
1607 | static bool | ||
1608 | intel_sdvo_get_digital_encoding_mode(struct intel_output *output) | ||
1609 | { | ||
1610 | struct intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
1611 | uint8_t status; | ||
1612 | |||
1613 | intel_sdvo_set_target_output(output, sdvo_priv->controlled_output); | ||
1614 | |||
1615 | intel_sdvo_write_cmd(output, SDVO_CMD_GET_ENCODE, NULL, 0); | ||
1616 | status = intel_sdvo_read_response(output, &sdvo_priv->is_hdmi, 1); | ||
1617 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
1618 | return false; | ||
1619 | return true; | ||
1620 | } | ||
1621 | |||
981 | bool intel_sdvo_init(struct drm_device *dev, int output_device) | 1622 | bool intel_sdvo_init(struct drm_device *dev, int output_device) |
982 | { | 1623 | { |
983 | struct drm_connector *connector; | 1624 | struct drm_connector *connector; |
@@ -1040,45 +1681,76 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1040 | 1681 | ||
1041 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); | 1682 | intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps); |
1042 | 1683 | ||
1043 | memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs)); | 1684 | if (sdvo_priv->caps.output_flags & |
1685 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
1686 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | ||
1687 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0; | ||
1688 | else | ||
1689 | sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1; | ||
1690 | |||
1691 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
1692 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1693 | connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1044 | 1694 | ||
1045 | /* TODO, CVBS, SVID, YPRPB & SCART outputs. */ | 1695 | if (intel_sdvo_get_supp_encode(intel_output, |
1046 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) | 1696 | &sdvo_priv->encode) && |
1697 | intel_sdvo_get_digital_encoding_mode(intel_output) && | ||
1698 | sdvo_priv->is_hdmi) { | ||
1699 | /* enable hdmi encoding mode if supported */ | ||
1700 | intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI); | ||
1701 | intel_sdvo_set_colorimetry(intel_output, | ||
1702 | SDVO_COLORIMETRY_RGB256); | ||
1703 | connector_type = DRM_MODE_CONNECTOR_HDMIA; | ||
1704 | } | ||
1705 | } | ||
1706 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0) | ||
1047 | { | 1707 | { |
1048 | sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; | 1708 | sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0; |
1709 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
1710 | encoder_type = DRM_MODE_ENCODER_TVDAC; | ||
1711 | connector_type = DRM_MODE_CONNECTOR_SVIDEO; | ||
1712 | sdvo_priv->is_tv = true; | ||
1713 | intel_output->needs_tv_clock = true; | ||
1714 | } | ||
1715 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) | ||
1716 | { | ||
1717 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; | ||
1049 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 1718 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
1050 | encoder_type = DRM_MODE_ENCODER_DAC; | 1719 | encoder_type = DRM_MODE_ENCODER_DAC; |
1051 | connector_type = DRM_MODE_CONNECTOR_VGA; | 1720 | connector_type = DRM_MODE_CONNECTOR_VGA; |
1052 | } | 1721 | } |
1053 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) | 1722 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) |
1054 | { | 1723 | { |
1055 | sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; | 1724 | sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; |
1056 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 1725 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
1057 | encoder_type = DRM_MODE_ENCODER_DAC; | 1726 | encoder_type = DRM_MODE_ENCODER_DAC; |
1058 | connector_type = DRM_MODE_CONNECTOR_VGA; | 1727 | connector_type = DRM_MODE_CONNECTOR_VGA; |
1059 | } | 1728 | } |
1060 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) | 1729 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0) |
1061 | { | 1730 | { |
1062 | sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; | 1731 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0; |
1063 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 1732 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
1064 | encoder_type = DRM_MODE_ENCODER_TMDS; | 1733 | encoder_type = DRM_MODE_ENCODER_LVDS; |
1065 | connector_type = DRM_MODE_CONNECTOR_DVID; | 1734 | connector_type = DRM_MODE_CONNECTOR_LVDS; |
1066 | } | 1735 | } |
1067 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) | 1736 | else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1) |
1068 | { | 1737 | { |
1069 | sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; | 1738 | sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; |
1070 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 1739 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
1071 | encoder_type = DRM_MODE_ENCODER_TMDS; | 1740 | encoder_type = DRM_MODE_ENCODER_LVDS; |
1072 | connector_type = DRM_MODE_CONNECTOR_DVID; | 1741 | connector_type = DRM_MODE_CONNECTOR_LVDS; |
1073 | } | 1742 | } |
1074 | else | 1743 | else |
1075 | { | 1744 | { |
1076 | unsigned char bytes[2]; | 1745 | unsigned char bytes[2]; |
1077 | 1746 | ||
1747 | sdvo_priv->controlled_output = 0; | ||
1078 | memcpy (bytes, &sdvo_priv->caps.output_flags, 2); | 1748 | memcpy (bytes, &sdvo_priv->caps.output_flags, 2); |
1079 | DRM_DEBUG("%s: No active RGB or TMDS outputs (0x%02x%02x)\n", | 1749 | DRM_DEBUG("%s: Unknown SDVO output type (0x%02x%02x)\n", |
1080 | SDVO_NAME(sdvo_priv), | 1750 | SDVO_NAME(sdvo_priv), |
1081 | bytes[0], bytes[1]); | 1751 | bytes[0], bytes[1]); |
1752 | encoder_type = DRM_MODE_ENCODER_NONE; | ||
1753 | connector_type = DRM_MODE_CONNECTOR_Unknown; | ||
1082 | goto err_i2c; | 1754 | goto err_i2c; |
1083 | } | 1755 | } |
1084 | 1756 | ||
@@ -1089,6 +1761,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1089 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); | 1761 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); |
1090 | drm_sysfs_connector_add(connector); | 1762 | drm_sysfs_connector_add(connector); |
1091 | 1763 | ||
1764 | intel_sdvo_select_ddc_bus(sdvo_priv); | ||
1765 | |||
1092 | /* Set the input timing to the screen. Assume always input 0. */ | 1766 | /* Set the input timing to the screen. Assume always input 0. */ |
1093 | intel_sdvo_set_target_input(intel_output, true, false); | 1767 | intel_sdvo_set_target_input(intel_output, true, false); |
1094 | 1768 | ||