diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-06 21:06:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-06 21:06:44 -0500 |
commit | c89a9f5a42811aa5b2f258e32750c0109f570fc1 (patch) | |
tree | 53f64a1326f0c3884261ad2160e1b18cc7af5fb6 /drivers | |
parent | db30c70575822cc84d87b5613c19cac24734b99f (diff) | |
parent | a75f28419a7efff611a81293d41d0e2137d7591e (diff) |
Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
drm: fix ordering of driver unload vs agp unload.
drm/i915: Respect the other stolen memory sizes we know of.
drm/i915: Non-mobile parts don't have integrated TV-out.
drm/i915: Add support for integrated HDMI on G4X hardware.
drm/i915: Pin cursor bo and unpin old bo when setting cursor.
drm/i915: Don't allow objects to get bound while VT switched.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 46 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 280 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 8 |
10 files changed, 397 insertions, 39 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index febb517ee679..5ff88d952226 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -314,14 +314,14 @@ static void drm_cleanup(struct drm_device * dev) | |||
314 | DRM_DEBUG("mtrr_del=%d\n", retval); | 314 | DRM_DEBUG("mtrr_del=%d\n", retval); |
315 | } | 315 | } |
316 | 316 | ||
317 | if (dev->driver->unload) | ||
318 | dev->driver->unload(dev); | ||
319 | |||
317 | if (drm_core_has_AGP(dev) && dev->agp) { | 320 | if (drm_core_has_AGP(dev) && dev->agp) { |
318 | drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); | 321 | drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); |
319 | dev->agp = NULL; | 322 | dev->agp = NULL; |
320 | } | 323 | } |
321 | 324 | ||
322 | if (dev->driver->unload) | ||
323 | dev->driver->unload(dev); | ||
324 | |||
325 | drm_ht_remove(&dev->map_hash); | 325 | drm_ht_remove(&dev->map_hash); |
326 | drm_ctxbitmap_cleanup(dev); | 326 | drm_ctxbitmap_cleanup(dev); |
327 | 327 | ||
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index dd57a5bd4572..793cba39d832 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -13,6 +13,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
13 | intel_crt.o \ | 13 | intel_crt.o \ |
14 | intel_lvds.o \ | 14 | intel_lvds.o \ |
15 | intel_bios.o \ | 15 | intel_bios.o \ |
16 | intel_hdmi.o \ | ||
16 | intel_sdvo.o \ | 17 | intel_sdvo.o \ |
17 | intel_modes.o \ | 18 | intel_modes.o \ |
18 | intel_i2c.o \ | 19 | intel_i2c.o \ |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3d7082af5b72..62a4bf7b49df 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -827,6 +827,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | |||
827 | struct pci_dev *bridge_dev; | 827 | struct pci_dev *bridge_dev; |
828 | u16 tmp = 0; | 828 | u16 tmp = 0; |
829 | unsigned long overhead; | 829 | unsigned long overhead; |
830 | unsigned long stolen; | ||
830 | 831 | ||
831 | bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); | 832 | bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); |
832 | if (!bridge_dev) { | 833 | if (!bridge_dev) { |
@@ -866,36 +867,55 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size, | |||
866 | else | 867 | else |
867 | overhead = (*aperture_size / 1024) + 4096; | 868 | overhead = (*aperture_size / 1024) + 4096; |
868 | 869 | ||
869 | switch (tmp & INTEL_855_GMCH_GMS_MASK) { | 870 | switch (tmp & INTEL_GMCH_GMS_MASK) { |
871 | case INTEL_855_GMCH_GMS_DISABLED: | ||
872 | DRM_ERROR("video memory is disabled\n"); | ||
873 | return -1; | ||
870 | case INTEL_855_GMCH_GMS_STOLEN_1M: | 874 | case INTEL_855_GMCH_GMS_STOLEN_1M: |
871 | break; /* 1M already */ | 875 | stolen = 1 * 1024 * 1024; |
876 | break; | ||
872 | case INTEL_855_GMCH_GMS_STOLEN_4M: | 877 | case INTEL_855_GMCH_GMS_STOLEN_4M: |
873 | *preallocated_size *= 4; | 878 | stolen = 4 * 1024 * 1024; |
874 | break; | 879 | break; |
875 | case INTEL_855_GMCH_GMS_STOLEN_8M: | 880 | case INTEL_855_GMCH_GMS_STOLEN_8M: |
876 | *preallocated_size *= 8; | 881 | stolen = 8 * 1024 * 1024; |
877 | break; | 882 | break; |
878 | case INTEL_855_GMCH_GMS_STOLEN_16M: | 883 | case INTEL_855_GMCH_GMS_STOLEN_16M: |
879 | *preallocated_size *= 16; | 884 | stolen = 16 * 1024 * 1024; |
880 | break; | 885 | break; |
881 | case INTEL_855_GMCH_GMS_STOLEN_32M: | 886 | case INTEL_855_GMCH_GMS_STOLEN_32M: |
882 | *preallocated_size *= 32; | 887 | stolen = 32 * 1024 * 1024; |
883 | break; | 888 | break; |
884 | case INTEL_915G_GMCH_GMS_STOLEN_48M: | 889 | case INTEL_915G_GMCH_GMS_STOLEN_48M: |
885 | *preallocated_size *= 48; | 890 | stolen = 48 * 1024 * 1024; |
886 | break; | 891 | break; |
887 | case INTEL_915G_GMCH_GMS_STOLEN_64M: | 892 | case INTEL_915G_GMCH_GMS_STOLEN_64M: |
888 | *preallocated_size *= 64; | 893 | stolen = 64 * 1024 * 1024; |
894 | break; | ||
895 | case INTEL_GMCH_GMS_STOLEN_128M: | ||
896 | stolen = 128 * 1024 * 1024; | ||
897 | break; | ||
898 | case INTEL_GMCH_GMS_STOLEN_256M: | ||
899 | stolen = 256 * 1024 * 1024; | ||
900 | break; | ||
901 | case INTEL_GMCH_GMS_STOLEN_96M: | ||
902 | stolen = 96 * 1024 * 1024; | ||
903 | break; | ||
904 | case INTEL_GMCH_GMS_STOLEN_160M: | ||
905 | stolen = 160 * 1024 * 1024; | ||
906 | break; | ||
907 | case INTEL_GMCH_GMS_STOLEN_224M: | ||
908 | stolen = 224 * 1024 * 1024; | ||
909 | break; | ||
910 | case INTEL_GMCH_GMS_STOLEN_352M: | ||
911 | stolen = 352 * 1024 * 1024; | ||
889 | break; | 912 | break; |
890 | case INTEL_855_GMCH_GMS_DISABLED: | ||
891 | DRM_ERROR("video memory is disabled\n"); | ||
892 | return -1; | ||
893 | default: | 913 | default: |
894 | DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", | 914 | DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", |
895 | tmp & INTEL_855_GMCH_GMS_MASK); | 915 | tmp & INTEL_GMCH_GMS_MASK); |
896 | return -1; | 916 | return -1; |
897 | } | 917 | } |
898 | *preallocated_size -= overhead; | 918 | *preallocated_size = stolen - overhead; |
899 | 919 | ||
900 | return 0; | 920 | return 0; |
901 | } | 921 | } |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4756e5cd6b5e..563de18063fd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -664,6 +664,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev); | |||
664 | writel(upper_32_bits(val), dev_priv->regs + \ | 664 | writel(upper_32_bits(val), dev_priv->regs + \ |
665 | (reg) + 4)) | 665 | (reg) + 4)) |
666 | #endif | 666 | #endif |
667 | #define POSTING_READ(reg) (void)I915_READ(reg) | ||
667 | 668 | ||
668 | #define I915_VERBOSE 0 | 669 | #define I915_VERBOSE 0 |
669 | 670 | ||
@@ -760,6 +761,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
760 | IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) | 761 | IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) |
761 | 762 | ||
762 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) | 763 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) |
764 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) | ||
763 | 765 | ||
764 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 766 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
765 | 767 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cc2ca5561feb..14afc23a0e24 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1623,6 +1623,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
1623 | struct drm_mm_node *free_space; | 1623 | struct drm_mm_node *free_space; |
1624 | int page_count, ret; | 1624 | int page_count, ret; |
1625 | 1625 | ||
1626 | if (dev_priv->mm.suspended) | ||
1627 | return -EBUSY; | ||
1626 | if (alignment == 0) | 1628 | if (alignment == 0) |
1627 | alignment = PAGE_SIZE; | 1629 | alignment = PAGE_SIZE; |
1628 | if (alignment & (PAGE_SIZE - 1)) { | 1630 | if (alignment & (PAGE_SIZE - 1)) { |
@@ -2641,7 +2643,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
2641 | if (obj_priv->gtt_space == NULL) { | 2643 | if (obj_priv->gtt_space == NULL) { |
2642 | ret = i915_gem_object_bind_to_gtt(obj, alignment); | 2644 | ret = i915_gem_object_bind_to_gtt(obj, alignment); |
2643 | if (ret != 0) { | 2645 | if (ret != 0) { |
2644 | if (ret != -ERESTARTSYS) | 2646 | if (ret != -EBUSY && ret != -ERESTARTSYS) |
2645 | DRM_ERROR("Failure to bind: %d", ret); | 2647 | DRM_ERROR("Failure to bind: %d", ret); |
2646 | return ret; | 2648 | return ret; |
2647 | } | 2649 | } |
@@ -3219,20 +3221,21 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
3219 | dev_priv->mm.wedged = 0; | 3221 | dev_priv->mm.wedged = 0; |
3220 | } | 3222 | } |
3221 | 3223 | ||
3222 | ret = i915_gem_init_ringbuffer(dev); | ||
3223 | if (ret != 0) | ||
3224 | return ret; | ||
3225 | |||
3226 | dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, | 3224 | dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, |
3227 | dev->agp->agp_info.aper_size | 3225 | dev->agp->agp_info.aper_size |
3228 | * 1024 * 1024); | 3226 | * 1024 * 1024); |
3229 | 3227 | ||
3230 | mutex_lock(&dev->struct_mutex); | 3228 | mutex_lock(&dev->struct_mutex); |
3229 | dev_priv->mm.suspended = 0; | ||
3230 | |||
3231 | ret = i915_gem_init_ringbuffer(dev); | ||
3232 | if (ret != 0) | ||
3233 | return ret; | ||
3234 | |||
3231 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); | 3235 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); |
3232 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); | 3236 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); |
3233 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); | 3237 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); |
3234 | BUG_ON(!list_empty(&dev_priv->mm.request_list)); | 3238 | BUG_ON(!list_empty(&dev_priv->mm.request_list)); |
3235 | dev_priv->mm.suspended = 0; | ||
3236 | mutex_unlock(&dev->struct_mutex); | 3239 | mutex_unlock(&dev->struct_mutex); |
3237 | 3240 | ||
3238 | drm_irq_install(dev); | 3241 | drm_irq_install(dev); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 47e6bafeb743..273162579e1b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -35,7 +35,7 @@ | |||
35 | #define INTEL_GMCH_MEM_64M 0x1 | 35 | #define INTEL_GMCH_MEM_64M 0x1 |
36 | #define INTEL_GMCH_MEM_128M 0 | 36 | #define INTEL_GMCH_MEM_128M 0 |
37 | 37 | ||
38 | #define INTEL_855_GMCH_GMS_MASK (0x7 << 4) | 38 | #define INTEL_GMCH_GMS_MASK (0xf << 4) |
39 | #define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4) | 39 | #define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4) |
40 | #define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4) | 40 | #define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4) |
41 | #define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4) | 41 | #define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4) |
@@ -45,6 +45,12 @@ | |||
45 | 45 | ||
46 | #define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4) | 46 | #define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4) |
47 | #define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4) | 47 | #define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4) |
48 | #define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4) | ||
49 | #define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4) | ||
50 | #define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) | ||
51 | #define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) | ||
52 | #define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) | ||
53 | #define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) | ||
48 | 54 | ||
49 | /* PCI config space */ | 55 | /* PCI config space */ |
50 | 56 | ||
@@ -549,6 +555,8 @@ | |||
549 | /** GM965 GM45 render standby register */ | 555 | /** GM965 GM45 render standby register */ |
550 | #define MCHBAR_RENDER_STANDBY 0x111B8 | 556 | #define MCHBAR_RENDER_STANDBY 0x111B8 |
551 | 557 | ||
558 | #define PEG_BAND_GAP_DATA 0x14d68 | ||
559 | |||
552 | /* | 560 | /* |
553 | * Overlay regs | 561 | * Overlay regs |
554 | */ | 562 | */ |
@@ -612,6 +620,9 @@ | |||
612 | 620 | ||
613 | /* Hotplug control (945+ only) */ | 621 | /* Hotplug control (945+ only) */ |
614 | #define PORT_HOTPLUG_EN 0x61110 | 622 | #define PORT_HOTPLUG_EN 0x61110 |
623 | #define HDMIB_HOTPLUG_INT_EN (1 << 29) | ||
624 | #define HDMIC_HOTPLUG_INT_EN (1 << 28) | ||
625 | #define HDMID_HOTPLUG_INT_EN (1 << 27) | ||
615 | #define SDVOB_HOTPLUG_INT_EN (1 << 26) | 626 | #define SDVOB_HOTPLUG_INT_EN (1 << 26) |
616 | #define SDVOC_HOTPLUG_INT_EN (1 << 25) | 627 | #define SDVOC_HOTPLUG_INT_EN (1 << 25) |
617 | #define TV_HOTPLUG_INT_EN (1 << 18) | 628 | #define TV_HOTPLUG_INT_EN (1 << 18) |
@@ -619,6 +630,9 @@ | |||
619 | #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) | 630 | #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) |
620 | 631 | ||
621 | #define PORT_HOTPLUG_STAT 0x61114 | 632 | #define PORT_HOTPLUG_STAT 0x61114 |
633 | #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) | ||
634 | #define HDMIC_HOTPLUG_INT_STATUS (1 << 28) | ||
635 | #define HDMID_HOTPLUG_INT_STATUS (1 << 27) | ||
622 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) | 636 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) |
623 | #define TV_HOTPLUG_INT_STATUS (1 << 10) | 637 | #define TV_HOTPLUG_INT_STATUS (1 << 10) |
624 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) | 638 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) |
@@ -648,7 +662,16 @@ | |||
648 | #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) | 662 | #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) |
649 | #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) | 663 | #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) |
650 | #define SDVOC_GANG_MODE (1 << 16) | 664 | #define SDVOC_GANG_MODE (1 << 16) |
665 | #define SDVO_ENCODING_SDVO (0x0 << 10) | ||
666 | #define SDVO_ENCODING_HDMI (0x2 << 10) | ||
667 | /** Requird for HDMI operation */ | ||
668 | #define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) | ||
651 | #define SDVO_BORDER_ENABLE (1 << 7) | 669 | #define SDVO_BORDER_ENABLE (1 << 7) |
670 | #define SDVO_AUDIO_ENABLE (1 << 6) | ||
671 | /** New with 965, default is to be set */ | ||
672 | #define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) | ||
673 | /** New with 965, default is to be set */ | ||
674 | #define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) | ||
652 | #define SDVOB_PCIE_CONCURRENCY (1 << 3) | 675 | #define SDVOB_PCIE_CONCURRENCY (1 << 3) |
653 | #define SDVO_DETECTED (1 << 2) | 676 | #define SDVO_DETECTED (1 << 2) |
654 | /* Bits to be preserved when writing */ | 677 | /* Bits to be preserved when writing */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e5c1c80d1f90..8ccb9c3ab868 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -751,6 +751,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
751 | is_lvds = true; | 751 | is_lvds = true; |
752 | break; | 752 | break; |
753 | case INTEL_OUTPUT_SDVO: | 753 | case INTEL_OUTPUT_SDVO: |
754 | case INTEL_OUTPUT_HDMI: | ||
754 | is_sdvo = true; | 755 | is_sdvo = true; |
755 | break; | 756 | break; |
756 | case INTEL_OUTPUT_DVO: | 757 | case INTEL_OUTPUT_DVO: |
@@ -986,19 +987,17 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
986 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; | 987 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; |
987 | uint32_t temp; | 988 | uint32_t temp; |
988 | size_t addr; | 989 | size_t addr; |
990 | int ret; | ||
989 | 991 | ||
990 | DRM_DEBUG("\n"); | 992 | DRM_DEBUG("\n"); |
991 | 993 | ||
992 | /* if we want to turn off the cursor ignore width and height */ | 994 | /* if we want to turn off the cursor ignore width and height */ |
993 | if (!handle) { | 995 | if (!handle) { |
994 | DRM_DEBUG("cursor off\n"); | 996 | DRM_DEBUG("cursor off\n"); |
995 | /* turn of the cursor */ | 997 | temp = CURSOR_MODE_DISABLE; |
996 | temp = 0; | 998 | addr = 0; |
997 | temp |= CURSOR_MODE_DISABLE; | 999 | bo = NULL; |
998 | 1000 | goto finish; | |
999 | I915_WRITE(control, temp); | ||
1000 | I915_WRITE(base, 0); | ||
1001 | return 0; | ||
1002 | } | 1001 | } |
1003 | 1002 | ||
1004 | /* Currently we only support 64x64 cursors */ | 1003 | /* Currently we only support 64x64 cursors */ |
@@ -1025,15 +1024,30 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, | |||
1025 | addr = obj_priv->gtt_offset; | 1024 | addr = obj_priv->gtt_offset; |
1026 | } | 1025 | } |
1027 | 1026 | ||
1028 | intel_crtc->cursor_addr = addr; | 1027 | ret = i915_gem_object_pin(bo, PAGE_SIZE); |
1028 | if (ret) { | ||
1029 | DRM_ERROR("failed to pin cursor bo\n"); | ||
1030 | drm_gem_object_unreference(bo); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | |||
1029 | temp = 0; | 1034 | temp = 0; |
1030 | /* set the pipe for the cursor */ | 1035 | /* set the pipe for the cursor */ |
1031 | temp |= (pipe << 28); | 1036 | temp |= (pipe << 28); |
1032 | temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | 1037 | temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; |
1033 | 1038 | ||
1039 | finish: | ||
1034 | I915_WRITE(control, temp); | 1040 | I915_WRITE(control, temp); |
1035 | I915_WRITE(base, addr); | 1041 | I915_WRITE(base, addr); |
1036 | 1042 | ||
1043 | if (intel_crtc->cursor_bo) { | ||
1044 | i915_gem_object_unpin(intel_crtc->cursor_bo); | ||
1045 | drm_gem_object_unreference(intel_crtc->cursor_bo); | ||
1046 | } | ||
1047 | |||
1048 | intel_crtc->cursor_addr = addr; | ||
1049 | intel_crtc->cursor_bo = bo; | ||
1050 | |||
1037 | return 0; | 1051 | return 0; |
1038 | } | 1052 | } |
1039 | 1053 | ||
@@ -1430,12 +1444,19 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
1430 | intel_lvds_init(dev); | 1444 | intel_lvds_init(dev); |
1431 | 1445 | ||
1432 | if (IS_I9XX(dev)) { | 1446 | if (IS_I9XX(dev)) { |
1433 | intel_sdvo_init(dev, SDVOB); | 1447 | int found; |
1434 | intel_sdvo_init(dev, SDVOC); | 1448 | |
1449 | found = intel_sdvo_init(dev, SDVOB); | ||
1450 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
1451 | intel_hdmi_init(dev, SDVOB); | ||
1452 | |||
1453 | found = intel_sdvo_init(dev, SDVOC); | ||
1454 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
1455 | intel_hdmi_init(dev, SDVOC); | ||
1435 | } else | 1456 | } else |
1436 | intel_dvo_init(dev); | 1457 | intel_dvo_init(dev); |
1437 | 1458 | ||
1438 | if (IS_I9XX(dev) && !IS_I915G(dev)) | 1459 | if (IS_I9XX(dev) && IS_MOBILE(dev)) |
1439 | intel_tv_init(dev); | 1460 | intel_tv_init(dev); |
1440 | 1461 | ||
1441 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 1462 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
@@ -1445,6 +1466,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
1445 | 1466 | ||
1446 | /* valid crtcs */ | 1467 | /* valid crtcs */ |
1447 | switch(intel_output->type) { | 1468 | switch(intel_output->type) { |
1469 | case INTEL_OUTPUT_HDMI: | ||
1470 | crtc_mask = ((1 << 0)| | ||
1471 | (1 << 1)); | ||
1472 | clone_mask = ((1 << INTEL_OUTPUT_HDMI)); | ||
1473 | break; | ||
1448 | case INTEL_OUTPUT_DVO: | 1474 | case INTEL_OUTPUT_DVO: |
1449 | case INTEL_OUTPUT_SDVO: | 1475 | case INTEL_OUTPUT_SDVO: |
1450 | crtc_mask = ((1 << 0)| | 1476 | crtc_mask = ((1 << 0)| |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 407edd5bf582..8a4cc50c5b4e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define INTEL_OUTPUT_SDVO 3 | 53 | #define INTEL_OUTPUT_SDVO 3 |
54 | #define INTEL_OUTPUT_LVDS 4 | 54 | #define INTEL_OUTPUT_LVDS 4 |
55 | #define INTEL_OUTPUT_TVOUT 5 | 55 | #define INTEL_OUTPUT_TVOUT 5 |
56 | #define INTEL_OUTPUT_HDMI 6 | ||
56 | 57 | ||
57 | #define INTEL_DVO_CHIP_NONE 0 | 58 | #define INTEL_DVO_CHIP_NONE 0 |
58 | #define INTEL_DVO_CHIP_LVDS 1 | 59 | #define INTEL_DVO_CHIP_LVDS 1 |
@@ -88,6 +89,7 @@ struct intel_crtc { | |||
88 | struct drm_crtc base; | 89 | struct drm_crtc base; |
89 | int pipe; | 90 | int pipe; |
90 | int plane; | 91 | int plane; |
92 | struct drm_gem_object *cursor_bo; | ||
91 | uint32_t cursor_addr; | 93 | uint32_t cursor_addr; |
92 | u8 lut_r[256], lut_g[256], lut_b[256]; | 94 | u8 lut_r[256], lut_g[256], lut_b[256]; |
93 | int dpms_mode; | 95 | int dpms_mode; |
@@ -108,7 +110,8 @@ int intel_ddc_get_modes(struct intel_output *intel_output); | |||
108 | extern bool intel_ddc_probe(struct intel_output *intel_output); | 110 | extern bool intel_ddc_probe(struct intel_output *intel_output); |
109 | 111 | ||
110 | extern void intel_crt_init(struct drm_device *dev); | 112 | extern void intel_crt_init(struct drm_device *dev); |
111 | extern void intel_sdvo_init(struct drm_device *dev, int output_device); | 113 | extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg); |
114 | extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | ||
112 | extern void intel_dvo_init(struct drm_device *dev); | 115 | extern void intel_dvo_init(struct drm_device *dev); |
113 | extern void intel_tv_init(struct drm_device *dev); | 116 | extern void intel_tv_init(struct drm_device *dev); |
114 | extern void intel_lvds_init(struct drm_device *dev); | 117 | extern void intel_lvds_init(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c new file mode 100644 index 000000000000..b06a4a3ff08d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * Copyright 2006 Dave Airlie <airlied@linux.ie> | ||
3 | * Copyright © 2006-2009 Intel Corporation | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the next | ||
13 | * paragraph) shall be included in all copies or substantial portions of the | ||
14 | * Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
22 | * DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | * Authors: | ||
25 | * Eric Anholt <eric@anholt.net> | ||
26 | * Jesse Barnes <jesse.barnes@intel.com> | ||
27 | */ | ||
28 | |||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include "drmP.h" | ||
32 | #include "drm.h" | ||
33 | #include "drm_crtc.h" | ||
34 | #include "intel_drv.h" | ||
35 | #include "i915_drm.h" | ||
36 | #include "i915_drv.h" | ||
37 | |||
38 | struct intel_hdmi_priv { | ||
39 | u32 sdvox_reg; | ||
40 | u32 save_SDVOX; | ||
41 | int has_hdmi_sink; | ||
42 | }; | ||
43 | |||
44 | static void intel_hdmi_mode_set(struct drm_encoder *encoder, | ||
45 | struct drm_display_mode *mode, | ||
46 | struct drm_display_mode *adjusted_mode) | ||
47 | { | ||
48 | struct drm_device *dev = encoder->dev; | ||
49 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
50 | struct drm_crtc *crtc = encoder->crtc; | ||
51 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
52 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
53 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
54 | u32 sdvox; | ||
55 | |||
56 | sdvox = SDVO_ENCODING_HDMI | | ||
57 | SDVO_BORDER_ENABLE | | ||
58 | SDVO_VSYNC_ACTIVE_HIGH | | ||
59 | SDVO_HSYNC_ACTIVE_HIGH; | ||
60 | |||
61 | if (hdmi_priv->has_hdmi_sink) | ||
62 | sdvox |= SDVO_AUDIO_ENABLE; | ||
63 | |||
64 | if (intel_crtc->pipe == 1) | ||
65 | sdvox |= SDVO_PIPE_B_SELECT; | ||
66 | |||
67 | I915_WRITE(hdmi_priv->sdvox_reg, sdvox); | ||
68 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
69 | } | ||
70 | |||
71 | static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) | ||
72 | { | ||
73 | struct drm_device *dev = encoder->dev; | ||
74 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
75 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
76 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
77 | u32 temp; | ||
78 | |||
79 | if (mode != DRM_MODE_DPMS_ON) { | ||
80 | temp = I915_READ(hdmi_priv->sdvox_reg); | ||
81 | I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); | ||
82 | } else { | ||
83 | temp = I915_READ(hdmi_priv->sdvox_reg); | ||
84 | I915_WRITE(hdmi_priv->sdvox_reg, temp | SDVO_ENABLE); | ||
85 | } | ||
86 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
87 | } | ||
88 | |||
89 | static void intel_hdmi_save(struct drm_connector *connector) | ||
90 | { | ||
91 | struct drm_device *dev = connector->dev; | ||
92 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
93 | struct intel_output *intel_output = to_intel_output(connector); | ||
94 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
95 | |||
96 | hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg); | ||
97 | } | ||
98 | |||
99 | static void intel_hdmi_restore(struct drm_connector *connector) | ||
100 | { | ||
101 | struct drm_device *dev = connector->dev; | ||
102 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
103 | struct intel_output *intel_output = to_intel_output(connector); | ||
104 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
105 | |||
106 | I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX); | ||
107 | POSTING_READ(hdmi_priv->sdvox_reg); | ||
108 | } | ||
109 | |||
110 | static int intel_hdmi_mode_valid(struct drm_connector *connector, | ||
111 | struct drm_display_mode *mode) | ||
112 | { | ||
113 | if (mode->clock > 165000) | ||
114 | return MODE_CLOCK_HIGH; | ||
115 | if (mode->clock < 20000) | ||
116 | return MODE_CLOCK_HIGH; | ||
117 | |||
118 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
119 | return MODE_NO_DBLESCAN; | ||
120 | |||
121 | return MODE_OK; | ||
122 | } | ||
123 | |||
124 | static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | ||
125 | struct drm_display_mode *mode, | ||
126 | struct drm_display_mode *adjusted_mode) | ||
127 | { | ||
128 | return true; | ||
129 | } | ||
130 | |||
131 | static enum drm_connector_status | ||
132 | intel_hdmi_detect(struct drm_connector *connector) | ||
133 | { | ||
134 | struct drm_device *dev = connector->dev; | ||
135 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
136 | struct intel_output *intel_output = to_intel_output(connector); | ||
137 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | ||
138 | u32 temp, bit; | ||
139 | |||
140 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
141 | |||
142 | I915_WRITE(PORT_HOTPLUG_EN, | ||
143 | temp | | ||
144 | HDMIB_HOTPLUG_INT_EN | | ||
145 | HDMIC_HOTPLUG_INT_EN | | ||
146 | HDMID_HOTPLUG_INT_EN); | ||
147 | |||
148 | POSTING_READ(PORT_HOTPLUG_EN); | ||
149 | |||
150 | switch (hdmi_priv->sdvox_reg) { | ||
151 | case SDVOB: | ||
152 | bit = HDMIB_HOTPLUG_INT_STATUS; | ||
153 | break; | ||
154 | case SDVOC: | ||
155 | bit = HDMIC_HOTPLUG_INT_STATUS; | ||
156 | break; | ||
157 | default: | ||
158 | return connector_status_unknown; | ||
159 | } | ||
160 | |||
161 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) | ||
162 | return connector_status_connected; | ||
163 | else | ||
164 | return connector_status_disconnected; | ||
165 | } | ||
166 | |||
167 | static int intel_hdmi_get_modes(struct drm_connector *connector) | ||
168 | { | ||
169 | struct intel_output *intel_output = to_intel_output(connector); | ||
170 | |||
171 | /* We should parse the EDID data and find out if it's an HDMI sink so | ||
172 | * we can send audio to it. | ||
173 | */ | ||
174 | |||
175 | return intel_ddc_get_modes(intel_output); | ||
176 | } | ||
177 | |||
178 | static void intel_hdmi_destroy(struct drm_connector *connector) | ||
179 | { | ||
180 | struct intel_output *intel_output = to_intel_output(connector); | ||
181 | |||
182 | if (intel_output->i2c_bus) | ||
183 | intel_i2c_destroy(intel_output->i2c_bus); | ||
184 | drm_sysfs_connector_remove(connector); | ||
185 | drm_connector_cleanup(connector); | ||
186 | kfree(intel_output); | ||
187 | } | ||
188 | |||
189 | static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { | ||
190 | .dpms = intel_hdmi_dpms, | ||
191 | .mode_fixup = intel_hdmi_mode_fixup, | ||
192 | .prepare = intel_encoder_prepare, | ||
193 | .mode_set = intel_hdmi_mode_set, | ||
194 | .commit = intel_encoder_commit, | ||
195 | }; | ||
196 | |||
197 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | ||
198 | .save = intel_hdmi_save, | ||
199 | .restore = intel_hdmi_restore, | ||
200 | .detect = intel_hdmi_detect, | ||
201 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
202 | .destroy = intel_hdmi_destroy, | ||
203 | }; | ||
204 | |||
205 | static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { | ||
206 | .get_modes = intel_hdmi_get_modes, | ||
207 | .mode_valid = intel_hdmi_mode_valid, | ||
208 | .best_encoder = intel_best_encoder, | ||
209 | }; | ||
210 | |||
211 | static void intel_hdmi_enc_destroy(struct drm_encoder *encoder) | ||
212 | { | ||
213 | drm_encoder_cleanup(encoder); | ||
214 | } | ||
215 | |||
216 | static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { | ||
217 | .destroy = intel_hdmi_enc_destroy, | ||
218 | }; | ||
219 | |||
220 | |||
221 | void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) | ||
222 | { | ||
223 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
224 | struct drm_connector *connector; | ||
225 | struct intel_output *intel_output; | ||
226 | struct intel_hdmi_priv *hdmi_priv; | ||
227 | |||
228 | intel_output = kcalloc(sizeof(struct intel_output) + | ||
229 | sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); | ||
230 | if (!intel_output) | ||
231 | return; | ||
232 | hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1); | ||
233 | |||
234 | connector = &intel_output->base; | ||
235 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | ||
236 | DRM_MODE_CONNECTOR_DVID); | ||
237 | drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); | ||
238 | |||
239 | intel_output->type = INTEL_OUTPUT_HDMI; | ||
240 | |||
241 | connector->interlace_allowed = 0; | ||
242 | connector->doublescan_allowed = 0; | ||
243 | |||
244 | /* Set up the DDC bus. */ | ||
245 | if (sdvox_reg == SDVOB) | ||
246 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); | ||
247 | else | ||
248 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); | ||
249 | |||
250 | if (!intel_output->ddc_bus) | ||
251 | goto err_connector; | ||
252 | |||
253 | hdmi_priv->sdvox_reg = sdvox_reg; | ||
254 | intel_output->dev_priv = hdmi_priv; | ||
255 | |||
256 | drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs, | ||
257 | DRM_MODE_ENCODER_TMDS); | ||
258 | drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs); | ||
259 | |||
260 | drm_mode_connector_attach_encoder(&intel_output->base, | ||
261 | &intel_output->enc); | ||
262 | drm_sysfs_connector_add(connector); | ||
263 | |||
264 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | ||
265 | * 0xd. Failure to do so will result in spurious interrupts being | ||
266 | * generated on the port when a cable is not attached. | ||
267 | */ | ||
268 | if (IS_G4X(dev) && !IS_GM45(dev)) { | ||
269 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | ||
270 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | ||
271 | } | ||
272 | |||
273 | return; | ||
274 | |||
275 | err_connector: | ||
276 | drm_connector_cleanup(connector); | ||
277 | kfree(intel_output); | ||
278 | |||
279 | return; | ||
280 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index fbbaa4f414a0..407215469102 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -978,7 +978,7 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { | |||
978 | }; | 978 | }; |
979 | 979 | ||
980 | 980 | ||
981 | void intel_sdvo_init(struct drm_device *dev, int output_device) | 981 | bool intel_sdvo_init(struct drm_device *dev, int output_device) |
982 | { | 982 | { |
983 | struct drm_connector *connector; | 983 | struct drm_connector *connector; |
984 | struct intel_output *intel_output; | 984 | struct intel_output *intel_output; |
@@ -991,7 +991,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) | |||
991 | 991 | ||
992 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 992 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
993 | if (!intel_output) { | 993 | if (!intel_output) { |
994 | return; | 994 | return false; |
995 | } | 995 | } |
996 | 996 | ||
997 | connector = &intel_output->base; | 997 | connector = &intel_output->base; |
@@ -1116,7 +1116,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) | |||
1116 | 1116 | ||
1117 | intel_output->ddc_bus = i2cbus; | 1117 | intel_output->ddc_bus = i2cbus; |
1118 | 1118 | ||
1119 | return; | 1119 | return true; |
1120 | 1120 | ||
1121 | err_i2c: | 1121 | err_i2c: |
1122 | intel_i2c_destroy(intel_output->i2c_bus); | 1122 | intel_i2c_destroy(intel_output->i2c_bus); |
@@ -1124,5 +1124,5 @@ err_connector: | |||
1124 | drm_connector_cleanup(connector); | 1124 | drm_connector_cleanup(connector); |
1125 | kfree(intel_output); | 1125 | kfree(intel_output); |
1126 | 1126 | ||
1127 | return; | 1127 | return false; |
1128 | } | 1128 | } |