diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-09 11:52:28 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-09 11:52:28 -0500 |
| commit | ff7473300d429118aa97368ba5a16bc63aecfc75 (patch) | |
| tree | 42c2b4714e048a0613468ced95e20c8081ee7797 | |
| parent | d7c41b616518457e3bfece12e3f59f15d7450eeb (diff) | |
| parent | d2f59357700487a8b944f4f7777d1e97cf5ea2ed (diff) | |
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
drm/i915: select framebuffer support automatically
drm/i915: add get_vblank_counter function for GM45
drm/i915: capture last_vblank count at IRQ uninstall time too
drm/i915: Unlock mutex on i915_gem_fault() error path
drm/i915: Quiet the message on get/setparam ioctl with an unknown value.
drm/i915: skip LVDS initialization on Apple Mac Mini
drm/i915: sync SDVO code with stable userland modesetting driver
drm/i915: Unref the object after failing to set tiling mode.
drm/i915: add fence register management to execbuf
drm/i915: Return error from i915_gem_object_get_fence_reg() when failing.
drm/i915: Set up an MTRR covering the GTT at driver load.
drm/i915: Skip SDVO/HDMI init when the chipset tells us it's not present.
drm/i915: Suppress GEM teardown on X Server exit in KMS mode.
drm/radeon: fix ioremap conflict with AGP mappings
i915: fix unneeded locking in i915 LVDS get modes code.
| -rw-r--r-- | drivers/gpu/drm/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_irq.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_memory.c | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 47 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 83 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_tiling.c | 91 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 49 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 870 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo_regs.h | 404 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cp.c | 6 | ||||
| -rw-r--r-- | drivers/video/Kconfig | 6 | ||||
| -rw-r--r-- | include/drm/i915_drm.h | 2 |
18 files changed, 1428 insertions, 193 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 5130b72d593c..4be3acbaaf9a 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -70,7 +70,7 @@ config DRM_I915 | |||
| 70 | select FB_CFB_FILLRECT | 70 | select FB_CFB_FILLRECT |
| 71 | select FB_CFB_COPYAREA | 71 | select FB_CFB_COPYAREA |
| 72 | select FB_CFB_IMAGEBLIT | 72 | select FB_CFB_IMAGEBLIT |
| 73 | depends on FB | 73 | select FB |
| 74 | tristate "i915 driver" | 74 | tristate "i915 driver" |
| 75 | help | 75 | help |
| 76 | Choose this option if you have a system that has Intel 830M, 845G, | 76 | Choose this option if you have a system that has Intel 830M, 845G, |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 69aa0ab28403..3795dbc0f50c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -276,6 +276,7 @@ int drm_irq_uninstall(struct drm_device * dev) | |||
| 276 | for (i = 0; i < dev->num_crtcs; i++) { | 276 | for (i = 0; i < dev->num_crtcs; i++) { |
| 277 | DRM_WAKEUP(&dev->vbl_queue[i]); | 277 | DRM_WAKEUP(&dev->vbl_queue[i]); |
| 278 | dev->vblank_enabled[i] = 0; | 278 | dev->vblank_enabled[i] = 0; |
| 279 | dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i); | ||
| 279 | } | 280 | } |
| 280 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 281 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
| 281 | 282 | ||
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index 803bc9e7ce3c..bcc869bc4092 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c | |||
| @@ -171,9 +171,14 @@ EXPORT_SYMBOL(drm_core_ioremap); | |||
| 171 | 171 | ||
| 172 | void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev) | 172 | void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev) |
| 173 | { | 173 | { |
| 174 | map->handle = ioremap_wc(map->offset, map->size); | 174 | if (drm_core_has_AGP(dev) && |
| 175 | dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) | ||
| 176 | map->handle = agp_remap(map->offset, map->size, dev); | ||
| 177 | else | ||
| 178 | map->handle = ioremap_wc(map->offset, map->size); | ||
| 175 | } | 179 | } |
| 176 | EXPORT_SYMBOL(drm_core_ioremap_wc); | 180 | EXPORT_SYMBOL(drm_core_ioremap_wc); |
| 181 | |||
| 177 | void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) | 182 | void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) |
| 178 | { | 183 | { |
| 179 | if (!map->handle || !map->size) | 184 | if (!map->handle || !map->size) |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ee64b7301f67..81f1cff56fd5 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -731,8 +731,11 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
| 731 | case I915_PARAM_HAS_GEM: | 731 | case I915_PARAM_HAS_GEM: |
| 732 | value = dev_priv->has_gem; | 732 | value = dev_priv->has_gem; |
| 733 | break; | 733 | break; |
| 734 | case I915_PARAM_NUM_FENCES_AVAIL: | ||
| 735 | value = dev_priv->num_fence_regs - dev_priv->fence_reg_start; | ||
| 736 | break; | ||
| 734 | default: | 737 | default: |
| 735 | DRM_ERROR("Unknown parameter %d\n", param->param); | 738 | DRM_DEBUG("Unknown parameter %d\n", param->param); |
| 736 | return -EINVAL; | 739 | return -EINVAL; |
| 737 | } | 740 | } |
| 738 | 741 | ||
| @@ -764,8 +767,15 @@ static int i915_setparam(struct drm_device *dev, void *data, | |||
| 764 | case I915_SETPARAM_ALLOW_BATCHBUFFER: | 767 | case I915_SETPARAM_ALLOW_BATCHBUFFER: |
| 765 | dev_priv->allow_batchbuffer = param->value; | 768 | dev_priv->allow_batchbuffer = param->value; |
| 766 | break; | 769 | break; |
| 770 | case I915_SETPARAM_NUM_USED_FENCES: | ||
| 771 | if (param->value > dev_priv->num_fence_regs || | ||
| 772 | param->value < 0) | ||
| 773 | return -EINVAL; | ||
| 774 | /* Userspace can use first N regs */ | ||
| 775 | dev_priv->fence_reg_start = param->value; | ||
| 776 | break; | ||
| 767 | default: | 777 | default: |
| 768 | DRM_ERROR("unknown parameter %d\n", param->param); | 778 | DRM_DEBUG("unknown parameter %d\n", param->param); |
| 769 | return -EINVAL; | 779 | return -EINVAL; |
| 770 | } | 780 | } |
| 771 | 781 | ||
| @@ -966,10 +976,6 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 966 | if (ret) | 976 | if (ret) |
| 967 | goto kfree_devname; | 977 | goto kfree_devname; |
| 968 | 978 | ||
| 969 | dev_priv->mm.gtt_mapping = | ||
| 970 | io_mapping_create_wc(dev->agp->base, | ||
| 971 | dev->agp->agp_info.aper_size * 1024*1024); | ||
| 972 | |||
| 973 | /* Allow hardware batchbuffers unless told otherwise. | 979 | /* Allow hardware batchbuffers unless told otherwise. |
| 974 | */ | 980 | */ |
| 975 | dev_priv->allow_batchbuffer = 1; | 981 | dev_priv->allow_batchbuffer = 1; |
| @@ -1081,6 +1087,23 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1081 | goto free_priv; | 1087 | goto free_priv; |
| 1082 | } | 1088 | } |
| 1083 | 1089 | ||
| 1090 | dev_priv->mm.gtt_mapping = | ||
| 1091 | io_mapping_create_wc(dev->agp->base, | ||
| 1092 | dev->agp->agp_info.aper_size * 1024*1024); | ||
| 1093 | /* Set up a WC MTRR for non-PAT systems. This is more common than | ||
| 1094 | * one would think, because the kernel disables PAT on first | ||
| 1095 | * generation Core chips because WC PAT gets overridden by a UC | ||
| 1096 | * MTRR if present. Even if a UC MTRR isn't present. | ||
| 1097 | */ | ||
| 1098 | dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base, | ||
| 1099 | dev->agp->agp_info.aper_size * | ||
| 1100 | 1024 * 1024, | ||
| 1101 | MTRR_TYPE_WRCOMB, 1); | ||
| 1102 | if (dev_priv->mm.gtt_mtrr < 0) { | ||
| 1103 | DRM_INFO("MTRR allocation failed\n. Graphics " | ||
| 1104 | "performance may suffer.\n"); | ||
| 1105 | } | ||
| 1106 | |||
| 1084 | #ifdef CONFIG_HIGHMEM64G | 1107 | #ifdef CONFIG_HIGHMEM64G |
| 1085 | /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */ | 1108 | /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */ |
| 1086 | dev_priv->has_gem = 0; | 1109 | dev_priv->has_gem = 0; |
| @@ -1089,6 +1112,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1089 | dev_priv->has_gem = 1; | 1112 | dev_priv->has_gem = 1; |
| 1090 | #endif | 1113 | #endif |
| 1091 | 1114 | ||
| 1115 | dev->driver->get_vblank_counter = i915_get_vblank_counter; | ||
| 1116 | if (IS_GM45(dev)) | ||
| 1117 | dev->driver->get_vblank_counter = gm45_get_vblank_counter; | ||
| 1118 | |||
| 1092 | i915_gem_load(dev); | 1119 | i915_gem_load(dev); |
| 1093 | 1120 | ||
| 1094 | /* Init HWS */ | 1121 | /* Init HWS */ |
| @@ -1145,8 +1172,14 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1145 | { | 1172 | { |
| 1146 | struct drm_i915_private *dev_priv = dev->dev_private; | 1173 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1147 | 1174 | ||
| 1175 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
| 1176 | if (dev_priv->mm.gtt_mtrr >= 0) { | ||
| 1177 | mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, | ||
| 1178 | dev->agp->agp_info.aper_size * 1024 * 1024); | ||
| 1179 | dev_priv->mm.gtt_mtrr = -1; | ||
| 1180 | } | ||
| 1181 | |||
| 1148 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1182 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1149 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
| 1150 | drm_irq_uninstall(dev); | 1183 | drm_irq_uninstall(dev); |
| 1151 | } | 1184 | } |
| 1152 | 1185 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f8b3df0926c0..aac12ee31a46 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -112,7 +112,6 @@ static struct drm_driver driver = { | |||
| 112 | .suspend = i915_suspend, | 112 | .suspend = i915_suspend, |
| 113 | .resume = i915_resume, | 113 | .resume = i915_resume, |
| 114 | .device_is_agp = i915_driver_device_is_agp, | 114 | .device_is_agp = i915_driver_device_is_agp, |
| 115 | .get_vblank_counter = i915_get_vblank_counter, | ||
| 116 | .enable_vblank = i915_enable_vblank, | 115 | .enable_vblank = i915_enable_vblank, |
| 117 | .disable_vblank = i915_disable_vblank, | 116 | .disable_vblank = i915_disable_vblank, |
| 118 | .irq_preinstall = i915_driver_irq_preinstall, | 117 | .irq_preinstall = i915_driver_irq_preinstall, |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e13518252007..7325363164f8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -284,6 +284,7 @@ typedef struct drm_i915_private { | |||
| 284 | struct drm_mm gtt_space; | 284 | struct drm_mm gtt_space; |
| 285 | 285 | ||
| 286 | struct io_mapping *gtt_mapping; | 286 | struct io_mapping *gtt_mapping; |
| 287 | int gtt_mtrr; | ||
| 287 | 288 | ||
| 288 | /** | 289 | /** |
| 289 | * List of objects currently involved in rendering from the | 290 | * List of objects currently involved in rendering from the |
| @@ -534,6 +535,7 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, | |||
| 534 | extern int i915_enable_vblank(struct drm_device *dev, int crtc); | 535 | extern int i915_enable_vblank(struct drm_device *dev, int crtc); |
| 535 | extern void i915_disable_vblank(struct drm_device *dev, int crtc); | 536 | extern void i915_disable_vblank(struct drm_device *dev, int crtc); |
| 536 | extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); | 537 | extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); |
| 538 | extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc); | ||
| 537 | extern int i915_vblank_swap(struct drm_device *dev, void *data, | 539 | extern int i915_vblank_swap(struct drm_device *dev, void *data, |
| 538 | struct drm_file *file_priv); | 540 | struct drm_file *file_priv); |
| 539 | extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask); | 541 | extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask); |
| @@ -601,6 +603,7 @@ int i915_gem_init_object(struct drm_gem_object *obj); | |||
| 601 | void i915_gem_free_object(struct drm_gem_object *obj); | 603 | void i915_gem_free_object(struct drm_gem_object *obj); |
| 602 | int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); | 604 | int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); |
| 603 | void i915_gem_object_unpin(struct drm_gem_object *obj); | 605 | void i915_gem_object_unpin(struct drm_gem_object *obj); |
| 606 | int i915_gem_object_unbind(struct drm_gem_object *obj); | ||
| 604 | void i915_gem_lastclose(struct drm_device *dev); | 607 | void i915_gem_lastclose(struct drm_device *dev); |
| 605 | uint32_t i915_get_gem_seqno(struct drm_device *dev); | 608 | uint32_t i915_get_gem_seqno(struct drm_device *dev); |
| 606 | void i915_gem_retire_requests(struct drm_device *dev); | 609 | void i915_gem_retire_requests(struct drm_device *dev); |
| @@ -784,6 +787,11 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
| 784 | IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) | 787 | IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev)) |
| 785 | 788 | ||
| 786 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) | 789 | #define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev)) |
| 790 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte | ||
| 791 | * rows, which changed the alignment requirements and fence programming. | ||
| 792 | */ | ||
| 793 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ | ||
| 794 | IS_I915GM(dev))) | ||
| 787 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) | 795 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev)) |
| 788 | 796 | ||
| 789 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 797 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index debad5c04cc0..1441831fa06e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -52,7 +52,7 @@ static void i915_gem_object_free_page_list(struct drm_gem_object *obj); | |||
| 52 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); | 52 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); |
| 53 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, | 53 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, |
| 54 | unsigned alignment); | 54 | unsigned alignment); |
| 55 | static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj); | 55 | static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write); |
| 56 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); | 56 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); |
| 57 | static int i915_gem_evict_something(struct drm_device *dev); | 57 | static int i915_gem_evict_something(struct drm_device *dev); |
| 58 | static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | 58 | static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, |
| @@ -567,6 +567,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 567 | pgoff_t page_offset; | 567 | pgoff_t page_offset; |
| 568 | unsigned long pfn; | 568 | unsigned long pfn; |
| 569 | int ret = 0; | 569 | int ret = 0; |
| 570 | bool write = !!(vmf->flags & FAULT_FLAG_WRITE); | ||
| 570 | 571 | ||
| 571 | /* We don't use vmf->pgoff since that has the fake offset */ | 572 | /* We don't use vmf->pgoff since that has the fake offset */ |
| 572 | page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> | 573 | page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> |
| @@ -585,8 +586,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 585 | 586 | ||
| 586 | /* Need a new fence register? */ | 587 | /* Need a new fence register? */ |
| 587 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE && | 588 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE && |
| 588 | obj_priv->tiling_mode != I915_TILING_NONE) | 589 | obj_priv->tiling_mode != I915_TILING_NONE) { |
| 589 | i915_gem_object_get_fence_reg(obj); | 590 | ret = i915_gem_object_get_fence_reg(obj, write); |
| 591 | if (ret) { | ||
| 592 | mutex_unlock(&dev->struct_mutex); | ||
| 593 | return VM_FAULT_SIGBUS; | ||
| 594 | } | ||
| 595 | } | ||
| 590 | 596 | ||
| 591 | pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + | 597 | pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + |
| 592 | page_offset; | 598 | page_offset; |
| @@ -1211,7 +1217,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) | |||
| 1211 | /** | 1217 | /** |
| 1212 | * Unbinds an object from the GTT aperture. | 1218 | * Unbinds an object from the GTT aperture. |
| 1213 | */ | 1219 | */ |
| 1214 | static int | 1220 | int |
| 1215 | i915_gem_object_unbind(struct drm_gem_object *obj) | 1221 | i915_gem_object_unbind(struct drm_gem_object *obj) |
| 1216 | { | 1222 | { |
| 1217 | struct drm_device *dev = obj->dev; | 1223 | struct drm_device *dev = obj->dev; |
| @@ -1445,21 +1451,26 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1445 | drm_i915_private_t *dev_priv = dev->dev_private; | 1451 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 1446 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1452 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1447 | int regnum = obj_priv->fence_reg; | 1453 | int regnum = obj_priv->fence_reg; |
| 1454 | int tile_width; | ||
| 1448 | uint32_t val; | 1455 | uint32_t val; |
| 1449 | uint32_t pitch_val; | 1456 | uint32_t pitch_val; |
| 1450 | 1457 | ||
| 1451 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1458 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
| 1452 | (obj_priv->gtt_offset & (obj->size - 1))) { | 1459 | (obj_priv->gtt_offset & (obj->size - 1))) { |
| 1453 | WARN(1, "%s: object not 1M or size aligned\n", __func__); | 1460 | WARN(1, "%s: object 0x%08x not 1M or size (0x%x) aligned\n", |
| 1461 | __func__, obj_priv->gtt_offset, obj->size); | ||
| 1454 | return; | 1462 | return; |
| 1455 | } | 1463 | } |
| 1456 | 1464 | ||
| 1457 | if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) || | 1465 | if (obj_priv->tiling_mode == I915_TILING_Y && |
| 1458 | IS_I945GM(dev) || | 1466 | HAS_128_BYTE_Y_TILING(dev)) |
| 1459 | IS_G33(dev))) | 1467 | tile_width = 128; |
| 1460 | pitch_val = (obj_priv->stride / 128) - 1; | ||
| 1461 | else | 1468 | else |
| 1462 | pitch_val = (obj_priv->stride / 512) - 1; | 1469 | tile_width = 512; |
| 1470 | |||
| 1471 | /* Note: pitch better be a power of two tile widths */ | ||
| 1472 | pitch_val = obj_priv->stride / tile_width; | ||
| 1473 | pitch_val = ffs(pitch_val) - 1; | ||
| 1463 | 1474 | ||
| 1464 | val = obj_priv->gtt_offset; | 1475 | val = obj_priv->gtt_offset; |
| 1465 | if (obj_priv->tiling_mode == I915_TILING_Y) | 1476 | if (obj_priv->tiling_mode == I915_TILING_Y) |
| @@ -1483,7 +1494,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1483 | 1494 | ||
| 1484 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1495 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
| 1485 | (obj_priv->gtt_offset & (obj->size - 1))) { | 1496 | (obj_priv->gtt_offset & (obj->size - 1))) { |
| 1486 | WARN(1, "%s: object not 1M or size aligned\n", __func__); | 1497 | WARN(1, "%s: object 0x%08x not 1M or size aligned\n", |
| 1498 | __func__, obj_priv->gtt_offset); | ||
| 1487 | return; | 1499 | return; |
| 1488 | } | 1500 | } |
| 1489 | 1501 | ||
| @@ -1503,6 +1515,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1503 | /** | 1515 | /** |
| 1504 | * i915_gem_object_get_fence_reg - set up a fence reg for an object | 1516 | * i915_gem_object_get_fence_reg - set up a fence reg for an object |
| 1505 | * @obj: object to map through a fence reg | 1517 | * @obj: object to map through a fence reg |
| 1518 | * @write: object is about to be written | ||
| 1506 | * | 1519 | * |
| 1507 | * When mapping objects through the GTT, userspace wants to be able to write | 1520 | * When mapping objects through the GTT, userspace wants to be able to write |
| 1508 | * to them without having to worry about swizzling if the object is tiled. | 1521 | * to them without having to worry about swizzling if the object is tiled. |
| @@ -1513,8 +1526,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1513 | * It then sets up the reg based on the object's properties: address, pitch | 1526 | * It then sets up the reg based on the object's properties: address, pitch |
| 1514 | * and tiling format. | 1527 | * and tiling format. |
| 1515 | */ | 1528 | */ |
| 1516 | static void | 1529 | static int |
| 1517 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | 1530 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) |
| 1518 | { | 1531 | { |
| 1519 | struct drm_device *dev = obj->dev; | 1532 | struct drm_device *dev = obj->dev; |
| 1520 | struct drm_i915_private *dev_priv = dev->dev_private; | 1533 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -1527,12 +1540,18 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | |||
| 1527 | WARN(1, "allocating a fence for non-tiled object?\n"); | 1540 | WARN(1, "allocating a fence for non-tiled object?\n"); |
| 1528 | break; | 1541 | break; |
| 1529 | case I915_TILING_X: | 1542 | case I915_TILING_X: |
| 1530 | WARN(obj_priv->stride & (512 - 1), | 1543 | if (!obj_priv->stride) |
| 1531 | "object is X tiled but has non-512B pitch\n"); | 1544 | return -EINVAL; |
| 1545 | WARN((obj_priv->stride & (512 - 1)), | ||
| 1546 | "object 0x%08x is X tiled but has non-512B pitch\n", | ||
| 1547 | obj_priv->gtt_offset); | ||
| 1532 | break; | 1548 | break; |
| 1533 | case I915_TILING_Y: | 1549 | case I915_TILING_Y: |
| 1534 | WARN(obj_priv->stride & (128 - 1), | 1550 | if (!obj_priv->stride) |
| 1535 | "object is Y tiled but has non-128B pitch\n"); | 1551 | return -EINVAL; |
| 1552 | WARN((obj_priv->stride & (128 - 1)), | ||
| 1553 | "object 0x%08x is Y tiled but has non-128B pitch\n", | ||
| 1554 | obj_priv->gtt_offset); | ||
| 1536 | break; | 1555 | break; |
| 1537 | } | 1556 | } |
| 1538 | 1557 | ||
| @@ -1563,10 +1582,11 @@ try_again: | |||
| 1563 | * objects to finish before trying again. | 1582 | * objects to finish before trying again. |
| 1564 | */ | 1583 | */ |
| 1565 | if (i == dev_priv->num_fence_regs) { | 1584 | if (i == dev_priv->num_fence_regs) { |
| 1566 | ret = i915_gem_object_wait_rendering(reg->obj); | 1585 | ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); |
| 1567 | if (ret) { | 1586 | if (ret) { |
| 1568 | WARN(ret, "wait_rendering failed: %d\n", ret); | 1587 | WARN(ret != -ERESTARTSYS, |
| 1569 | return; | 1588 | "switch to GTT domain failed: %d\n", ret); |
| 1589 | return ret; | ||
| 1570 | } | 1590 | } |
| 1571 | goto try_again; | 1591 | goto try_again; |
| 1572 | } | 1592 | } |
| @@ -1591,6 +1611,8 @@ try_again: | |||
| 1591 | i915_write_fence_reg(reg); | 1611 | i915_write_fence_reg(reg); |
| 1592 | else | 1612 | else |
| 1593 | i830_write_fence_reg(reg); | 1613 | i830_write_fence_reg(reg); |
| 1614 | |||
| 1615 | return 0; | ||
| 1594 | } | 1616 | } |
| 1595 | 1617 | ||
| 1596 | /** | 1618 | /** |
| @@ -1631,7 +1653,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
| 1631 | if (dev_priv->mm.suspended) | 1653 | if (dev_priv->mm.suspended) |
| 1632 | return -EBUSY; | 1654 | return -EBUSY; |
| 1633 | if (alignment == 0) | 1655 | if (alignment == 0) |
| 1634 | alignment = PAGE_SIZE; | 1656 | alignment = i915_gem_get_gtt_alignment(obj); |
| 1635 | if (alignment & (PAGE_SIZE - 1)) { | 1657 | if (alignment & (PAGE_SIZE - 1)) { |
| 1636 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); | 1658 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); |
| 1637 | return -EINVAL; | 1659 | return -EINVAL; |
| @@ -2652,6 +2674,14 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
| 2652 | DRM_ERROR("Failure to bind: %d", ret); | 2674 | DRM_ERROR("Failure to bind: %d", ret); |
| 2653 | return ret; | 2675 | return ret; |
| 2654 | } | 2676 | } |
| 2677 | /* | ||
| 2678 | * Pre-965 chips need a fence register set up in order to | ||
| 2679 | * properly handle tiled surfaces. | ||
| 2680 | */ | ||
| 2681 | if (!IS_I965G(dev) && | ||
| 2682 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
| 2683 | obj_priv->tiling_mode != I915_TILING_NONE) | ||
| 2684 | i915_gem_object_get_fence_reg(obj, true); | ||
| 2655 | } | 2685 | } |
| 2656 | obj_priv->pin_count++; | 2686 | obj_priv->pin_count++; |
| 2657 | 2687 | ||
| @@ -3229,10 +3259,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
| 3229 | dev_priv->mm.wedged = 0; | 3259 | dev_priv->mm.wedged = 0; |
| 3230 | } | 3260 | } |
| 3231 | 3261 | ||
| 3232 | dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, | ||
| 3233 | dev->agp->agp_info.aper_size | ||
| 3234 | * 1024 * 1024); | ||
| 3235 | |||
| 3236 | mutex_lock(&dev->struct_mutex); | 3262 | mutex_lock(&dev->struct_mutex); |
| 3237 | dev_priv->mm.suspended = 0; | 3263 | dev_priv->mm.suspended = 0; |
| 3238 | 3264 | ||
| @@ -3255,7 +3281,6 @@ int | |||
| 3255 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, | 3281 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, |
| 3256 | struct drm_file *file_priv) | 3282 | struct drm_file *file_priv) |
| 3257 | { | 3283 | { |
| 3258 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 3259 | int ret; | 3284 | int ret; |
| 3260 | 3285 | ||
| 3261 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 3286 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
| @@ -3264,7 +3289,6 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, | |||
| 3264 | ret = i915_gem_idle(dev); | 3289 | ret = i915_gem_idle(dev); |
| 3265 | drm_irq_uninstall(dev); | 3290 | drm_irq_uninstall(dev); |
| 3266 | 3291 | ||
| 3267 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
| 3268 | return ret; | 3292 | return ret; |
| 3269 | } | 3293 | } |
| 3270 | 3294 | ||
| @@ -3273,6 +3297,9 @@ i915_gem_lastclose(struct drm_device *dev) | |||
| 3273 | { | 3297 | { |
| 3274 | int ret; | 3298 | int ret; |
| 3275 | 3299 | ||
| 3300 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
| 3301 | return; | ||
| 3302 | |||
| 3276 | ret = i915_gem_idle(dev); | 3303 | ret = i915_gem_idle(dev); |
| 3277 | if (ret) | 3304 | if (ret) |
| 3278 | DRM_ERROR("failed to idle hardware: %d\n", ret); | 3305 | DRM_ERROR("failed to idle hardware: %d\n", ret); |
| @@ -3294,7 +3321,7 @@ i915_gem_load(struct drm_device *dev) | |||
| 3294 | /* Old X drivers will take 0-2 for front, back, depth buffers */ | 3321 | /* Old X drivers will take 0-2 for front, back, depth buffers */ |
| 3295 | dev_priv->fence_reg_start = 3; | 3322 | dev_priv->fence_reg_start = 3; |
| 3296 | 3323 | ||
| 3297 | if (IS_I965G(dev)) | 3324 | if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
| 3298 | dev_priv->num_fence_regs = 16; | 3325 | dev_priv->num_fence_regs = 16; |
| 3299 | else | 3326 | else |
| 3300 | dev_priv->num_fence_regs = 8; | 3327 | dev_priv->num_fence_regs = 8; |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 241f39b7f460..fa1685cba840 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -173,6 +173,73 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) | |||
| 173 | dev_priv->mm.bit_6_swizzle_y = swizzle_y; | 173 | dev_priv->mm.bit_6_swizzle_y = swizzle_y; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | |||
| 177 | /** | ||
| 178 | * Returns the size of the fence for a tiled object of the given size. | ||
| 179 | */ | ||
| 180 | static int | ||
| 181 | i915_get_fence_size(struct drm_device *dev, int size) | ||
| 182 | { | ||
| 183 | int i; | ||
| 184 | int start; | ||
| 185 | |||
| 186 | if (IS_I965G(dev)) { | ||
| 187 | /* The 965 can have fences at any page boundary. */ | ||
| 188 | return ALIGN(size, 4096); | ||
| 189 | } else { | ||
| 190 | /* Align the size to a power of two greater than the smallest | ||
| 191 | * fence size. | ||
| 192 | */ | ||
| 193 | if (IS_I9XX(dev)) | ||
| 194 | start = 1024 * 1024; | ||
| 195 | else | ||
| 196 | start = 512 * 1024; | ||
| 197 | |||
| 198 | for (i = start; i < size; i <<= 1) | ||
| 199 | ; | ||
| 200 | |||
| 201 | return i; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Check pitch constriants for all chips & tiling formats */ | ||
| 206 | static bool | ||
| 207 | i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | ||
| 208 | { | ||
| 209 | int tile_width; | ||
| 210 | |||
| 211 | /* Linear is always fine */ | ||
| 212 | if (tiling_mode == I915_TILING_NONE) | ||
| 213 | return true; | ||
| 214 | |||
| 215 | if (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)) | ||
| 216 | tile_width = 128; | ||
| 217 | else | ||
| 218 | tile_width = 512; | ||
| 219 | |||
| 220 | /* 965+ just needs multiples of tile width */ | ||
| 221 | if (IS_I965G(dev)) { | ||
| 222 | if (stride & (tile_width - 1)) | ||
| 223 | return false; | ||
| 224 | return true; | ||
| 225 | } | ||
| 226 | |||
| 227 | /* Pre-965 needs power of two tile widths */ | ||
| 228 | if (stride < tile_width) | ||
| 229 | return false; | ||
| 230 | |||
| 231 | if (stride & (stride - 1)) | ||
| 232 | return false; | ||
| 233 | |||
| 234 | /* We don't handle the aperture area covered by the fence being bigger | ||
| 235 | * than the object size. | ||
| 236 | */ | ||
| 237 | if (i915_get_fence_size(dev, size) != size) | ||
| 238 | return false; | ||
| 239 | |||
| 240 | return true; | ||
| 241 | } | ||
| 242 | |||
| 176 | /** | 243 | /** |
| 177 | * Sets the tiling mode of an object, returning the required swizzling of | 244 | * Sets the tiling mode of an object, returning the required swizzling of |
| 178 | * bit 6 of addresses in the object. | 245 | * bit 6 of addresses in the object. |
| @@ -191,6 +258,11 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
| 191 | return -EINVAL; | 258 | return -EINVAL; |
| 192 | obj_priv = obj->driver_private; | 259 | obj_priv = obj->driver_private; |
| 193 | 260 | ||
| 261 | if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { | ||
| 262 | drm_gem_object_unreference(obj); | ||
| 263 | return -EINVAL; | ||
| 264 | } | ||
| 265 | |||
| 194 | mutex_lock(&dev->struct_mutex); | 266 | mutex_lock(&dev->struct_mutex); |
| 195 | 267 | ||
| 196 | if (args->tiling_mode == I915_TILING_NONE) { | 268 | if (args->tiling_mode == I915_TILING_NONE) { |
| @@ -207,7 +279,24 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, | |||
| 207 | args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; | 279 | args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; |
| 208 | } | 280 | } |
| 209 | } | 281 | } |
| 210 | obj_priv->tiling_mode = args->tiling_mode; | 282 | if (args->tiling_mode != obj_priv->tiling_mode) { |
| 283 | int ret; | ||
| 284 | |||
| 285 | /* Unbind the object, as switching tiling means we're | ||
| 286 | * switching the cache organization due to fencing, probably. | ||
| 287 | */ | ||
| 288 | ret = i915_gem_object_unbind(obj); | ||
| 289 | if (ret != 0) { | ||
| 290 | WARN(ret != -ERESTARTSYS, | ||
| 291 | "failed to unbind object for tiling switch"); | ||
| 292 | args->tiling_mode = obj_priv->tiling_mode; | ||
| 293 | mutex_unlock(&dev->struct_mutex); | ||
| 294 | drm_gem_object_unreference(obj); | ||
| 295 | |||
| 296 | return ret; | ||
| 297 | } | ||
| 298 | obj_priv->tiling_mode = args->tiling_mode; | ||
| 299 | } | ||
| 211 | obj_priv->stride = args->stride; | 300 | obj_priv->stride = args->stride; |
| 212 | 301 | ||
| 213 | mutex_unlock(&dev->struct_mutex); | 302 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6290219de6c8..548ff2c66431 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -174,6 +174,19 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) | |||
| 174 | return count; | 174 | return count; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) | ||
| 178 | { | ||
| 179 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
| 180 | int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45; | ||
| 181 | |||
| 182 | if (!i915_pipe_enabled(dev, pipe)) { | ||
| 183 | DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe); | ||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | return I915_READ(reg); | ||
| 188 | } | ||
| 189 | |||
| 177 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 190 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
| 178 | { | 191 | { |
| 179 | struct drm_device *dev = (struct drm_device *) arg; | 192 | struct drm_device *dev = (struct drm_device *) arg; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 273162579e1b..9d6539a868b3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -186,12 +186,12 @@ | |||
| 186 | #define FENCE_REG_830_0 0x2000 | 186 | #define FENCE_REG_830_0 0x2000 |
| 187 | #define I830_FENCE_START_MASK 0x07f80000 | 187 | #define I830_FENCE_START_MASK 0x07f80000 |
| 188 | #define I830_FENCE_TILING_Y_SHIFT 12 | 188 | #define I830_FENCE_TILING_Y_SHIFT 12 |
| 189 | #define I830_FENCE_SIZE_BITS(size) ((get_order(size >> 19) - 1) << 8) | 189 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) |
| 190 | #define I830_FENCE_PITCH_SHIFT 4 | 190 | #define I830_FENCE_PITCH_SHIFT 4 |
| 191 | #define I830_FENCE_REG_VALID (1<<0) | 191 | #define I830_FENCE_REG_VALID (1<<0) |
| 192 | 192 | ||
| 193 | #define I915_FENCE_START_MASK 0x0ff00000 | 193 | #define I915_FENCE_START_MASK 0x0ff00000 |
| 194 | #define I915_FENCE_SIZE_BITS(size) ((get_order(size >> 20) - 1) << 8) | 194 | #define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8) |
| 195 | 195 | ||
| 196 | #define FENCE_REG_965_0 0x03000 | 196 | #define FENCE_REG_965_0 0x03000 |
| 197 | #define I965_FENCE_PITCH_SHIFT 2 | 197 | #define I965_FENCE_PITCH_SHIFT 2 |
| @@ -1371,6 +1371,9 @@ | |||
| 1371 | #define PIPE_FRAME_LOW_SHIFT 24 | 1371 | #define PIPE_FRAME_LOW_SHIFT 24 |
| 1372 | #define PIPE_PIXEL_MASK 0x00ffffff | 1372 | #define PIPE_PIXEL_MASK 0x00ffffff |
| 1373 | #define PIPE_PIXEL_SHIFT 0 | 1373 | #define PIPE_PIXEL_SHIFT 0 |
| 1374 | /* GM45+ just has to be different */ | ||
| 1375 | #define PIPEA_FRMCOUNT_GM45 0x70040 | ||
| 1376 | #define PIPEA_FLIPCOUNT_GM45 0x70044 | ||
| 1374 | 1377 | ||
| 1375 | /* Cursor A & B regs */ | 1378 | /* Cursor A & B regs */ |
| 1376 | #define CURACNTR 0x70080 | 1379 | #define CURACNTR 0x70080 |
| @@ -1439,6 +1442,9 @@ | |||
| 1439 | #define PIPEBSTAT 0x71024 | 1442 | #define PIPEBSTAT 0x71024 |
| 1440 | #define PIPEBFRAMEHIGH 0x71040 | 1443 | #define PIPEBFRAMEHIGH 0x71040 |
| 1441 | #define PIPEBFRAMEPIXEL 0x71044 | 1444 | #define PIPEBFRAMEPIXEL 0x71044 |
| 1445 | #define PIPEB_FRMCOUNT_GM45 0x71040 | ||
| 1446 | #define PIPEB_FLIPCOUNT_GM45 0x71044 | ||
| 1447 | |||
| 1442 | 1448 | ||
| 1443 | /* Display B control */ | 1449 | /* Display B control */ |
| 1444 | #define DSPBCNTR 0x71180 | 1450 | #define DSPBCNTR 0x71180 |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 31c3732b7a69..bbdd72909a11 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -755,6 +755,8 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 755 | case INTEL_OUTPUT_SDVO: | 755 | case INTEL_OUTPUT_SDVO: |
| 756 | case INTEL_OUTPUT_HDMI: | 756 | case INTEL_OUTPUT_HDMI: |
| 757 | is_sdvo = true; | 757 | is_sdvo = true; |
| 758 | if (intel_output->needs_tv_clock) | ||
| 759 | is_tv = true; | ||
| 758 | break; | 760 | break; |
| 759 | case INTEL_OUTPUT_DVO: | 761 | case INTEL_OUTPUT_DVO: |
| 760 | is_dvo = true; | 762 | is_dvo = true; |
| @@ -1452,6 +1454,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask) | |||
| 1452 | 1454 | ||
| 1453 | static void intel_setup_outputs(struct drm_device *dev) | 1455 | static void intel_setup_outputs(struct drm_device *dev) |
| 1454 | { | 1456 | { |
| 1457 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1455 | struct drm_connector *connector; | 1458 | struct drm_connector *connector; |
| 1456 | 1459 | ||
| 1457 | intel_crt_init(dev); | 1460 | intel_crt_init(dev); |
| @@ -1463,13 +1466,16 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 1463 | if (IS_I9XX(dev)) { | 1466 | if (IS_I9XX(dev)) { |
| 1464 | int found; | 1467 | int found; |
| 1465 | 1468 | ||
| 1466 | found = intel_sdvo_init(dev, SDVOB); | 1469 | if (I915_READ(SDVOB) & SDVO_DETECTED) { |
| 1467 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 1470 | found = intel_sdvo_init(dev, SDVOB); |
| 1468 | intel_hdmi_init(dev, SDVOB); | 1471 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
| 1469 | 1472 | intel_hdmi_init(dev, SDVOB); | |
| 1470 | found = intel_sdvo_init(dev, SDVOC); | 1473 | } |
| 1471 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 1474 | if (!IS_G4X(dev) || (I915_READ(SDVOB) & SDVO_DETECTED)) { |
| 1472 | intel_hdmi_init(dev, SDVOC); | 1475 | found = intel_sdvo_init(dev, SDVOC); |
| 1476 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | ||
| 1477 | intel_hdmi_init(dev, SDVOC); | ||
| 1478 | } | ||
| 1473 | } else | 1479 | } else |
| 1474 | intel_dvo_init(dev); | 1480 | intel_dvo_init(dev); |
| 1475 | 1481 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8a4cc50c5b4e..957daef8edff 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -82,6 +82,7 @@ struct intel_output { | |||
| 82 | struct intel_i2c_chan *i2c_bus; /* for control functions */ | 82 | struct intel_i2c_chan *i2c_bus; /* for control functions */ |
| 83 | struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ | 83 | struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ |
| 84 | bool load_detect_temp; | 84 | bool load_detect_temp; |
| 85 | bool needs_tv_clock; | ||
| 85 | void *dev_priv; | 86 | void *dev_priv; |
| 86 | }; | 87 | }; |
| 87 | 88 | ||
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b36a5214d8df..6d4f91265354 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | * Jesse Barnes <jesse.barnes@intel.com> | 27 | * Jesse Barnes <jesse.barnes@intel.com> |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/dmi.h> | ||
| 30 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
| 31 | #include "drmP.h" | 32 | #include "drmP.h" |
| 32 | #include "drm.h" | 33 | #include "drm.h" |
| @@ -311,10 +312,8 @@ static int intel_lvds_get_modes(struct drm_connector *connector) | |||
| 311 | if (dev_priv->panel_fixed_mode != NULL) { | 312 | if (dev_priv->panel_fixed_mode != NULL) { |
| 312 | struct drm_display_mode *mode; | 313 | struct drm_display_mode *mode; |
| 313 | 314 | ||
| 314 | mutex_lock(&dev->mode_config.mutex); | ||
| 315 | mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); | 315 | mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode); |
| 316 | drm_mode_probed_add(connector, mode); | 316 | drm_mode_probed_add(connector, mode); |
| 317 | mutex_unlock(&dev->mode_config.mutex); | ||
| 318 | 317 | ||
| 319 | return 1; | 318 | return 1; |
| 320 | } | 319 | } |
| @@ -405,6 +404,16 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 405 | u32 lvds; | 404 | u32 lvds; |
| 406 | int pipe; | 405 | int pipe; |
| 407 | 406 | ||
| 407 | /* Blacklist machines that we know falsely report LVDS. */ | ||
| 408 | /* FIXME: add a check for the Aopen Mini PC */ | ||
| 409 | |||
| 410 | /* Apple Mac Mini Core Duo and Mac Mini Core 2 Duo */ | ||
| 411 | if(dmi_match(DMI_PRODUCT_NAME, "Macmini1,1") || | ||
| 412 | dmi_match(DMI_PRODUCT_NAME, "Macmini2,1")) { | ||
| 413 | DRM_DEBUG("Skipping LVDS initialization for Apple Mac Mini\n"); | ||
| 414 | return; | ||
| 415 | } | ||
| 416 | |||
| 408 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 417 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); |
| 409 | if (!intel_output) { | 418 | if (!intel_output) { |
| 410 | return; | 419 | return; |
| @@ -458,7 +467,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 458 | dev_priv->panel_fixed_mode = | 467 | dev_priv->panel_fixed_mode = |
| 459 | drm_mode_duplicate(dev, scan); | 468 | drm_mode_duplicate(dev, scan); |
| 460 | mutex_unlock(&dev->mode_config.mutex); | 469 | mutex_unlock(&dev->mode_config.mutex); |
| 461 | goto out; /* FIXME: check for quirks */ | 470 | goto out; |
| 462 | } | 471 | } |
| 463 | mutex_unlock(&dev->mode_config.mutex); | 472 | mutex_unlock(&dev->mode_config.mutex); |
| 464 | } | 473 | } |
| @@ -492,7 +501,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 492 | if (dev_priv->panel_fixed_mode) { | 501 | if (dev_priv->panel_fixed_mode) { |
| 493 | dev_priv->panel_fixed_mode->type |= | 502 | dev_priv->panel_fixed_mode->type |= |
| 494 | DRM_MODE_TYPE_PREFERRED; | 503 | DRM_MODE_TYPE_PREFERRED; |
| 495 | goto out; /* FIXME: check for quirks */ | 504 | goto out; |
| 496 | } | 505 | } |
| 497 | } | 506 | } |
| 498 | 507 | ||
| @@ -500,38 +509,6 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 500 | if (!dev_priv->panel_fixed_mode) | 509 | if (!dev_priv->panel_fixed_mode) |
| 501 | goto failed; | 510 | goto failed; |
| 502 | 511 | ||
| 503 | /* FIXME: detect aopen & mac mini type stuff automatically? */ | ||
| 504 | /* | ||
| 505 | * Blacklist machines with BIOSes that list an LVDS panel without | ||
| 506 | * actually having one. | ||
| 507 | */ | ||
| 508 | if (IS_I945GM(dev)) { | ||
| 509 | /* aopen mini pc */ | ||
| 510 | if (dev->pdev->subsystem_vendor == 0xa0a0) | ||
| 511 | goto failed; | ||
| 512 | |||
| 513 | if ((dev->pdev->subsystem_vendor == 0x8086) && | ||
| 514 | (dev->pdev->subsystem_device == 0x7270)) { | ||
| 515 | /* It's a Mac Mini or Macbook Pro. | ||
| 516 | * | ||
| 517 | * Apple hardware is out to get us. The macbook pro | ||
| 518 | * has a real LVDS panel, but the mac mini does not, | ||
| 519 | * and they have the same device IDs. We'll | ||
| 520 | * distinguish by panel size, on the assumption | ||
| 521 | * that Apple isn't about to make any machines with an | ||
| 522 | * 800x600 display. | ||
| 523 | */ | ||
| 524 | |||
| 525 | if (dev_priv->panel_fixed_mode != NULL && | ||
| 526 | dev_priv->panel_fixed_mode->hdisplay == 800 && | ||
| 527 | dev_priv->panel_fixed_mode->vdisplay == 600) { | ||
| 528 | DRM_DEBUG("Suspected Mac Mini, ignoring the LVDS\n"); | ||
| 529 | goto failed; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | } | ||
| 533 | |||
| 534 | |||
| 535 | out: | 512 | out: |
| 536 | drm_sysfs_connector_add(connector); | 513 | drm_sysfs_connector_add(connector); |
| 537 | return; | 514 | return; |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 407215469102..a30508b639ba 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; |
| @@ -148,8 +194,8 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | |||
| 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 | const static 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 | ||
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 861a43f8693c..1117b9c151a6 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h | |||
| @@ -173,6 +173,9 @@ struct intel_sdvo_get_trained_inputs_response { | |||
| 173 | * Returns two struct intel_sdvo_output_flags structures. | 173 | * Returns two struct intel_sdvo_output_flags structures. |
| 174 | */ | 174 | */ |
| 175 | #define SDVO_CMD_GET_IN_OUT_MAP 0x06 | 175 | #define SDVO_CMD_GET_IN_OUT_MAP 0x06 |
| 176 | struct intel_sdvo_in_out_map { | ||
| 177 | u16 in0, in1; | ||
| 178 | }; | ||
| 176 | 179 | ||
| 177 | /** | 180 | /** |
| 178 | * Sets the current mapping of SDVO inputs to outputs on the device. | 181 | * Sets the current mapping of SDVO inputs to outputs on the device. |
| @@ -206,7 +209,8 @@ struct intel_sdvo_get_trained_inputs_response { | |||
| 206 | struct intel_sdvo_get_interrupt_event_source_response { | 209 | struct intel_sdvo_get_interrupt_event_source_response { |
| 207 | u16 interrupt_status; | 210 | u16 interrupt_status; |
| 208 | unsigned int ambient_light_interrupt:1; | 211 | unsigned int ambient_light_interrupt:1; |
| 209 | unsigned int pad:7; | 212 | unsigned int hdmi_audio_encrypt_change:1; |
| 213 | unsigned int pad:6; | ||
| 210 | } __attribute__((packed)); | 214 | } __attribute__((packed)); |
| 211 | 215 | ||
| 212 | /** | 216 | /** |
| @@ -305,23 +309,411 @@ struct intel_sdvo_set_target_input_args { | |||
| 305 | # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) | 309 | # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) |
| 306 | 310 | ||
| 307 | #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 | 311 | #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 |
| 312 | /** 5 bytes of bit flags for TV formats shared by all TV format functions */ | ||
| 313 | struct intel_sdvo_tv_format { | ||
| 314 | unsigned int ntsc_m:1; | ||
| 315 | unsigned int ntsc_j:1; | ||
| 316 | unsigned int ntsc_443:1; | ||
| 317 | unsigned int pal_b:1; | ||
| 318 | unsigned int pal_d:1; | ||
| 319 | unsigned int pal_g:1; | ||
| 320 | unsigned int pal_h:1; | ||
| 321 | unsigned int pal_i:1; | ||
| 322 | |||
| 323 | unsigned int pal_m:1; | ||
| 324 | unsigned int pal_n:1; | ||
| 325 | unsigned int pal_nc:1; | ||
| 326 | unsigned int pal_60:1; | ||
| 327 | unsigned int secam_b:1; | ||
| 328 | unsigned int secam_d:1; | ||
| 329 | unsigned int secam_g:1; | ||
| 330 | unsigned int secam_k:1; | ||
| 331 | |||
| 332 | unsigned int secam_k1:1; | ||
| 333 | unsigned int secam_l:1; | ||
| 334 | unsigned int secam_60:1; | ||
| 335 | unsigned int hdtv_std_smpte_240m_1080i_59:1; | ||
| 336 | unsigned int hdtv_std_smpte_240m_1080i_60:1; | ||
| 337 | unsigned int hdtv_std_smpte_260m_1080i_59:1; | ||
| 338 | unsigned int hdtv_std_smpte_260m_1080i_60:1; | ||
| 339 | unsigned int hdtv_std_smpte_274m_1080i_50:1; | ||
| 340 | |||
| 341 | unsigned int hdtv_std_smpte_274m_1080i_59:1; | ||
| 342 | unsigned int hdtv_std_smpte_274m_1080i_60:1; | ||
| 343 | unsigned int hdtv_std_smpte_274m_1080p_23:1; | ||
| 344 | unsigned int hdtv_std_smpte_274m_1080p_24:1; | ||
| 345 | unsigned int hdtv_std_smpte_274m_1080p_25:1; | ||
| 346 | unsigned int hdtv_std_smpte_274m_1080p_29:1; | ||
| 347 | unsigned int hdtv_std_smpte_274m_1080p_30:1; | ||
| 348 | unsigned int hdtv_std_smpte_274m_1080p_50:1; | ||
| 349 | |||
| 350 | unsigned int hdtv_std_smpte_274m_1080p_59:1; | ||
| 351 | unsigned int hdtv_std_smpte_274m_1080p_60:1; | ||
| 352 | unsigned int hdtv_std_smpte_295m_1080i_50:1; | ||
| 353 | unsigned int hdtv_std_smpte_295m_1080p_50:1; | ||
| 354 | unsigned int hdtv_std_smpte_296m_720p_59:1; | ||
| 355 | unsigned int hdtv_std_smpte_296m_720p_60:1; | ||
| 356 | unsigned int hdtv_std_smpte_296m_720p_50:1; | ||
| 357 | unsigned int hdtv_std_smpte_293m_480p_59:1; | ||
| 358 | |||
| 359 | unsigned int hdtv_std_smpte_170m_480i_59:1; | ||
| 360 | unsigned int hdtv_std_iturbt601_576i_50:1; | ||
| 361 | unsigned int hdtv_std_iturbt601_576p_50:1; | ||
| 362 | unsigned int hdtv_std_eia_7702a_480i_60:1; | ||
| 363 | unsigned int hdtv_std_eia_7702a_480p_60:1; | ||
| 364 | unsigned int pad:3; | ||
| 365 | } __attribute__((packed)); | ||
| 308 | 366 | ||
| 309 | #define SDVO_CMD_GET_TV_FORMAT 0x28 | 367 | #define SDVO_CMD_GET_TV_FORMAT 0x28 |
| 310 | 368 | ||
| 311 | #define SDVO_CMD_SET_TV_FORMAT 0x29 | 369 | #define SDVO_CMD_SET_TV_FORMAT 0x29 |
| 312 | 370 | ||
| 371 | /** Returns the resolutiosn that can be used with the given TV format */ | ||
| 372 | #define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83 | ||
| 373 | struct intel_sdvo_sdtv_resolution_request { | ||
| 374 | unsigned int ntsc_m:1; | ||
| 375 | unsigned int ntsc_j:1; | ||
| 376 | unsigned int ntsc_443:1; | ||
| 377 | unsigned int pal_b:1; | ||
| 378 | unsigned int pal_d:1; | ||
| 379 | unsigned int pal_g:1; | ||
| 380 | unsigned int pal_h:1; | ||
| 381 | unsigned int pal_i:1; | ||
| 382 | |||
| 383 | unsigned int pal_m:1; | ||
| 384 | unsigned int pal_n:1; | ||
| 385 | unsigned int pal_nc:1; | ||
| 386 | unsigned int pal_60:1; | ||
| 387 | unsigned int secam_b:1; | ||
| 388 | unsigned int secam_d:1; | ||
| 389 | unsigned int secam_g:1; | ||
| 390 | unsigned int secam_k:1; | ||
| 391 | |||
| 392 | unsigned int secam_k1:1; | ||
| 393 | unsigned int secam_l:1; | ||
| 394 | unsigned int secam_60:1; | ||
| 395 | unsigned int pad:5; | ||
| 396 | } __attribute__((packed)); | ||
| 397 | |||
| 398 | struct intel_sdvo_sdtv_resolution_reply { | ||
| 399 | unsigned int res_320x200:1; | ||
| 400 | unsigned int res_320x240:1; | ||
| 401 | unsigned int res_400x300:1; | ||
| 402 | unsigned int res_640x350:1; | ||
| 403 | unsigned int res_640x400:1; | ||
| 404 | unsigned int res_640x480:1; | ||
| 405 | unsigned int res_704x480:1; | ||
| 406 | unsigned int res_704x576:1; | ||
| 407 | |||
| 408 | unsigned int res_720x350:1; | ||
| 409 | unsigned int res_720x400:1; | ||
| 410 | unsigned int res_720x480:1; | ||
| 411 | unsigned int res_720x540:1; | ||
| 412 | unsigned int res_720x576:1; | ||
| 413 | unsigned int res_768x576:1; | ||
| 414 | unsigned int res_800x600:1; | ||
| 415 | unsigned int res_832x624:1; | ||
| 416 | |||
| 417 | unsigned int res_920x766:1; | ||
| 418 | unsigned int res_1024x768:1; | ||
| 419 | unsigned int res_1280x1024:1; | ||
| 420 | unsigned int pad:5; | ||
| 421 | } __attribute__((packed)); | ||
| 422 | |||
| 423 | /* Get supported resolution with squire pixel aspect ratio that can be | ||
| 424 | scaled for the requested HDTV format */ | ||
| 425 | #define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85 | ||
| 426 | |||
| 427 | struct intel_sdvo_hdtv_resolution_request { | ||
| 428 | unsigned int hdtv_std_smpte_240m_1080i_59:1; | ||
| 429 | unsigned int hdtv_std_smpte_240m_1080i_60:1; | ||
| 430 | unsigned int hdtv_std_smpte_260m_1080i_59:1; | ||
| 431 | unsigned int hdtv_std_smpte_260m_1080i_60:1; | ||
| 432 | unsigned int hdtv_std_smpte_274m_1080i_50:1; | ||
| 433 | unsigned int hdtv_std_smpte_274m_1080i_59:1; | ||
| 434 | unsigned int hdtv_std_smpte_274m_1080i_60:1; | ||
| 435 | unsigned int hdtv_std_smpte_274m_1080p_23:1; | ||
| 436 | |||
| 437 | unsigned int hdtv_std_smpte_274m_1080p_24:1; | ||
| 438 | unsigned int hdtv_std_smpte_274m_1080p_25:1; | ||
| 439 | unsigned int hdtv_std_smpte_274m_1080p_29:1; | ||
| 440 | unsigned int hdtv_std_smpte_274m_1080p_30:1; | ||
| 441 | unsigned int hdtv_std_smpte_274m_1080p_50:1; | ||
| 442 | unsigned int hdtv_std_smpte_274m_1080p_59:1; | ||
| 443 | unsigned int hdtv_std_smpte_274m_1080p_60:1; | ||
| 444 | unsigned int hdtv_std_smpte_295m_1080i_50:1; | ||
| 445 | |||
| 446 | unsigned int hdtv_std_smpte_295m_1080p_50:1; | ||
| 447 | unsigned int hdtv_std_smpte_296m_720p_59:1; | ||
| 448 | unsigned int hdtv_std_smpte_296m_720p_60:1; | ||
| 449 | unsigned int hdtv_std_smpte_296m_720p_50:1; | ||
| 450 | unsigned int hdtv_std_smpte_293m_480p_59:1; | ||
| 451 | unsigned int hdtv_std_smpte_170m_480i_59:1; | ||
| 452 | unsigned int hdtv_std_iturbt601_576i_50:1; | ||
| 453 | unsigned int hdtv_std_iturbt601_576p_50:1; | ||
| 454 | |||
| 455 | unsigned int hdtv_std_eia_7702a_480i_60:1; | ||
| 456 | unsigned int hdtv_std_eia_7702a_480p_60:1; | ||
| 457 | unsigned int pad:6; | ||
| 458 | } __attribute__((packed)); | ||
| 459 | |||
| 460 | struct intel_sdvo_hdtv_resolution_reply { | ||
| 461 | unsigned int res_640x480:1; | ||
| 462 | unsigned int res_800x600:1; | ||
| 463 | unsigned int res_1024x768:1; | ||
| 464 | unsigned int res_1280x960:1; | ||
| 465 | unsigned int res_1400x1050:1; | ||
| 466 | unsigned int res_1600x1200:1; | ||
| 467 | unsigned int res_1920x1440:1; | ||
| 468 | unsigned int res_2048x1536:1; | ||
| 469 | |||
| 470 | unsigned int res_2560x1920:1; | ||
| 471 | unsigned int res_3200x2400:1; | ||
| 472 | unsigned int res_3840x2880:1; | ||
| 473 | unsigned int pad1:5; | ||
| 474 | |||
| 475 | unsigned int res_848x480:1; | ||
| 476 | unsigned int res_1064x600:1; | ||
| 477 | unsigned int res_1280x720:1; | ||
| 478 | unsigned int res_1360x768:1; | ||
| 479 | unsigned int res_1704x960:1; | ||
| 480 | unsigned int res_1864x1050:1; | ||
| 481 | unsigned int res_1920x1080:1; | ||
| 482 | unsigned int res_2128x1200:1; | ||
| 483 | |||
| 484 | unsigned int res_2560x1400:1; | ||
| 485 | unsigned int res_2728x1536:1; | ||
| 486 | unsigned int res_3408x1920:1; | ||
| 487 | unsigned int res_4264x2400:1; | ||
| 488 | unsigned int res_5120x2880:1; | ||
| 489 | unsigned int pad2:3; | ||
| 490 | |||
| 491 | unsigned int res_768x480:1; | ||
| 492 | unsigned int res_960x600:1; | ||
| 493 | unsigned int res_1152x720:1; | ||
| 494 | unsigned int res_1124x768:1; | ||
| 495 | unsigned int res_1536x960:1; | ||
| 496 | unsigned int res_1680x1050:1; | ||
| 497 | unsigned int res_1728x1080:1; | ||
| 498 | unsigned int res_1920x1200:1; | ||
| 499 | |||
| 500 | unsigned int res_2304x1440:1; | ||
| 501 | unsigned int res_2456x1536:1; | ||
| 502 | unsigned int res_3072x1920:1; | ||
| 503 | unsigned int res_3840x2400:1; | ||
| 504 | unsigned int res_4608x2880:1; | ||
| 505 | unsigned int pad3:3; | ||
| 506 | |||
| 507 | unsigned int res_1280x1024:1; | ||
| 508 | unsigned int pad4:7; | ||
| 509 | |||
| 510 | unsigned int res_1280x768:1; | ||
| 511 | unsigned int pad5:7; | ||
| 512 | } __attribute__((packed)); | ||
| 513 | |||
| 514 | /* Get supported power state returns info for encoder and monitor, rely on | ||
| 515 | last SetTargetInput and SetTargetOutput calls */ | ||
| 313 | #define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a | 516 | #define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a |
| 517 | /* Get power state returns info for encoder and monitor, rely on last | ||
| 518 | SetTargetInput and SetTargetOutput calls */ | ||
| 519 | #define SDVO_CMD_GET_POWER_STATE 0x2b | ||
| 314 | #define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b | 520 | #define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b |
| 315 | #define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c | 521 | #define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c |
| 316 | # define SDVO_ENCODER_STATE_ON (1 << 0) | 522 | # define SDVO_ENCODER_STATE_ON (1 << 0) |
| 317 | # define SDVO_ENCODER_STATE_STANDBY (1 << 1) | 523 | # define SDVO_ENCODER_STATE_STANDBY (1 << 1) |
| 318 | # define SDVO_ENCODER_STATE_SUSPEND (1 << 2) | 524 | # define SDVO_ENCODER_STATE_SUSPEND (1 << 2) |
| 319 | # define SDVO_ENCODER_STATE_OFF (1 << 3) | 525 | # define SDVO_ENCODER_STATE_OFF (1 << 3) |
| 526 | # define SDVO_MONITOR_STATE_ON (1 << 4) | ||
| 527 | # define SDVO_MONITOR_STATE_STANDBY (1 << 5) | ||
| 528 | # define SDVO_MONITOR_STATE_SUSPEND (1 << 6) | ||
| 529 | # define SDVO_MONITOR_STATE_OFF (1 << 7) | ||
| 530 | |||
| 531 | #define SDVO_CMD_GET_MAX_PANEL_POWER_SEQUENCING 0x2d | ||
| 532 | #define SDVO_CMD_GET_PANEL_POWER_SEQUENCING 0x2e | ||
| 533 | #define SDVO_CMD_SET_PANEL_POWER_SEQUENCING 0x2f | ||
| 534 | /** | ||
| 535 | * The panel power sequencing parameters are in units of milliseconds. | ||
| 536 | * The high fields are bits 8:9 of the 10-bit values. | ||
| 537 | */ | ||
| 538 | struct sdvo_panel_power_sequencing { | ||
| 539 | u8 t0; | ||
| 540 | u8 t1; | ||
| 541 | u8 t2; | ||
| 542 | u8 t3; | ||
| 543 | u8 t4; | ||
| 544 | |||
| 545 | unsigned int t0_high:2; | ||
| 546 | unsigned int t1_high:2; | ||
| 547 | unsigned int t2_high:2; | ||
| 548 | unsigned int t3_high:2; | ||
| 549 | |||
| 550 | unsigned int t4_high:2; | ||
| 551 | unsigned int pad:6; | ||
| 552 | } __attribute__((packed)); | ||
| 553 | |||
| 554 | #define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30 | ||
| 555 | struct sdvo_max_backlight_reply { | ||
| 556 | u8 max_value; | ||
| 557 | u8 default_value; | ||
| 558 | } __attribute__((packed)); | ||
| 559 | |||
| 560 | #define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31 | ||
| 561 | #define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32 | ||
| 562 | |||
| 563 | #define SDVO_CMD_GET_AMBIENT_LIGHT 0x33 | ||
| 564 | struct sdvo_get_ambient_light_reply { | ||
| 565 | u16 trip_low; | ||
| 566 | u16 trip_high; | ||
| 567 | u16 value; | ||
| 568 | } __attribute__((packed)); | ||
| 569 | #define SDVO_CMD_SET_AMBIENT_LIGHT 0x34 | ||
| 570 | struct sdvo_set_ambient_light_reply { | ||
| 571 | u16 trip_low; | ||
| 572 | u16 trip_high; | ||
| 573 | unsigned int enable:1; | ||
| 574 | unsigned int pad:7; | ||
| 575 | } __attribute__((packed)); | ||
| 576 | |||
| 577 | /* Set display power state */ | ||
| 578 | #define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d | ||
| 579 | # define SDVO_DISPLAY_STATE_ON (1 << 0) | ||
| 580 | # define SDVO_DISPLAY_STATE_STANDBY (1 << 1) | ||
| 581 | # define SDVO_DISPLAY_STATE_SUSPEND (1 << 2) | ||
| 582 | # define SDVO_DISPLAY_STATE_OFF (1 << 3) | ||
| 583 | |||
| 584 | #define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84 | ||
| 585 | struct intel_sdvo_enhancements_reply { | ||
| 586 | unsigned int flicker_filter:1; | ||
| 587 | unsigned int flicker_filter_adaptive:1; | ||
| 588 | unsigned int flicker_filter_2d:1; | ||
| 589 | unsigned int saturation:1; | ||
| 590 | unsigned int hue:1; | ||
| 591 | unsigned int brightness:1; | ||
| 592 | unsigned int contrast:1; | ||
| 593 | unsigned int overscan_h:1; | ||
| 594 | |||
| 595 | unsigned int overscan_v:1; | ||
| 596 | unsigned int position_h:1; | ||
| 597 | unsigned int position_v:1; | ||
| 598 | unsigned int sharpness:1; | ||
| 599 | unsigned int dot_crawl:1; | ||
| 600 | unsigned int dither:1; | ||
| 601 | unsigned int max_tv_chroma_filter:1; | ||
| 602 | unsigned int max_tv_luma_filter:1; | ||
| 603 | } __attribute__((packed)); | ||
| 604 | |||
| 605 | /* Picture enhancement limits below are dependent on the current TV format, | ||
| 606 | * and thus need to be queried and set after it. | ||
| 607 | */ | ||
| 608 | #define SDVO_CMD_GET_MAX_FLICKER_FITER 0x4d | ||
| 609 | #define SDVO_CMD_GET_MAX_ADAPTIVE_FLICKER_FITER 0x7b | ||
| 610 | #define SDVO_CMD_GET_MAX_2D_FLICKER_FITER 0x52 | ||
| 611 | #define SDVO_CMD_GET_MAX_SATURATION 0x55 | ||
| 612 | #define SDVO_CMD_GET_MAX_HUE 0x58 | ||
| 613 | #define SDVO_CMD_GET_MAX_BRIGHTNESS 0x5b | ||
| 614 | #define SDVO_CMD_GET_MAX_CONTRAST 0x5e | ||
| 615 | #define SDVO_CMD_GET_MAX_OVERSCAN_H 0x61 | ||
| 616 | #define SDVO_CMD_GET_MAX_OVERSCAN_V 0x64 | ||
| 617 | #define SDVO_CMD_GET_MAX_POSITION_H 0x67 | ||
| 618 | #define SDVO_CMD_GET_MAX_POSITION_V 0x6a | ||
| 619 | #define SDVO_CMD_GET_MAX_SHARPNESS_V 0x6d | ||
| 620 | #define SDVO_CMD_GET_MAX_TV_CHROMA 0x74 | ||
| 621 | #define SDVO_CMD_GET_MAX_TV_LUMA 0x77 | ||
| 622 | struct intel_sdvo_enhancement_limits_reply { | ||
| 623 | u16 max_value; | ||
| 624 | u16 default_value; | ||
| 625 | } __attribute__((packed)); | ||
| 320 | 626 | ||
| 321 | #define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93 | 627 | #define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f |
| 628 | #define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80 | ||
| 629 | # define SDVO_LVDS_COLOR_DEPTH_18 (0 << 0) | ||
| 630 | # define SDVO_LVDS_COLOR_DEPTH_24 (1 << 0) | ||
| 631 | # define SDVO_LVDS_CONNECTOR_SPWG (0 << 2) | ||
| 632 | # define SDVO_LVDS_CONNECTOR_OPENLDI (1 << 2) | ||
| 633 | # define SDVO_LVDS_SINGLE_CHANNEL (0 << 4) | ||
| 634 | # define SDVO_LVDS_DUAL_CHANNEL (1 << 4) | ||
| 635 | |||
| 636 | #define SDVO_CMD_GET_FLICKER_FILTER 0x4e | ||
| 637 | #define SDVO_CMD_SET_FLICKER_FILTER 0x4f | ||
| 638 | #define SDVO_CMD_GET_ADAPTIVE_FLICKER_FITER 0x50 | ||
| 639 | #define SDVO_CMD_SET_ADAPTIVE_FLICKER_FITER 0x51 | ||
| 640 | #define SDVO_CMD_GET_2D_FLICKER_FITER 0x53 | ||
| 641 | #define SDVO_CMD_SET_2D_FLICKER_FITER 0x54 | ||
| 642 | #define SDVO_CMD_GET_SATURATION 0x56 | ||
| 643 | #define SDVO_CMD_SET_SATURATION 0x57 | ||
| 644 | #define SDVO_CMD_GET_HUE 0x59 | ||
| 645 | #define SDVO_CMD_SET_HUE 0x5a | ||
| 646 | #define SDVO_CMD_GET_BRIGHTNESS 0x5c | ||
| 647 | #define SDVO_CMD_SET_BRIGHTNESS 0x5d | ||
| 648 | #define SDVO_CMD_GET_CONTRAST 0x5f | ||
| 649 | #define SDVO_CMD_SET_CONTRAST 0x60 | ||
| 650 | #define SDVO_CMD_GET_OVERSCAN_H 0x62 | ||
| 651 | #define SDVO_CMD_SET_OVERSCAN_H 0x63 | ||
| 652 | #define SDVO_CMD_GET_OVERSCAN_V 0x65 | ||
| 653 | #define SDVO_CMD_SET_OVERSCAN_V 0x66 | ||
| 654 | #define SDVO_CMD_GET_POSITION_H 0x68 | ||
| 655 | #define SDVO_CMD_SET_POSITION_H 0x69 | ||
| 656 | #define SDVO_CMD_GET_POSITION_V 0x6b | ||
| 657 | #define SDVO_CMD_SET_POSITION_V 0x6c | ||
| 658 | #define SDVO_CMD_GET_SHARPNESS 0x6e | ||
| 659 | #define SDVO_CMD_SET_SHARPNESS 0x6f | ||
| 660 | #define SDVO_CMD_GET_TV_CHROMA 0x75 | ||
| 661 | #define SDVO_CMD_SET_TV_CHROMA 0x76 | ||
| 662 | #define SDVO_CMD_GET_TV_LUMA 0x78 | ||
| 663 | #define SDVO_CMD_SET_TV_LUMA 0x79 | ||
| 664 | struct intel_sdvo_enhancements_arg { | ||
| 665 | u16 value; | ||
| 666 | }__attribute__((packed)); | ||
| 667 | |||
| 668 | #define SDVO_CMD_GET_DOT_CRAWL 0x70 | ||
| 669 | #define SDVO_CMD_SET_DOT_CRAWL 0x71 | ||
| 670 | # define SDVO_DOT_CRAWL_ON (1 << 0) | ||
| 671 | # define SDVO_DOT_CRAWL_DEFAULT_ON (1 << 1) | ||
| 672 | |||
| 673 | #define SDVO_CMD_GET_DITHER 0x72 | ||
| 674 | #define SDVO_CMD_SET_DITHER 0x73 | ||
| 675 | # define SDVO_DITHER_ON (1 << 0) | ||
| 676 | # define SDVO_DITHER_DEFAULT_ON (1 << 1) | ||
| 322 | 677 | ||
| 323 | #define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a | 678 | #define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a |
| 324 | # define SDVO_CONTROL_BUS_PROM 0x0 | 679 | # define SDVO_CONTROL_BUS_PROM (1 << 0) |
| 325 | # define SDVO_CONTROL_BUS_DDC1 0x1 | 680 | # define SDVO_CONTROL_BUS_DDC1 (1 << 1) |
| 326 | # define SDVO_CONTROL_BUS_DDC2 0x2 | 681 | # define SDVO_CONTROL_BUS_DDC2 (1 << 2) |
| 327 | # define SDVO_CONTROL_BUS_DDC3 0x3 | 682 | # define SDVO_CONTROL_BUS_DDC3 (1 << 3) |
| 683 | |||
| 684 | /* HDMI op codes */ | ||
| 685 | #define SDVO_CMD_GET_SUPP_ENCODE 0x9d | ||
| 686 | #define SDVO_CMD_GET_ENCODE 0x9e | ||
| 687 | #define SDVO_CMD_SET_ENCODE 0x9f | ||
| 688 | #define SDVO_ENCODE_DVI 0x0 | ||
| 689 | #define SDVO_ENCODE_HDMI 0x1 | ||
| 690 | #define SDVO_CMD_SET_PIXEL_REPLI 0x8b | ||
| 691 | #define SDVO_CMD_GET_PIXEL_REPLI 0x8c | ||
| 692 | #define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d | ||
| 693 | #define SDVO_CMD_SET_COLORIMETRY 0x8e | ||
| 694 | #define SDVO_COLORIMETRY_RGB256 0x0 | ||
| 695 | #define SDVO_COLORIMETRY_RGB220 0x1 | ||
| 696 | #define SDVO_COLORIMETRY_YCrCb422 0x3 | ||
| 697 | #define SDVO_COLORIMETRY_YCrCb444 0x4 | ||
| 698 | #define SDVO_CMD_GET_COLORIMETRY 0x8f | ||
| 699 | #define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90 | ||
| 700 | #define SDVO_CMD_SET_AUDIO_STAT 0x91 | ||
| 701 | #define SDVO_CMD_GET_AUDIO_STAT 0x92 | ||
| 702 | #define SDVO_CMD_SET_HBUF_INDEX 0x93 | ||
| 703 | #define SDVO_CMD_GET_HBUF_INDEX 0x94 | ||
| 704 | #define SDVO_CMD_GET_HBUF_INFO 0x95 | ||
| 705 | #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 | ||
| 706 | #define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97 | ||
| 707 | #define SDVO_CMD_SET_HBUF_DATA 0x98 | ||
| 708 | #define SDVO_CMD_GET_HBUF_DATA 0x99 | ||
| 709 | #define SDVO_CMD_SET_HBUF_TXRATE 0x9a | ||
| 710 | #define SDVO_CMD_GET_HBUF_TXRATE 0x9b | ||
| 711 | #define SDVO_HBUF_TX_DISABLED (0 << 6) | ||
| 712 | #define SDVO_HBUF_TX_ONCE (2 << 6) | ||
| 713 | #define SDVO_HBUF_TX_VSYNC (3 << 6) | ||
| 714 | #define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c | ||
| 715 | |||
| 716 | struct intel_sdvo_encode{ | ||
| 717 | u8 dvi_rev; | ||
| 718 | u8 hdmi_rev; | ||
| 719 | } __attribute__ ((packed)); | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 63212d7bbc28..df4cf97e5d97 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
| @@ -1039,9 +1039,9 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, | |||
| 1039 | 1039 | ||
| 1040 | #if __OS_HAS_AGP | 1040 | #if __OS_HAS_AGP |
| 1041 | if (dev_priv->flags & RADEON_IS_AGP) { | 1041 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1042 | drm_core_ioremap(dev_priv->cp_ring, dev); | 1042 | drm_core_ioremap_wc(dev_priv->cp_ring, dev); |
| 1043 | drm_core_ioremap(dev_priv->ring_rptr, dev); | 1043 | drm_core_ioremap_wc(dev_priv->ring_rptr, dev); |
| 1044 | drm_core_ioremap(dev->agp_buffer_map, dev); | 1044 | drm_core_ioremap_wc(dev->agp_buffer_map, dev); |
| 1045 | if (!dev_priv->cp_ring->handle || | 1045 | if (!dev_priv->cp_ring->handle || |
| 1046 | !dev_priv->ring_rptr->handle || | 1046 | !dev_priv->ring_rptr->handle || |
| 1047 | !dev->agp_buffer_map->handle) { | 1047 | !dev->agp_buffer_map->handle) { |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f0267706cb45..bf0af660df8a 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -1054,9 +1054,10 @@ config FB_RIVA_BACKLIGHT | |||
| 1054 | 1054 | ||
| 1055 | config FB_I810 | 1055 | config FB_I810 |
| 1056 | tristate "Intel 810/815 support (EXPERIMENTAL)" | 1056 | tristate "Intel 810/815 support (EXPERIMENTAL)" |
| 1057 | depends on FB && EXPERIMENTAL && PCI && X86_32 | 1057 | depends on EXPERIMENTAL && PCI && X86_32 |
| 1058 | select AGP | 1058 | select AGP |
| 1059 | select AGP_INTEL | 1059 | select AGP_INTEL |
| 1060 | select FB | ||
| 1060 | select FB_MODE_HELPERS | 1061 | select FB_MODE_HELPERS |
| 1061 | select FB_CFB_FILLRECT | 1062 | select FB_CFB_FILLRECT |
| 1062 | select FB_CFB_COPYAREA | 1063 | select FB_CFB_COPYAREA |
| @@ -1119,7 +1120,8 @@ config FB_CARILLO_RANCH | |||
| 1119 | 1120 | ||
| 1120 | config FB_INTEL | 1121 | config FB_INTEL |
| 1121 | tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)" | 1122 | tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)" |
| 1122 | depends on FB && EXPERIMENTAL && PCI && X86 | 1123 | depends on EXPERIMENTAL && PCI && X86 |
| 1124 | select FB | ||
| 1123 | select AGP | 1125 | select AGP |
| 1124 | select AGP_INTEL | 1126 | select AGP_INTEL |
| 1125 | select FB_MODE_HELPERS | 1127 | select FB_MODE_HELPERS |
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index b3bcf72dc656..912cd52db965 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h | |||
| @@ -261,6 +261,7 @@ typedef struct drm_i915_irq_wait { | |||
| 261 | #define I915_PARAM_LAST_DISPATCH 3 | 261 | #define I915_PARAM_LAST_DISPATCH 3 |
| 262 | #define I915_PARAM_CHIPSET_ID 4 | 262 | #define I915_PARAM_CHIPSET_ID 4 |
| 263 | #define I915_PARAM_HAS_GEM 5 | 263 | #define I915_PARAM_HAS_GEM 5 |
| 264 | #define I915_PARAM_NUM_FENCES_AVAIL 6 | ||
| 264 | 265 | ||
| 265 | typedef struct drm_i915_getparam { | 266 | typedef struct drm_i915_getparam { |
| 266 | int param; | 267 | int param; |
| @@ -272,6 +273,7 @@ typedef struct drm_i915_getparam { | |||
| 272 | #define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 | 273 | #define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1 |
| 273 | #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 | 274 | #define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 |
| 274 | #define I915_SETPARAM_ALLOW_BATCHBUFFER 3 | 275 | #define I915_SETPARAM_ALLOW_BATCHBUFFER 3 |
| 276 | #define I915_SETPARAM_NUM_USED_FENCES 4 | ||
| 275 | 277 | ||
| 276 | typedef struct drm_i915_setparam { | 278 | typedef struct drm_i915_setparam { |
| 277 | int param; | 279 | int param; |
